为序列加载 ostream <<运算符

Oveloading the ostream << operator for a sequence

本文关键字:lt 运算符 ostream 加载      更新时间:2023-10-16

我想定义运算符<<对元素序列进行操作,就像 STL 算法的工作方式一样,通过将容器的第一个和最后一个元素作为参数。与只接受一个参数相反,容器本身,例如

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

这样我只需要编写一个函数,无论我是否使用列表、向量、数组等,它都可以工作。我必须用两个参数调用函数,inList.begin() 和 inList.end()

问题是运算符<<只接受一个参数。克服这个问题的最佳方法是什么?

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

[element1 element2 element3 element4 element5]

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

[element1 element2 element3]

在这种情况下,您建议的答案是否有效?

你不能逃避传递一个参数,但你想要一些东西可以与任何类型的容器一起工作。所以理想情况下,你会想要一个像

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

和一个看起来像ostream& operator<<

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

但是,此运算符将与预定义的运算符冲突,因此您不能像那样实现它。幸运的是,您可以玩一些模板魔术来解决这个问题,并看到一个非常好的解决方案,请查看此SO问题和相应的github项目

请注意,由于(大概)目标是为容器提供通用ostream& operator<<,并且您将通过函数模板实现此目的,因此不必让函数采用迭代器。它也可以采用(const)引用容器。

只传递一个参数,并在方法内部获取beginend。所有标准容器都有beginend。不,您不能将参数的数量更改为operator <<.

这是一个老问题,但我最近不得不解决同样的问题,所以我想我会在这里发布我的解决方案。Range 和 makeRange 复制了 std::p air 和 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
}