BCS*_*BCS 6 c++ templates language-design
在C++中,有一个函数本地类型的函数是可以的:
int main() {
struct S { static void M(const S& s) { } };
S s;
S::M(s);
}
Run Code Online (Sandbox Code Playgroud)
但是没有确定的模板可以:
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&)'
}
Run Code Online (Sandbox Code Playgroud)
没有链接[...]的类型不能用作模板类型参数的模板参数
为什么C++不允许这样做?
到目前为止我听到的最好的解释是内部类型没有链接,这可能意味着将它们作为arg的函数必须没有链接.但是我没有理由看到模板实例化必须具有链接.
ps请不要只说" 那是不允许的,因为标准说它不是 "
我相信预见的困难是两个实例Foo<T>意义完全不同的事实,因为T两者并不相同.相当多的模板早期实现(包括cfront)使用了模板实例化的存储库,因此当/如果发现该类型的实例化尚未存储在存储库中时,编译器可以自动实例化所需类型的模板.
为了使用本地类型工作,存储库不仅能够存储实例化模板的类型,而且还需要执行类似于为实例化创建类型的完整"路径".虽然这可能是可能的,但我认为它被视为很少额外的工作(如果有的话)真正的好处.
自那时以来,规则已经改变,以至于编译器已经需要做一些事情,这只是大致相当,发现(和合并)在不同的地点相同类型的实例(包括跨课时),这样两个实例foo<int>(例如)唐不违反ODR.基于这种认识,该限制已经在(目前草案)的C++ 0x松动(您仍然无法实例化模板类在当地的类型,但是你可以使用本地类型作为参数传递给一个模板函数) .
我猜这是因为它需要在函数范围内有效实例化模板,因为这是此类类型可见的地方。然而,与此同时,模板实例化应该表现得好像它们在定义模板的范围内一样。我确信可以以某种方式处理这个问题,但如果我是对的,标准机构决定不给编译器编写者带来这种负担。
类似的决定是原因vector<vector<int>>是根据标准语法无效;检测该构造需要编译器词法分析器和解析器阶段之间进行一些交互。然而,这种情况正在改变,因为 C++0x 标准人员发现所有编译器都在检测它以发出合理的错误消息。
我怀疑,如果要证明允许这种构造实现起来很简单,并且它不会在语言范围规则中引入任何歧义,那么有一天您可能会看到这里的标准也发生了变化。