如何使用转换包装back_inserter_iterator
之类的OutputIterator?
考虑
std::vector<double> xx;
std::vector<double> yy;
std::vector<double> diff;
auto ba = std::back_inserter(diff);
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), ba);
我想在推回差异向量之前应用自由函数f(double)
或g(std::vector<double>::iterator)
:
具体来说,我如何存储diff元素(或迭代器)的地址而不是元素本身。
std::vector<double&> diff;
auto baAdr = ??? std::back_inserter( ??? (diff));
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), baAdr);
出于性能原因(真实数据很大)我不想构造临时向量和std::transform
。它对于不可复制的可移动类型也不起作用。
我可以使用提升。
答案 0 :(得分:5)
使用boost::function_output_iterator
:
#include <vector>
#include <algorithm>
#include <boost/function_output_iterator.hpp>
int main()
{
std::vector<double> xx;
std::vector<double> yy;
std::vector<const double*> diff; // const pointers, or else you
// need a const_cast in lambda
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(),
boost::make_function_output_iterator(
[&diff](const double& d) { diff.push_back(&d); }
)
);
}
答案 1 :(得分:4)
可能还有一些东西可以用来提升,但是我的hacky尝试编写自己的迭代器:
template <typename T, typename FN>
struct transform_iterator {
transform_iterator(T &t, FN fn)
: _t{t}
, _fn{std::move(fn)} { }
transform_iterator<T, FN>& operator * () { return *this; }
transform_iterator<T, FN>& operator ++ () { return *this; }
template <typename V>
transform_iterator<T, FN>& operator = (V const &v) {
_t.push_back(_fn(v));
return *this;
}
T &_t;
FN _fn;
};
这将采用一个函数并在尝试分配给迭代器时执行它(我认为这就像back_inserter
这样的事情通常起作用)。一个简单的辅助函数可以创建迭代器:
template <typename T, typename FN>
auto make_transform_iterator(T &t, FN fn) {
return transform_iterator<T, FN>{t, std::move(fn)};
};
最后,iterator_traits
需要专业化,因此transform_iterator
可以使用算法。
namespace std {
template <typename T, typename FN>
struct iterator_traits<transform_iterator<T, FN>> {
using value_type = typename T::value_type;
};
}
需要在iterator_traits
中设置更多类型,但这对我的测试来说已经足够了;你的里程会有所不同。
我的main
看起来像这样:
int main() {
std::vector<int> xx{1, 2, 3};
std::vector<int> yy{1, 3, 5};
std::vector<int> diff;
auto ba = make_transform_iterator(diff, [](auto v) { return v + 10; });
std::set_difference(std::begin(xx), std::end(xx),
std::begin(yy), std::end(yy),
ba);
for(auto const &v: diff) {
std::cout << v << '\n';
}
return 0;
}
您可以将其展开以使用通用输出迭代器,而不仅仅是支持push_back
的类型。