2010-08-12 106 views
6

在C++中它的确定有一个funcction,需要一个函数的局部类型:为什么模板不能使用函数本地类型?

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.

A型[...]不可用作模板类型的模板参数

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


到目前为止,它是内在的类型没有关联,而这可能意味着该把他们作为一个ARG函数必须有没有联系我听过的最好说明。但没有理由我可以看到模板实例化必须有联系。


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

+5

没有什么好的理由,C++ 0x将删除这个限制(但不是在p.s链接的那个限制;我仍然不知道为什么不允许)。 – 2010-08-12 17:21:05

+0

@Mike;简明扼要! – BCS 2010-08-12 17:22:10

回答

3

我猜这是因为它会要求模板在函数的范围内有效地实例化,因为那是类型可见的地方。但是,与此同时,模板实例化应该像是在模板定义的范围内一样。我确信这是可以以某种方式处理的,但如果我是对的,标准组织决定不将这种负担加在编译器编写者身上。

类似的决定是因为vector<vector<int>>是无效的标准语法;检测到构造需要编译器词法分析器和解析器阶段之间的一些交互。然而,这种情况正在改变,因为C++ 0x标准的人发现所有的编译器都会检测到它,以发出理智的错误消息。

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

+1

只要C++ 0x获得批准,“有一天”会一经改变,除非他们改变了主意。最终草案删除了这个限制。 – 2010-08-12 17:24:21

+0

我可以想象一个很难实现的编译器体系结构,但我也可以想象它将免费获得的体系结构。 – BCS 2010-08-12 17:25:06

7

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

为了使用本地类型进行工作,存储库不仅能够存储实例化模板的类型,而且还需要执行类似于为类型创建完整“路径”的操作实例化。尽管这可能是可能的,但我认为这对于很少的(如果有的话)真正的好处是很多额外的工作。

从那时起,规则已经发生了很大的变化,以至于编译器已经被要求做一些基本等价的事情,在不同的地方(包括TU上)查找(并合并)相同类型的实例,以便得到两个实例foo<int> (例如)不要违反ODR。基于这种认识,C++ 0x(当前草案)中已经放宽了限制(您仍然不能在本地类型上实例化模板类,但是可以使用本地类型作为模板函数的参数) 。

+0

简而言之,它曾经是编译器的更多工作? – BCS 2010-08-12 21:54:44

+0

@BCS:尽管这可能也是如此,但它并没有那么多,以至于它曾经是编译器的更多工作,因为它是:1)大多数额外的工作现在都是由于其他原因而完成的,2)编译C++现在非常复杂,无论如何人们更愿意接受增加更多的复杂性,只要它不太剧烈。 – 2010-08-12 22:22:27

+0

§14.3.1[temp.arg.type]有几个将本地类型传递给类模板的示例。 – Potatoswatter 2010-08-13 01:20:37

相关问题