如何重载运算符<<对于C ++中的数组?

时间:2011-09-16 01:14:57

标签: c++ operator-overloading

我试图这样做:

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

T代表一个数组吗?重载数组的<<运算符是否正确?


修改

根据Kerrek SB的建议,这是<<的实施:

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

我的实施是否合适?我收到了编译错误。

2 个答案:

答案 0 :(得分:7)

你可以这样做:

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

当然,这仅适用于编译时数组。请注意,当T是内置类型或std命名空间中的类型时,不允许您实例化此模板!

如果可能的话,可能最好使其内联,因为您将为每个N引发单独的实例化。 (pretty printer有一个例子。)

你会注意到,一揽子模板引入了歧义,因为os << "Hello"现在有两个可能的重载:匹配const char (&)[6]的模板,以及衰变的(非模板)重载 - to-pointer const char *,它们都具有相同的转换序列。我们可以通过禁用char数组的重载来解决这个问题:

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

事实上,为了更加通用,您还可以制作basic_ostream参数模板参数:

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

鉴于T必须是用户定义的类型,您甚至可以将is_same<T, char>替换为is_fundamental<T>以进行更多检查(但用户仍然不能使用这适用于标准库类型的数组。)

答案 1 :(得分:3)

您可以采用的另一种方法如下:

template<typename T>
ostream& operator<<(ostream &out, const std::pair<T, int>& array)
{
    //...code
    return out;
}

其中T将获取指向数组的指针(即,它将是数组将衰减的指针类型),并且该对的int部分将是数组。然后您可以像下面这样使用它:

int array[10];
//...some code that initializes array, etc.

cout << make_pair(array, 10);

使用此方法的一个优点是它也适用于动态数组(即您在堆上分配的数组等)。