我们被教导创建函数对象以使用算法。
有些算法可以调用operator()
,例如:
这些函数对象通常应该从unary_function
或binary_function
继承,表现得像函数,谓词等。
但书籍通常不会展示创建OutputIterators
的示例:
e.g。遍历函数的输出
std::set_intersection()
,我必须提供目标容器,
然后然后遍历结果:
std::vector<int> tmp_dest;
std::set_difference (
src1.begin(), src1.end(),
src2.begin(), src2.end(),
std::back_inserter(tmp_dest));
std::for_each( tmp_dest.begin(), tmp_dest.end(), do_something );
int res = std::accumulate( tmp_dest.begin(), tmp_dest.end(), 0 );
但是认为有时使用每个算法的值而不先存储它们会更有效,例如:
std::set_difference (
src1.begin(), src1.end(),
src2.begin(), src2.end(),
do_something );
Accumulator accumulate(0); // inherits from std::insert_iterator ?
std::set_difference (
src1.begin(), src1.end(),
src2.begin(), src2.end(),
accumulate );
insert_iterator
继承,但它实际上不是迭代器(例如它没有实现operator++()
)有哪些被广泛接受的做法?
答案 0 :(得分:6)
如果您想要一个输出迭代器,为每个接收到的值调用您自己的函数,请使用Boost.Iterator's function_output_iterator。
答案 1 :(得分:4)
我没有看到这个问题的根本问题,只要未来的维护者明白这些代码是如何工作的以及它正在做什么。
我可能不会从任何标准类继承这样的操作(除了给它output_iterator_tag
之外)。由于我们正在处理模板,因此我们不需要处理父接口。
但请记住,你的语句(eg it does not implement operator++() )
似乎不正确:无论你输入什么,因为“输出迭代器”需要满足输出迭代器的要求,包括可复制,取消引用 - 分配,可递增。无论您传递的对象类型是什么,都需要满足这些要求。
答案 2 :(得分:3)
我对此的看法是使用Boost(也显示了set_difference
的Boost Range算法版本,尽管是偏离主题的):
#include <set>
#include <boost/range/algorithm.hpp>
#include <boost/function_output_iterator.hpp>
#include <cassert>
void do_something(int) {}
int main()
{
const std::set<int>
src1 { 1,2,3 },
src2 { 1,9 };
unsigned total = 0;
boost::set_difference(src1, src2,
boost::make_function_output_iterator([&](int i)
{
total += i*i;
}));
assert(total == 13); // 2*2 + 3*3
}
答案 3 :(得分:2)
采用输出迭代器的算法的目标是由输出迭代器表示的值序列。他们使用迭代器有两个原因:
对于某些算法,提供了两个版本,一个具有函数调用接口,另一个具有迭代器接口。例如,这是std::for_each()
和std::copy()
之间的差异。
在任何情况下,如果您只需要一个需要输出迭代器的函数,那么让其他迭代器操作为no-ops并在赋值给*it
时调用该函数:this创建一个完美的valud输出迭代器。
答案 4 :(得分:1)
以下作品:
#include <cassert>
#include <algorithm>
class AccumulatorIterator
{
public:
explicit AccumulatorIterator(int initial) : value(initial) {}
AccumulatorIterator& operator = (int rhs) { value += rhs; return *this; }
AccumulatorIterator& operator *() { return *this; }
AccumulatorIterator& operator ++() { return *this; }
operator int() const { return value; }
private:
int value;
};
int main() {
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
std::sort(std::begin(first), std::end(first)); // 5 10 15 20 25
std::sort(std::begin(second), std::end(second)); // 10 20 30 40 50
const int res = std::set_intersection (std::begin(first), std::end(first),
std::begin(second), std::end(second), AccumulatorIterator(0));
assert(res == 10 + 20);
return 0;
}