【问题标题】:Oveloading the ostream << operator for a sequence重载序列的 ostream << 运算符
【发布时间】:2012-06-01 14:27:20
【问题描述】:

我想定义运算符

std::ostream& operator<< ( std::ostream &out, std::list inList );

因此,无论我使用的是列表、向量、数组等,我都只需要编写一个可以工作的函数。而且我必须使用两个参数调用该函数,inList.begin() 和 inList。结束()

问题是 operator

编辑:感谢您的回答。我可能应该更清楚地说明我希望能够打印一系列元素,可能包括容器的子序列(再次,如 STL 算法)。例如。如果向量 v 有 5 个元素,我希望可以将它们全部打印出来,给出从 v.begin() 到 v.end() 的序列,输出如下:

[element1 element2 element3 element4 element5]

但我希望我也可以只打印前三个,在 [v.begin(), v.begin()+3) 范围内

[element1 element2 element3]

您建议的答案在这种情况下有效吗?

【问题讨论】:

    标签: c++ operator-overloading ostream


    【解决方案1】:

    您无法避免传递一个参数,但您希望某些东西可以与任何类型的容器一起使用。所以理想情况下你会想要一个像

    这样的函数
    template <typename T>
    std::ostream& someFunction(std::ostream& out, T first, T last) {
      // do your stuff
    }
    

    还有一个ostream&amp; operator&lt;&lt; 看起来有点像

    template <T>
    std::ostream& << (std::ostream& out, const T& sequence) {
      return someFunction(out, sequence.begin(), sequence.end());
    }
    

    然而,这个操作符会与预定义的操作符发生冲突,所以你不能就这样实现它。幸运的是,您可以玩一些模板魔术来解决这个问题,并查看一个非常好的解决方案,查看this SO question 和相应的github project

    请注意,由于(可能)目标是为容器提供一个通用的ostream&amp; operator&lt;&lt;,并且您可以通过函数模板来实现这一点,因此让函数接受迭代器并不是必需的。它也可以对容器进行 (const) 引用。

    【讨论】:

      【解决方案2】:

      只传递一个参数,并在方法内部使用beginend。所有标准容器都有beginend。不,您不能将参数数量更改为operator &lt;&lt;

      【讨论】:

      • 1) 请注意,必须编写函数模板,而不是函数。 2) 或许std::begin()std::end() 会更好?
      • @Robᵩ 1) 可能 2) 不明白为什么...它支持主要编译器吗?
      • 2) 因为std::begin() 除了std:: 容器之外还专门针对数组。
      【解决方案3】:

      这是一个老问题,但我最近不得不解决同样的问题,所以我想我会在这里发布我的解决方案。 Range 和 makeRange 复制了 std::pair 和 std::make_pair 的功能,但我添加前者只是为了避免冲突(其他类型的对可能打印不同)。

      #include <iostream>
      
      using namespace std;
      
      template <typename Iterator>
      struct Range
      {
        Range();
        Range(Iterator begin_, Iterator end_) : begin(begin_), end(end_) {}
      
        Iterator begin, end;
      };
      
      template <typename Iterator>
      Range<Iterator>
      makeRange(Iterator begin, Iterator end)
      {
        return Range<Iterator>(begin, end);
      }
      
      template <typename InputIterator>
      ostream &
      operator<<(ostream & out, Range<InputIterator> const & range)
      {
        for (InputIterator iter = range.begin; iter != range.end; ++iter)
        {
          if (iter != range.begin) out << ", ";  // adjust formatting to taste
          out << *iter;
        }
      
        return out;
      }
      
      int
      main(int argc, char * argv[])
      {
        int a[] = { 1, 2, 3, 4, 5 };
        cout << makeRange(a, a + 2) << endl;  // prints 1, 2
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-17
        • 2020-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多