Перегрузка оператора вывода для массивов

по данным ответ правильный способ перегрузки оператора вывода << для массивов c-стиля это -:

#include <iostream>
using namespace std;

template <size_t arrSize>
std::ostream& operator<<( std::ostream& out, const char( &arr )[arrSize] )
{
    return out << static_cast<const char*>( arr ); // use the original version
}

// Print an array
template<typename T1, size_t arrSize>
std::ostream& operator <<( std::ostream& out, const T1( & arr )[arrSize] )
{
    out << "[";
    if ( arrSize )
    {
        const char* separator = "";
        for ( const auto& element : arr )
        {
            out << separator;
            out << element;
            separator = ", ";
        }
    }
    out << "]";
    return out;
}

int main()
{
    int arr[] = {1, 2, 3};
    cout << arr;
}

но я все еще получаю ошибки компилятора

error: ambiguous overload for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'const char [2]')  

на out << "["; и out << "]"; заявления.

как правильно это сделать ?

1 ответов


проблема заключается в стандартной перегрузке для operator<<, которая печатает массив символов это:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                         const char* s );

поэтому, когда вы предоставляете свои:

template <size_t arrSize>
std::ostream& operator<<( std::ostream& out, const char( &arr )[arrSize] )

это будет неоднозначно: у нас есть два разных шаблона функций с одинаковыми последовательностями преобразования, ни один из которых не является более специализированным, чем другой.

однако, поскольку вы хотите, чтобы ваша версия просто вызывала оригинал, на самом деле нет причин предоставлять свою версию по адресу все. Просто сделайте свой" общий " массив принтер не принимает char использование SFINAE:

// Print an array
template<typename T1, size_t arrSize, 
         typename = std::enable_if_t<!std::is_same<T1,char>::value>>
std::ostream& operator <<( std::ostream& out, const T1( & arr )[arrSize] )
{ /* rest as before */ }