重载ostream<<序列的运算符

时间:2012-06-01 14:27:21

标签: c++ operator-overloading ostream

我想定义运算符<<以类似于STL算法的方式操作一系列元素,通过将容器的第一个和最后一个元素作为参数。与仅采用一个参数相反,容器本身,例如

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

因此,我只需编写一个无论是否使用list,vector,array等都可以工作的函数。我必须使用两个参数inList.begin()和inList调用该函数。端()

问题是运营商&lt;&lt;只需要一个参数。克服这个问题的最佳方法是什么?

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

[element1 element2 element3 element4 element5]

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

[element1 element2 element3]

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

3 个答案:

答案 0 :(得分:2)

你无法摆脱传递一个论点,但你希望某些容器可以使用。理想情况下,你会想要一个像

这样的函数
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());
}

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

请注意,由于(可能)目标是为容器设置通用ostream& operator<<,并且您可以通过函数模板实现此目的,因此使函数采用迭代器并不是必需的。它也可以对容器进行(const)引用。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

这是一个老问题,但我最近必须解决同样的问题,所以我想在这里发布我的解决方案。 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
}