Xilexio
Xilexio

Reputation: 1238

operator << for internal class of a template class

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

Answers (1)

Fytch
Fytch

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;
    }
};

http://ideone.com/dx8Qri

Upvotes: 4

Related Questions