Linking error: templated friend operator overload
I am having a strange linking error. I followed instructions presented here to avoid this kind of problems, but I can't figure out how to split headers and implementation files.
Here's my test file:
#include <cargo.h>
#include <iostream>
#include <string>
using namespace std;
using namespace dom;
int main()
{
dom::cargo<string> text("Hello, World!");
cout << text << endl;
return 0;
}
Header file for class cargo
included in the test:
#ifndef CARGO_H
#defi开发者_运维技巧ne CARGO_H 1
#include "node.h"
#include <iostream>
namespace dom
{
template <typename Type> class cargo;
template <typename Type>
std::ostream& operator<<(std::ostream&, const dom::cargo<Type>&);
template <typename Type>
class cargo
: public dom::node
{
Type value;
public:
cargo()
: value()
{ }
cargo(Type value)
: value(value)
{ }
friend std::ostream& operator<< <>(std::ostream&, const dom::cargo<Type>&);
};
}
#endif // !CARGO_H
And its implementation:
#include "cargo.h"
template <typename Type>
std::ostream& operator<< (std::ostream& ostream, dom::cargo<Type>& cargo)
{
return (ostream << cargo.value);
}
I'm using CMake to compile and link it all togather.
The linking error I get is about undefined reference to operator <<
:
Scanning dependencies of target test
[100%] Building CXX object Tests/CMakeFiles/test.dir/test0.c++.o
Linking CXX executable test
CMakeFiles/test.dir/test0.c++.o: In function `main':
test0.c++:(.text+0x9b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& dom::operator<< <std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_ostream<char, std::char_traits<char> >&, dom::cargo<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&)'
collect2: ld returned 1 exit status
make[2]: *** [Tests/test] Error 1
make[1]: *** [Tests/CMakeFiles/test.dir/all] Error 2
make: *** [all] Error 2
What am I doing wrong? Please help me!
(Member) function templates are not functions; the linker doesn't see them unless you instantiate them. Source files are compiled separately, so if you put a (member) function template in one source file and don't explicitly instantiate it, the linker won't see it.
So in your case, the function template has not been turned into a function in cargo.o
, so the linker reports an error because main.o
depends on it. You need to put the template in the header file, or explicitly instantiate it in cargo.cpp
.
精彩评论