Перегрузка не являющегося членом оператора для шаблонного внутреннего класса - PullRequest
0 голосов
/ 25 ноября 2018

Я не могу понять, почему компилятор не может видеть или использовать 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 голосов
/ 25 ноября 2018

Проблемная часть - A<T>::B в списке параметров, так как компилятор не может вывести выражения типа этой формы, поскольку существование и тип члена B зависит от T.Я бы взял тип аргумента b в качестве аргумента шаблона T напрямую и использовал бы SFINAE для ограничения принятых типов.

0 голосов
/ 25 ноября 2018

Ошибка состоит в том, что перегрузка для вложенного типа содержит невыгруженный контекст параметр 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;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...