实例化后显式专业化
我有以下代码:
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
,虽然不能,但一个简单的程序可以证明这一点:
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;
}
导致无法解析的外部。
为什么编译器说它已经实例化它,而它不能甚至没有实例化它?为什么编译器不将其视为未解析的符号,而链接器却将其视为未解析的符号?
我知道切换方法顺序可以解决这个问题,但我想知道编译器为什么这样做。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该代码请求在
DoSomething(*i)
进行隐式实例化。您没有在该翻译单元中定义模板的事实意味着它无法实例化专业化,因此DoSomething(*i)
在您的情况下会产生“无法解析的符号”(链接器-)错误。要消除该错误,您必须在该 TU 中定义模板,或者在定义模板的 TU 中提供该模板的显式实例化指令。代码请求专门化
DoSomething 的隐式实例化这一事实本身就表明了这一点。 >
在您明确提供专业化足以使程序变得不正确之前(尽管不需要诊断;编译器在这里做得很好,但不需要这样做)。正如 @CharlesBailey 所指出的,声明显式专业化就完全足够了;它的定义可以在其他地方给出,甚至在使用 TU 之外。
The code requested an implicit instantiation at
DoSomething(*i)
. The fact that you didn't define the template in that translation unit means that it could not instantiate a specialization, henceDoSomething(*i)
yields an "unresolved symbol" (linker-) error in your case. To get rid of that error, you either have to define the template in that TU, or provide an explicit instantiation directive of that template in a TU where you define the template.The mere fact that the code requested an implicit instantiation for specialization
DoSomething<vector<int> >
before you explicitly provided that specialization is enough for the program to become ill-formed (without a diagnostic being required though; the compiler does a good job here which it is not required to do).As @CharlesBailey helpfully notes, declaring the explicit specialization is perfectly sufficient; a definition of it can be given elsewhere, even outside of the using TU.
一般来说,这只是意味着您没有为模板专业化提供“原型”。换句话说,您没有提醒编译器“嘿,该函数的特定类型将会有专门化,所以不要插入错误的函数。”
就我而言,我在
.cpp
文件中有一个模板专门化,并收到此错误。提供“函数原型”(只是模板专业化标头后跟分号,就像常规函数原型一样)解决了问题。Generally it just means you didn't provide a "prototype" for the template specialization. In other words you didn't give the compiler a heads up that "hey, there is going to be a specialization for this specific type of the function, so don't plug in the wrong one."
In my case I had a template specialization in a
.cpp
file, and got this error. Providing a "function prototype" (which is just the template specialization header followed by a semicolon, just like a regular function prototype) fixed the problem.