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;
fo开发者_运维技巧r(i = 0; i < N; i++)
os << arr[i] << " ";
os << endl;
return os;
}
Is my implementation right? I got a compilation error.
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).
Another way you could do this would be something like the following:
template<typename T>
ostream& operator<<(ostream &out, const std::pair<T, int>& array)
{
//...code
return out;
}
Where T
will take a pointer to an array (i.e., it will be the pointer-type that the array will decay into), and the int
portion of the pair would be the size of the array. You could then use it like the following:
int array[10];
//...some code that initializes array, etc.
cout << make_pair(array, 10);
One plus with this method is it will also work for dynamic arrays (i.e., arrays you allocate on the heap, etc.)
精彩评论