If you implement << after class:

 #include <iostream> template <typename t_b> class B; template <typename t_a> class A { public: friend class B<t_a>; operator B<t_a>(); }; template <typename t_b> class B { public: friend class A<t_b>; A<t_b> operator [] (const B &s2) {} friend std::ostream& operator << <t_b>(std::ostream &, const B &); // <-- ошибка тут }; template<typename t_a> A<t_a>::operator B<t_a>() { return B<t_a>(); } template <typename t_b> std::ostream& operator << (std::ostream &os, const B<t_b> &s) {} int main() { B<int> s1, s2, s3; std::cout << s1[s2]; } 

[Error] declaration of 'operator <<' as non-function

If before:

 #include <iostream> template <typename t_b> class B; template <typename t_a> class A { public: friend class B<t_a>; operator B<t_a>(); }; template <typename t_b> std::ostream& operator << (std::ostream &os, const B<t_b> &s) {} template <typename t_b> class B { public: friend class A<t_b>; A<t_b> operator [] (const B &s2) {} friend std::ostream& operator << <t_b>(std::ostream &, const B &); }; template<typename t_a> A<t_a>::operator B<t_a>() { return B<t_a>(); } int main() { B<int> s1, s2, s3; std::cout << s1[s2]; // <-- ошибка тут } 

[Error] cannot bind 'std :: ostream {aka std :: basic_ostream}' lvalue to 'std :: basic_ostream &&'

Judging by the answers Operator overloading >> and << in the template class as friend functions and an error occurs with implicit type conversion in the first case there is a gcc bug, and in the second - a problem with ADL . And the solutions are mutually exclusive. How to be?

    2 answers 2

    The thing is that in template functions / classes there is no implicit type conversion of parameters, therefore your

     template <typename t_b> std::ostream& operator << (std::ostream &os, const B<t_b> &s) { return os; } 

    cannot produce implicit type conversions from A<t_b> to B<t_b> in this place

     std::cout << s1[s2]; 

    If we produce an explicit type conversion, then the problem will disappear:

     std::cout << static_cast<B<int>>(s1[s2]); 

    You can also add an explicit template specialization (which will then work without explicit type conversion) in the style:

     std::ostream& operator << (std::ostream &os, const B<int> &s) { return os; } 

    But I doubt that this way of solving the problem will suit you (not to add the same template specialization for each type).


    Or, you can use Harry's answer and implement an overload of a free operator under class A (now you have an implementation only under class B , and therefore, the compiler needs to cast types).

      Explicit type casting should save. Or add

       template <typename T> std::ostream& operator << (std::ostream &os, const A<T> &); 
      • Where to add ?? - ZmitrikNikolay
      • @ZmitrikNikolay It’s about the fact that you can add a redefinition of a free operator << explicitly under class A (you have now just under class B it is implemented) so that the compiler does not have to cast an instance of class A (the result of s1[s2] ) class B - StateItPrimitive
      • @StateItPrimitive well, if there are no other answers, I’ll do it, probably - ZmitrikNikolay
      • @ZmitrikNikolay Well, you really still wait just in case for other answers, all of a sudden we are missing something. - StateItPrimitive