我有以下代码:
typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;
template<typename Vec>
Vec DoSomething(const Vec &v);
template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
VecOfVec r;
for(auto i = v.begin(); i != v.end(); i++)
r.push_back(DoSomething(*i));
return r;
}
template<>
Vec DoSomething<Vec>(const Vec &v) // Error here
{
return v; // for the sake of the example
}
我收到以下错误:
explicit specialization of 'DoSomething<vector<int> >' after instantiation
在标记线处。
编译器坚持认为它已经实例化DoSomething<vector<int> >
,而它不能,并且一个简单的程序可以证明它:
typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;
template<typename Vec>
Vec DoSomething(const Vec &v);
template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
VecOfVec r;
for(auto i = v.begin(); i != v.end(); i++)
r.push_back(DoSomething(*i));
return r;
}
未解决的外部结果。
为什么编译器说它已经实例化它不能甚至不实例化?为什么编译器不将它视为未解析的符号,而链接器呢?
我知道切换方法顺序可以解决它,但我想知道为什么编译器会这样做。
答案 0 :(得分:11)
代码在DoSomething(*i)
请求隐式实例化。您没有在该转换单元中定义模板的事实意味着它无法实例化特化,因此DoSomething(*i)
会在您的情况下产生“未解析的符号”(链接器)错误。要消除该错误,您必须在该TU中定义模板,或者在定义模板的TU中提供该模板的显式实例化指令。
在你明确规定专业化足以使程序变得格式错误之前,代码请求专门化DoSomething<vector<int> >
的隐式实例化这一事实(虽然不需要诊断;编译器做得很好)这里不需要这样做。)
正如@CharlesBailey所说,宣布明确的专业化是完全足够的;它的定义可以在其他地方给出,甚至在使用TU之外。
答案 1 :(得分:3)
通常它只是意味着您没有为模板专业化提供“原型”。换句话说,你没有给编译器一个抬头“嘿,这个特定类型的函数会有专门化,所以不要插错。”
在我的情况下,我在.cpp
文件中有一个模板专门化,并且出现了此错误。提供一个“函数原型”(它只是模板特化标题,后跟分号,就像常规函数原型一样)修复了问题。