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.