模板化内部类的非成员运算符的重载

时间:2018-11-25 19:51:12

标签: c++ templates

我无法弄清为什么编译器无法看到或使用operator<< ( std::ostream & os, typename A<T>::B const& b )

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

在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)

它也不能在GCC上编译(不过只能在在线编译器上尝试过)。

我想其中涉及到有关范围和演绎的规则,但我无法准确找出。

2 个答案:

答案 0 :(得分:2)

该错误是因为嵌套类型的重载包含一个非推断上下文参数typename A<T>::B const& b,而对于运算符,您不能提供显式模板参数T,您需要将操作符定义为嵌套A<T>::B的好友,例如:

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

答案 1 :(得分:1)

有问题的部分是参数列表中的A<T>::B,因为编译器无法推断这种形式的类型表达式,因为成员B的存在和类型取决于T。我直接将b参数的类型作为模板参数T,并使用SFINAE约束可接受的类型。

相关问题