如何将Back_inserter与转换组合C 相结合

How to combine back_inserter with a transformation, C++

本文关键字:转换 组合 相结合 inserter Back      更新时间:2023-10-16

如何通过转换将输出仪(例如back_inserter_iterator(包装?考虑

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);

我想在推回DIFF向量之前应用免费功能f(double)g(std::vector<double>::iterator)

具体来说,我如何存储差异元素(或迭代器(的地址,而不是元素主题。

std::vector<double&> diff;
auto baAdr = ??? std::back_inserter( ??? (diff)); 
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), baAdr);

出于性能原因(实际数据很大(,我不想从中构建临时向量和std::transform。它也不适用于不可仿制的可移动类型。

我可以使用boost。

with 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); }
        )
    );
}

可能内置了一些可以提升的东西,但是这是我编写自己的迭代器的骇人听闻的尝试:

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;
};

这将在尝试分配给迭代器时执行功能并执行它(i think 这就是诸如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的类型。