Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how overload operator<< for an array in C++?

I'm trying to do it this way:

template <typename T>
ostream &operator<<(ostream &os, T &arr)
{ /*...*/ }

But can T represent an array? Is it correct to overload the << operator for an array?


EDIT:

According to Kerrek SB's advice, here is my implementation for <<:

template <typename T, unsigned int N>
ostream &operator<<(ostream &os, const T (&arr)[N])
{
    int i;
    for(i = 0; i < N; i++)
        os << arr[i] << " ";
    os << endl;
    return os;
}

Is my implementation right? I got a compilation error.

like image 913
Alcott Avatar asked Sep 16 '11 01:09

Alcott


People also ask

Can we overload << operator?

We can overload the '>>' and '<<' operators to take input in a linked list and print the element in the linked list in C++. It has the ability to provide the operators with a special meaning for a data type, this ability is known as Operator Overloading.

How do you overload left shift operator?

you can't overload left shift operator like this in c#. Because in the left shift operator, the first operand must be the containing type and second operand must be an integer.

Which function overload the >> operators?

7. Which function overloads the >> operator? Explanation: __rshift__() overloads the >> operator.

Can you overload array?

In the C++ programming language, it is possible to overload the index operator of the elements of the array [ ]. This operator is considered unary, that is, it requires one parameter – the array index. So, it is advisable to overload the [ ] operator in classes where arrays are used.


1 Answers

You could do this:

template <typename T, unsigned int N>
std::ostream & operator<<(std::ostream & os, const T (&arr)[N])
{
  // ..
  return os;
}

This works only for compile-time arrays, of course. Note that you are not allowed to instantiate this template when T is a built-in type or a type in the std namespace!

Probably best to make this inline if possible, since you'll cause a separate instantiation for every N. (The pretty printer has an example of this.)

You will notice, though, that the blanket template introduces an ambiguity, because os << "Hello" now has two possible overloads: the template matching const char (&)[6], and the (non-template) overload for the decay-to-pointer const char *, which both have identical conversion sequences. We can resolve this by disabling our overload for char arrays:

#include <ostream>
#include <type_traits>

template <typename T, unsigned int N>
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type
operator<<(std::ostream & os, const T (&arr)[N])
{
  // ..
  return os;
}

In fact, to be even more general you can also make the basic_ostream parameters template parameters:

template <typename T, unsigned int N, typename CTy, typename CTr>
typename std::enable_if<!std::is_same<T, char>::value,
                        std::basic_ostream<CTy, CTr> &>::type
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N])
{
  // ..
  return os;
}

In view of the fact that T must be a user-defined type, you could even replace is_same<T, char> with is_fundamental<T> to get a bit more checking (but users still must not use this for arrays of standard library types).

like image 83
Kerrek SB Avatar answered Sep 20 '22 03:09

Kerrek SB