Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading output operator for arrays

According to this answer, the correct way to overload output operator << for C-style arrays is this -:

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

But I am still getting the compiler error

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

for the out << "["; and out << "]"; statements.

What is the correct way of doing this ?

like image 311
Anmol Singh Jaggi Avatar asked Jun 30 '15 10:06

Anmol Singh Jaggi


People also ask

Can [] operator be overloaded?

An overloaded operator (except for the function call operator) cannot have default arguments or an ellipsis in the argument list. You must declare the overloaded = , [] , () , and -> operators as nonstatic member functions to ensure that they receive lvalues as their first operands.

Which operator is used for operator overloading?

Example1: ++ Operator (Unary Operator) Overloading In the above example, whenever ++ is called along with a variable, it increases the value by 1 unit. In this example, ++ is used as a prefix or pre-increment.

What is overloading explain operator overloading with example?

(1) The mechanism of giving some special meaning to an operator is called as operator overloading. (2) In C++, the user defined data types behave in much the same way as the built-in data types. (3) For instance, C++ permits to add two varibles of user-defined data types with the same syntax as the basic types.

Can we overload the operator for integers?

No we cannot overload integer or float types because overloading means to change the working of existing operators or make them to work with objects int is single member not an object.


1 Answers

The problem is the standard overload for operator<< that prints a character array is this one:

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

So when you provide yours:

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

That's going to be ambiguous: we have two different function templates with identical conversion sequences, neither of which is more specialized than the other.

However, since you want your version to JUST call the original, there is really no reason to provide your version at all. Just make your "generic" array printer not accept char using 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 */ }
like image 90
Barry Avatar answered Oct 22 '22 14:10

Barry