重载运算符<<(&)用于stl容器

时间:2017-07-26 12:10:51

标签: c++ c++11 templates stl operator-overloading

我正在尝试为stl容器重载operator<<()(即插入器运算符)(例如vectorlistarray)(即任何支持基于范围的容器for循环,其value_type也有operator<<()的重载。我写了以下模板函数

template <template <class...> class TT, class ...T>
ostream& operator<<(ostream& out, const TT<T...>& c)
{
    out << "[ ";

    for(auto x : c)
    {
        out << x << " ";
    }

    out << "]";
}

适用于vectorlist。但是当我尝试为array

调用它时会出错
int main()
{
    vector<int> v{1, 2, 3};
    list<double> ld = {1.2, 2.5, 3.3};
    array<int, 3> aa = {1, 2, 3};

    cout << v << endl;  // okay
    cout << ld << endl; // okay
    cout << aa << endl; // error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
                        // cout << aa << endl;
                        //         ^
}

为什么它不适用于array? 有没有解决这个问题的工作?

我在互联网上搜索了SO以查找是否有办法为stl容器重载operator<<()。 我已经在overloading << operator for c++ stl containers中阅读了答案,但它没有回答我的问题。 Pretty-print C++ STL containers中的答案似乎与我相符。

g ++版本: g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

编译命令: g++ -std=c++11

2 个答案:

答案 0 :(得分:3)

看看template <class...> class TT。此参数适用于模板,任何接受任意数量类型参数的模板。

现在看看std::array<class T, std::size_t N>。此模板不接受类型作为第二个参数。它接受一个整数常数。

因此它不能是您定义的模板函数的参数,并且模板参数推导因此而失败。

至于使其工作,最简单的方法是提供仅接受std::array的(模板化)重载。模板参数将是(推导的)数组参数。

template<typename T, std::size_t N>
ostream& operator<<(ostream& out, std::array<T, N> const& a)
{
    out << "[ ";

    for(auto x : a)
    {
        out << x << " ";
    }

    out << "]";
    return out;
}

答案 1 :(得分:3)

您的重载不适用于std::array,因为它与std::array使用的模板不匹配。与所有其他标准容器不同,std::array在其模板参数列表中具有非类型模板参数。它被定义为

template<typename T, std::size_t N>
struct array;

这不适用于template <template <class...> class TT, class ...T>,因为它只使用类型而不允许使用非类型std::size_t N部分。

如果你添加这个重载它应该工作

template <class T, std::size_t N>
ostream& operator<<(ostream& out, std::array<T, N>& c)
{
    out << "[ ";

    for(auto x : c)
    {
        out << x << " ";
    }

    out << "]";

    return out;
}

另请注意,您没有在重载中返回out。这是未定义的行为,因为您告诉编译器您正在返回一些内容,但是您没有这样做。