I have a struct that works as a wrapper for other types as follows:
template<typename T>
struct A {
A& operator=(const T& value){
m_value = value;
return *this;
}
operator T() const {
return m_value;
}
private:
T m_value;
};
I use it like this:
int main() {
A<int> a;
a = 5; // Copy assignment constructor
std::cout << a << "\n"; // Implicit conversion to int
}
which works as expected. My problem occurs when using non-fundamental types as the following example shows:
int main() {
A<std::complex<int>> c;
c = std::complex<int>(2, 2);
std::cout << c << "\n";
}
The snippet above raises an invalid operands to binary expression
error.
Why does this error occur? Why isn't the overloaded operator <<
of std::complex<int>
used with the implicitly converted A<std::complex<int>>
?
The stream operators for std::complex
are template functions. They will not be invoked unless you actual have a std::complex
as no conversions happens in template argument deduction. This means the compiler will not find a suitable overload to print a A<std::complex<int>>
You're first case for works because std::basic_ostream::operator <<
is overloaded to take an int
and you are allowed one user defined conversion is overload resolution.
As a work arround you can define your own operator <<
that takes your wrapper and forward to the underlying types' operator <<
. That would look like
template<typename T>
std::ostream& operator <<(std::ostream& os, const A<T>& a)
{
return os << static_cast<T>(a);
}