Rizo
Rizo

Reputation: 3113

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
#define 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!

Upvotes: 0

Views: 420

Answers (1)

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272537

(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.

Upvotes: 2

Related Questions