How to resolve the following errors?
I am getting the following errors- errors whenever i try 开发者_Go百科to compile the following program- http://codepad.org/Bf9l8j9H in VS 2010.
Any idea how to resolve the errors??
That is a linker error, and it indicates that you have declared but not defined (or the definition is not linked) the following overload:
std::ostream& operator<<( std::ostream&, node<weight>& );
The common checks to do from here would be checking whether you have a definition, whether the definition signature matches the declaration (have you declared that, but defined the operator taking a const reference?), whether the definition is being compiled and linked...
I just got a few time and actually read the code, which I will basically condense into this:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream&, node<T>& ); // [1] !!!!
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) {} // [2]
This is a common mistake and one of the reasons why it is simpler just to inline the definition of friend functions inside the templates that befriend them. Basically, in [1] your template is declaring (and befriending) a non-templated function that takes an ostream&
and a node<T>&
object.
The subtlety here is that when the template is instantiated for some particular type, and the friend
declaration is processed, T
is fixed and that line befriends a free non-templated function. For example, if you instantiate node
with int
, as in node<int> n
, the compiler will inject int
and replace T
with it, then the friend
declaration will be: friend ostream& operator<<( ostream&, node<int>& )
, and that in turn declares a free function in the enclosing namespace. Making that declaration explicit (and assuming that you only instantiate the template with int
, your code is read by the compiler as:
template <typename T> struct node {
friend ostream& operator<<( ostream&, node& ); // [1] note <T> not required here
};
// instantiating with int:
ostream& operator<<( ostream&, node<int>& ); // [3] declaration, not definition
template <typename T>
ostream& operator<<( ostream&, node<T>& ) {} // [2] your definition
At this point, whenever you type std::cout << a_int_node;
the compiler will consider all overloads, it will find a non-templated free function [3] that is a perfect match, and a templated version [2], but the non-templated version will take precedence. The compiler will not instantiate the templated operator<<
and will expect that you manually define the function in one translation unit.
Solutions
Simplest best solution is having the compiler generate the free function for you. You can just provide the operator definition inside the templated class and everything will be nice and simple:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream& o, node& n ) // [1]
{ /* code goes here */ return o; }
};
Even if the code is inside the template, because of the friend
being there, you are actually declaring and defining the function at namespace level. If you instantiate the template with int
, the compiler will generate: std::ostream& operator<<( std::ostream&, node<int>& )
for you in the enclosing namespace.
This solution is the best of all worlds: you only grant access to a single piece of code, and the compiler takes care of most of the gory details.
On the other end, you can befriend a whole template function. The syntax for that would be:
template <typename T>
struct node {
template <typename U>
friend std::ostream& operator<<( std::ostream&, node<U>& ); // [4]
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // can access private parts
{ /* code goes here */ return o; }
In this case, you are opening all instantiations of node
to all instantiations of the templated function, which semantically is opening the class to other users.
The third option is befriending a single template instantiation, this will have the same effect as the first option with the only difference that instead of a non-templated free function you are using a templated one. On the other hand, the syntax is quite more cumbersome as it requires declaring the function template before befriending, and that in turn requires declaring the class template:
template <typename T> struct node; // forward declare the class template
template <typename T>
std::ostream& operator<<( std::ostream&, node<T>& ); // declare function template
template <typename T>
struct node { // define class template
friend std::ostream& operator<< <>( std::ostream&, node<T>& ); // befriend instantiation
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // define function template
{ ... }
As you see, the simplest best solution is just defining the function template inside the class definition.
conio.h is an old header from the MS-DOS compilers; UPDATE: it is still available in VS 2010, though.
best is a stream you declared after you used it.
精彩评论