运算符的显式实例化>>超载

时间:2012-03-08 01:08:08

标签: c++ templates operator-overloading

我有一个班级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_tdouble

的typedef

但是,如果我添加了函数的以下(非模板)实现,那么一切都编译得很好:

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

3 个答案:

答案 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。