【问题标题】:Overloading operator<<() for stl containers为 stl 容器重载 operator<<()
【发布时间】:2018-01-01 18:10:51
【问题描述】:

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

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? 有什么办法可以解决这个问题吗?

我在互联网上进行了搜索,以查找是否有办法为 stl 容器重载 operator&lt;&lt;()。 我已经阅读了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

【问题讨论】:

  • 尽管没有返回 void,但您的运算符未能返回值。
  • 好吧,你要么从你链接的问题中得到复杂的答案(需要复杂性),要么为不同的容器编写不同的重载。毕竟只有少数几个容器。

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


【解决方案1】:

看看template &lt;class...&gt; class TT。此参数用于模板,任何接受任意数量的 type 参数的模板。

现在看看std::array&lt;class T, std::size_t N&gt;。此模板不接受 type 作为第二个参数。它接受一个整数常量。

所以它不能是你定义的模板函数的参数,因此模板参数推导失败。

至于让它工作,最简单的方法是提供一个(模板化的)重载,它只接受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;
}

【讨论】:

  • 有了这个重载,它适用于std::array。但不具有 C 风格的数组。我需要另一个重载吗?
  • @army007 - 很遗憾,是的。 (ostream&amp; out, T (&amp;a)[N])。此时,您可能希望将打印逻辑移至接受迭代器的模板。并将 many 重载转换为转发给它的简单包装器。
【解决方案2】:

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

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

这不适用于 template &lt;template &lt;class...&gt; class TT, class ...T&gt;,因为它只使用类型并且不允许使用非类型 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。这是未定义的行为,因为您告诉编译器您正在返回某些内容但您没有这样做。

【讨论】:

  • @tobi303 好电话。意思是说非类型模板参数
猜你喜欢
  • 2012-01-19
  • 2011-02-12
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 2014-12-07
相关资源
最近更新 更多