简体   繁体   中英

Overloading of a non-member operator for a templated inner class

I cannot figure out why the operator<< ( std::ostream & os, typename A<T>::B const& b ) can't be seen or used by the compiler.

#include <vector>
#include <iostream>


template <typename T> 
struct A
{
    struct B
    {
        std::vector<T> innervec;
    };

   std::vector<B> outervec;
};

template <typename T>
auto operator<< ( std::ostream & os, typename A<T>::B const& b ) -> std::ostream& 
{
    for (auto e : b.innvervec)
        os << "\n\t" << e;

    return os;
}

template <typename T>
auto operator<< ( std::ostream & os, A<T> const& a ) -> std::ostream& 
{
    for (auto e : a.outervec)
        os << '\n' << e;

   return os;
}

int main()
{
   A<int> a;
   A<int>::B b1;
   A<int>::B b2;
   b1.innervec.push_back( 11 );
   b1.innervec.push_back( 12 );
   b2.innervec.push_back( 21 );
   b2.innervec.push_back( 22 );
   a.outervec.push_back( b1 );
   a.outervec.push_back( b2 );
   std::cout << a << std::endl;
}

gives me the following error on VC++15:

error C2679: binary '<<': no operator found which takes a right-hand operand of type 'A<int>::B' (or there is no acceptable conversion)

And it doesn't compile on GCC as well (only tried with an online compiler though).

I suppose that a rule about scope and deduction is involved, but I couldn't find out which precisely.

The error is because the overload for the nested type contain a non-deduced context parameter typename A<T>::B const& b and for operators you can't provide the explicit template argument T , you need to define the operator as friend for the nested A<T>::B as:

template <typename T>
struct A
{
    struct B
    {
        std::vector<T> innervec;
        friend auto operator<< ( std::ostream & os, B const& b ) -> std::ostream&
        {
            for (auto e : b.innervec)
                os << "\n\t" << e;

            return os;
        }
    };

    std::vector<B> outervec;
};

The problematic part is A<T>::B in the parameter list, as the compiler cannot deduce type expressions of this form, since existence and type of member B depends on T . I would take the type of b argument as template argument T directly, and use SFINAE to constrain accepted types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM