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

时间:2010-08-12 17:04:58

标签: c++ templates language-design

在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.S。请不要只说“thats not allowed because the standard says it's not

2 个答案:

答案 0 :(得分:7)

我认为预见到的困难是Foo<T>的两个实例实际上意味着完全不同的事情,因为T对于两者都不一样。相当多的模板早期实现(包括cfront)使用了模板实例化的存储库,因此当/如果发现该类型的实例化尚未存储在存储库中时,编译器可以自动实例化所需类型的模板。

为了使用本地类型工作,存储库不仅能够存储实例化模板的类型,而且还需要为类型创建完整的“路径”。实例。虽然这可能是可能的,但我认为它被视为很少额外的工作(如果有的话)。

从那时起,规则已经发生了很大变化,以至于编译器已经被要求做一些几乎相同的事情,在不同的地方(包括跨TU)在同一类型上查找(和合并)实例化,以便{{{{ 1}}(例如)不违反ODR。基于该实现,在(当前草案)C ++ 0x中放宽了限制(您仍然无法在本地类型上实例化模板类,但您可以使用本地类型作为模板函数的参数)

答案 1 :(得分:3)

我猜这是因为它需要在函数范围内有效地实例化模板,因为这是可见的类型。但是,同时,模板实例化应该表现为它们位于定义模板的范围内。我确信这有可能以某种方式处理,但如果我是对的,标准组织决定不对编译器编写者施加这种负担。

类似的决定是vector<vector<int>>每个标准的语法无效的原因;检测到构造需要编译器词法分析器和解析器阶段之间的某些交互。然而,这种情况正在发生变化,因为C ++ 0x标准民众发现所有编译器都在检测它,无论如何都要发出合理的错误信息。

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