#include <iostream>

// Forward declarations
template <typename T> class C;
template <typename T> std::ostream& operator<<(std::ostream& os, const C<T>& dt);

template <typename T>
class C
{
public:
    explicit C(T data) : data_(data) {}
    template <typename T2>
    friend std::ostream& operator<<(std::ostream& os, const C<T2>& dt);
private:
    T data_;
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const C<T>& dt)
{
    C<char> c('!'); // Also has access even when T != char
    return os << dt.data_ << c.data_;
}

int main()
{
    C<int> der(234);
    std::cout << der;
}
