Could anyone provide me a hint how to implement correctly operator<< for MyType in provided code example?
#include <iostream>
#include <map>
template <typename T>
class A {
public:
typedef std::map<unsigned int, T> MyType;
MyType data;
void show();
};
template <typename T>
std::ostream& operator<<(std::ostream& stream, typename A<T>::MyType const& mm)
{
return stream << mm.size() << "\n";
}
//template <typename T>
//std::ostream& operator<<(std::ostream& stream, std::map<unsigned int, T> const& mm)
//{
// return stream << mm.size() << "\n";
//}
template <typename T>
void A<T>::show() {std::cout << data;}
int main() {
A<double> a;
a.show();
return 0;
}
Above code does not compile. But when I change definition of operator<< to commented out one, everything works correctly. This is just a (not) working example of a more complicated problem and in reality MyType is much much more nasty. In that simple example I just could easily copy-paste exact definition of MyType from a 'A' class but in more complicated case, when this typedef is depending on antoher typedef... it would be nice just to refer to it. Is there any solution to this problem?
Edit:
Output error from compiler (in general as if operator<< was not defined at all, so when both definitions for operator<< from example are commented out compiler prints same error).
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++14 -MMD -MP -MF"src/ostreamTest.d" -MT"src/ostreamTest.o" -o "src/ostreamTest.o" "../src/ostreamTest.cpp"
../src/ostreamTest.cpp:27:31: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'MyType' (aka 'map<unsigned int, double>'))
void A<T>::show() {std::cout << data;}
~~~~~~~~~ ^ ~~~~
Problem is the non-deduced context (thanks PasserBy for the link), which disallows us to find a direct solution.
A workaround might be moving the typedef out of the class, such as this:
template <typename T>
using A_MyType = std::map<unsigned int, T>;
template <typename T>
class A
{
public:
typedef A_MyType<T> MyType;
MyType data;
void show();
};
template <typename T>
std::ostream& operator<<(std::ostream& stream, A_MyType<T> const& mm)
{
return stream << mm.size() << std::endl;
}
Sure, this works fine for the std::map, if it works for your more complex class – impossible to say without knowing more details...