(注意:我知道这是非法的,我正在寻找这种语言的原因。)
template<class c> void Foo(); // Note: no generic version, here or anywhere.
int main(){
Foo<int>();
return 0;
}
template<> void Foo<int>();
错误:
error: explicit specialization of 'Foo<int>' after instantiation
谷歌快速通过this citation of the spec,但这只提供了什么,而不是原因。
修改
有几个回复转发了这个论点(例如证实了我的推测),规则是这样的,因为否则会违反One Definition Rule (ODR)。然而,这是一个非常弱的论点,因为在这种情况下,它不适用于两个原因:
Foo<int>
的调用无法定义模板的泛型特化,因为没有专门的泛型体。对此事的猜测:
关于为什么规则存在的猜测:如果第一行提供了一个定义(而不是声明),实例化后的显式特化将是一个问题,因为你会得到多个定义。但在这种情况下,唯一可见的定义是明确的专业化。
奇怪的是,以下(或者我正在处理的实际代码中的类似内容)可以工作:
档案A:
template<class c> void Foo();
int main(){
Foo<int>();
return 0;
}
档案B:
template<class c> void Foo();
template<> void Foo<int>();
但总的来说,使用它开始创建一个意大利面条进口结构。
答案 0 :(得分:5)
猜测为什么规则存在于 全部:如果第一行提供了 定义(而不是a 声明),一个明确的 实例化后的专业化 会是一个问题,因为你会 得到多个定义。但在这 案例,唯一的定义是 明确的专业化。
但你确实有多个定义。你已经定义了Foo&lt; int&gt;当你实例化它时,你尝试专门化int的模板函数,已经定义了。
int main(){
Foo<int>(); // Define Foo<int>();
return 0;
}
template<> void Foo<int>(); // Trying to specialize already defined Foo<int>
答案 1 :(得分:2)
此代码是非法的,因为在实例化后会出现显式特化。基本上,编译器首先看到了通用模板,然后它看到了它的实例化并专门化了具有特定类型的通用模板。之后,它看到了已经实例化的通用模板的特定实现。那么编译器应该做什么?回去重新编译代码?这就是不允许这样做的原因。
答案 2 :(得分:2)