我有一个班级Vector<T>
,并且正在使用提供班级YAML::Node
的库。我想为这两种类型重载operator>>
。
我在Vector
的声明中添加了以下声明:
friend void operator>>(YAML::Node const & node, Vector<T> & v);
我还添加了以下函数实现:
template<typename T>
void operator>>(YAML::Node const & node, Vector<T> & v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
最后,我添加了以下(尝试)显式实例化T = num_t
的模板:
template
void operator>>(YAML::Node const & node, Vector<num_t> & v);
但是,这会导致以下链接器错误:
Error 9 error LNK2019: unresolved external symbol "void __cdecl operator>>(class YAML::Node const &,class Vector<double> &)" (??5@YAXAEBVNode@YAML@@AEAV?$Vector@N@@@Z) referenced in function "public: static class Scene __cdecl Scene::fromFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?fromFile@Scene@@SA?AV1@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
(num_t
是double
)
但是,如果我添加了函数的以下(非模板)实现,那么一切都编译得很好:
void operator>>(YAML::Node const & node, Vector<num_t> & v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
为什么函数的模板版本不起作用?
编辑:忘了提;编译器是Visual Studio 11 Beta
答案 0 :(得分:3)
将函数声明为friend
不声明函数模板;相反,类模板的每个特化都声明了一个非模板函数,其参数类型根据模板参数重载。将选择这些而不是您定义的模板;但它们没有定义,因此错误。
要修复它,您可以在类模板之前声明函数模板(在这种情况下,友元声明将使其成为朋友,而不是声明新函数),或者在类模板中定义内联的friend函数,以便类模板的每个特化都定义函数并声明它。
答案 1 :(得分:2)
嗯,问题是您声明的friend
是一个非模板函数,它与您的移位运算符完全无关。实际上,您的模板使用编译器应该抱怨的任何私有成员。以下是一个示例:
template <typename T>
class foo
{
public:
template <typename S>
friend void f(foo<S>);
private:
T value;
};
template <typename T>
void f(foo<T> v)
{
v.value;
}
template void f(foo<int>);
int main()
{
foo<int> v;
f(v);
}
如果您用
替换好友声明friend void f(foo<T>);
此代码也不会链接,实际上会产生编译时错误,表明函数f()
不是朋友。
答案 2 :(得分:0)
这很奇怪。我看不出有什么问题,甚至MSDN文档(这是Visual C ++吧?)确认模板实例化应该推断出模板参数。实例化中的参数匹配。也许它对于重载运算符而言已经破裂了?
尝试在其上添加显式模板参数并没有什么坏处。
另外,也许它被typedef搞糊涂了?你永远都不会知道!尝试替换double。