Reputation: 1238
I want to implement operator <<
that would print contents of internal class of a template class, i.e. X<T>::Y
. It is okay to add any friend
declarations needed. How to do it?
Here is a full example of what I want to compile in C++11:
#include <iostream>
template <typename T>
class X {
public:
X(T d): y(d) {}
private:
class Y {
public:
Y(T d): data(d) {}
private:
T data;
template <typename U>
friend std::ostream &operator <<(std::ostream &os, const typename X<U>::Y &y);
};
Y y;
template <typename U>
friend std::ostream &operator <<(std::ostream &os, const X<U> &x);
};
// This operator is not detected by the operator below
template <typename U>
std::ostream &operator <<(std::ostream &os, const typename X<U>::Y &y) {
os << "Y(" << y.data << ")";
return os;
}
template <typename U>
std::ostream &operator <<(std::ostream &os, const X<U> &x) {
os << "X " << x.y;
return os;
}
int main() {
std::cout << X<int>(1);
return 0;
}
The compiler error I get is:
error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const X<int>::Y')
os << "X " << x.y;
^
Upvotes: 3
Views: 135
Reputation: 1087
This doesn't work since typename X<U>::Y
is a dependent type. If you want to print e.g. an int
, should the compiler just test all possible types for U
(there are infinite many due to recursion) in order to check, whether typename X<U>::Y
results as an int
(consider template specialisation!)? Therefore the only possibility is to implement the function right at the friend statement:
class Y {
public:
Y(T d): data(d) {}
private:
T data;
friend std::ostream &operator <<(std::ostream &os, Y const& y)
{
os << "Y(" << y.data << ")";
return os;
}
};
Upvotes: 4