1

I want to overload the << operator to print vectors. This works fine for template arguments vector<T> (with explicit template instantiations) but not for a concrete vector<complex<double>> argument when the code is split into a declaration in foo.h and a definition in foo.cpp.

So while this works:

// foo.h

template < typename T >
std::ostream& operator << (std::ostream& os, const std::vector< T >& v);


// foo.cpp
#include "foo.h" // and using directives

template < typename T >
inline ostream& operator << ( ostream& os, const vector< T >& v ) 
{
    os << "[";
    for (auto vv : v) os << " " << vv;
    os << " ]";

    return os;
}

template ostream& operator << ( ostream& os, const vector< double >& v); // double

template ostream& operator << ( ostream& os, const vector< int >& v); // int

When adding to the header a vector<complex<double>> argument variant

// foo.h
std::ostream& operator << ( std::ostream& os, const std::vector<std::complex<double>>& v)

and the implementation to the source

// foo.cpp
std::ostream& operator << ( std::ostream& os, const std::vector<std::complex<double>>& v) 
{   
    os << "[";
    for (auto vv : v)
        os << " ( " << vv.real() << ((vv.imag() >= 0 ) ? " +" : " ") << vv.imag() << "i )";
    os << " ]";
    return os;
}

I get the error

undefined reference to operator<<(std::ostream&, std::vector<std::complex<double>, std::allocator<std::complex<double> > > const&)

when trying to call that operator

If I move the implementation to the header file, the code works.

Since the whole type, i.e complex<double> is known, I didn't treat the last operator overload as templated but rather as a "regular" thing (there is no "pattern" to fill in for the compiler, isn't it?) But even when I treat it as a specialized template

template< >
std::ostream& operator << ( std::ostream& os, const std::vector<std::complex<double>>& v);

it does not work.

The answer to this related question says to simply NOT overload the vector type but it doesn't explain the above mentioned behavior and I am curious about why this happens.

kingusiu
  • 316
  • 2
  • 15
  • 3
    are you sure that you really compiled an linked against 'foo.cpp'? the symptom are the same if you forgot about it. – Serge Aug 24 '17 at 00:28
  • 1
    You are not linking against the cpp file. The compiler cannot find the implementation for that function, which is why you're getting that error. Are you including foo.h? – ScY Aug 24 '17 at 00:40
  • This is a dead end - in practical terms, you can't add operator overloads where the only operands are built-in types or members of `namespace std`. This is because overloaded operators should be findable by ADL, but yours will not be since it is not in `namespace std`. (And it's UB to add your code to namespace std). – M.M Aug 24 '17 at 01:12

0 Answers0