Reputation: 7048
I have a class Vector<T>
, and am using a library that provides a class YAML::Node
. I would like to overload operator>>
for these two types.
I have added the following declaration to Vector
's declaration:
friend void operator>>(YAML::Node const & node, Vector<T> & v);
I have also added the following implementation of the function:
template<typename T>
void operator>>(YAML::Node const & node, Vector<T> & v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
Finally, I have added the following (attempt at) explicitly instantiating the template for T = num_t
:
template
void operator>>(YAML::Node const & node, Vector<num_t> & v);
However, this results in the following linker error:
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
is a typedef for double
)
However, if I add the following (non-template) implementation of the function, everything compiles fine:
void operator>>(YAML::Node const & node, Vector<num_t> & v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
Why is the template version of the function not working?
Edit: Forgot to mention; the compiler is Visual Studio 11 Beta
Upvotes: 1
Views: 666
Reputation: 254531
Declaring the function as a friend
does not declare a function template; instead, each specialisation of the class template declares a non-template function, with its parameter types overloaded according to the template arguments. These will be chosen instead of the template you define; but they are not defined, hence the error.
To fix it, you can either declare the function template before the class template (in which case the friend declaration will make that a friend, rather than declare a new function), or define the friend function inline, inside the class template, so that each specialisation of the class template defines the function as well as declaring it.
Upvotes: 3
Reputation: 153895
Well, the problem is that the friend
you declared is a non-template function which has nothing to do at all with your shift operator. In fact, your template uses any private members the compiler should complain. Here is an example how this should look like:
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);
}
If you replace the friend declaration by
friend void f(foo<T>);
This code won't link either and will actually produce a compile time error indicating that the function f()
is not a friend.
Upvotes: 2
Reputation: 58598
That is strange. I can't see anything wrong, and even the MSDN documentation (this is Visual C++ right?) confirms that template instantiation should deduce the template arguments. The arguments in the instantiation match. Maybe it's broken for overloaded operators?
It would not hurt to try adding explicit template arguments on it.
Also, perhaps it's being confused by the typedef? You never know! Try substituting double.
Upvotes: 0