代码之家  ›  专栏  ›  技术社区  ›  BCS

为什么模板不能采用函数本地类型?

  •  6
  • BCS  · 技术社区  · 14 年前

    在C++中,有一个函数,它可以接受函数局部类型:

    int main() {
      struct S { static void M(const S& s) { } };
      S s;
      S::M(s);
    }
    

    template<typename T> void Foo(const T& t) { }
    
    int main() {
      struct S { } s;
      Foo(s);   // Line 5: error: no matching function for call to 'Foo(main()::S&)'
    }
    

    14.3.1 paragraph 2 in the c++ standard.

    没有链接[…]的类型不能用作模板类型参数的模板参数

    为什么C++不允许这样做?


    到目前为止,我听到的最好的解释是,内部类型没有链接,这可能意味着将它们作为arg的函数必须没有链接。但我没有理由认为模板实例化必须有链接。


    p、 请不要只是说 thats not allowed because the standard says it's not

    2 回复  |  直到 8 年前
        1
  •  3
  •   Walter Mundt    14 年前

    我猜这是因为它需要在函数的范围内有效地实例化模板,因为这是这些类型可见的地方。但是,同时,模板实例化应该像它们在定义模板的范围内一样工作。我相信这是有可能的,以某种方式处理,但如果我是对的,标准机构决定不把这个负担编译器作家。

    原因是类似的决定 vector<vector<int>> 根据标准是无效语法;检测构造需要编译器lexer和解析器阶段之间的一些交互。然而,这是在变化,因为C++的0x标准发现,所有编译器都在检测它,以发出错误的错误消息。

    我怀疑,如果要证明允许这种构造的实现是微不足道的,并且它不会在语言范围规则中引入任何歧义,那么有朝一日您可能会看到这里的标准也发生了变化。

        2
  •  7
  •   Jerry Coffin    14 年前

    我相信预见到的困难在于 Foo<T> 其实意思完全不同,因为 T

    要使其与本地类型一起工作,存储库不仅能够存储模板实例化时所使用的类型,而且还必须为实例化创建一个完整的类型“路径”。虽然这可能是可能的,但我认为这被视为一项额外的工作,几乎没有(如果有的话)真正的好处。

    从那时起,规则已经发生了足够的变化,编译器已经被要求做一些相当的事情,在不同的地方(包括跨tu)找到(并合并)相同类型的实例化,这样 foo<int> (例如)不要违反ODR。基于该实现,在C++(当前的草案)中放宽了限制(您仍然不能在本地类型上实例化模板类,但可以将局部类型作为模板函数使用参数)。