实例化后的显式特化

时间:2011-10-14 22:21:12

标签: c++ templates template-specialization

我有以下代码:

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;
}

未解决的外部结果。
为什么编译器说它已经实例化它不能甚至不实例化?为什么编译器不将它视为未解析的符号,而链接器呢? 我知道切换方法顺序可以解决它,但我想知道为什么编译器会这样做。

2 个答案:

答案 0 :(得分:11)

代码在DoSomething(*i)请求隐式实例化。您没有在该转换单元中定义模板的事实意味着它无法实例化特化,因此DoSomething(*i)会在您的情况下产生“未解析的符号”(链接器)错误。要消除该错误,您必须在该TU中定义模板,或者在定义模板的TU中提供该模板的显式实例化指令。

在你明确规定专业化足以使程序变得格式错误之前,代码请求专门化DoSomething<vector<int> >的隐式实例化这一事实(虽然不需要诊断;编译器做得很好)这里不需要这样做。)

正如@CharlesBailey所说,宣布明确的专业化是完全足够的;它的定义可以在其他地方给出,甚至在使用TU之外。

答案 1 :(得分:3)

通常它只是意味着您没有为模板专业化提供“原型”。换句话说,你没有给编译器一个抬头“嘿,这个特定类型的函数会有专门化,所以不要插错。”

在我的情况下,我在.cpp文件中有一个模板专门化,并且出现了此错误。提供一个“函数原型”(它只是模板特化标题,后跟分号,就像常规函数原型一样)修复了问题。