重载数组的输出运算符

Anm*_*ggi 9 c++ arrays templates pretty-print

根据这个答案,<<为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;
}
Run Code Online (Sandbox Code Playgroud)

但我仍然得到编译器错误

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

out << "[";和和out << "]";声明.

这样做的正确方法是什么?

Bar*_*rry 8

问题是operator<<打印字符数组的标准重载是这样的:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                         const char* s );
Run Code Online (Sandbox Code Playgroud)

所以,当你提供你的:

template <size_t arrSize>
std::ostream& operator<<( std::ostream& out, const char( &arr )[arrSize] )
Run Code Online (Sandbox Code Playgroud)

这将是模棱两可的:我们有两个不同的功能模板具有相同的转换序列,这两个模板都不比另一个更专业.

但是,由于您希望您的版本只能调用原始版本,因此根本没有理由提供您的版本.只是让你的"通用"阵列打印机不能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 */ }
Run Code Online (Sandbox Code Playgroud)