如何在<t>的容器上使用std :: sample返回指针容器<t *>?

时间:2017-10-16 18:29:19

标签: c++ algorithm pointers iterator c++17

我有vector<T> input我希望通过STL C ++ 17(http://en.cppreference.com/w/cpp/algorithm/sample)中的std::sample算法随机选择 n n 。如果results的类型为vector<T>,则代码可以正常运行。

代码示例1(未返回指针)

auto getSamples(unsigned int noSamples, const vector<T> &input)
{
    vector<T> results;
    std::mt19937 twisterEngine;
    std::sample(input.begin(), input.end(), std::back_inserter(results),
        noSamples, twisterEngine);
    return results;
}

但是,我不是要查找input中存储的元素的值/副本,但我想获得指向 n 采样元素的指针。有没有提示如何只使用标准c ++代码(例如不使用boost库等)来获取vector<T*> results返回的指针?如何调整以下代码才能完成?

代码示例2(返回指针的意图)

auto getSamples(unsigned int noSamples, const vector<T> &input)
{
    vector<T*> results;
    std::mt19937 twisterEngine;
    std::sample(input.begin(), input.end(), std::back_inserter(results),
        noSamples, twisterEngine);
    return results;
}

1 个答案:

答案 0 :(得分:3)

您只需要一个OutputIterator。它实际上并没有来发出一些东西,好像它是一个迭代器。它可以......完全做其他事情。比如,调用一个函数。

#include <iterator>

template <class F>
struct function_output_iterator {
    F f;

    using iterator_category = std::output_iterator_tag;
    using value_type = void;
    using difference_type = void;
    using pointer = void;
    using reference = void;

    function_output_iterator& operator++() { return *this; }
    function_output_iterator& operator*() { return *this; }
    function_output_iterator& operator++(int) { return *this; }

    template <class U,
        std::enable_if_t<!std::is_base_of<
            function_output_iterator, std::decay_t<U>>{}, int> = 0>
    void operator=(U&& u) {
        f(std::forward<U>(u));
    }
};

template <class F>
function_output_iterator(F ) -> function_output_iterator<F>;

然后,您可以执行任意操作:

auto getSamples(unsigned int noSamples, const vector<T> &input)
{
    vector<T*> results;
    results.reserve(noSamples);

    std::mt19937 twisterEngine;
    std::sample(input.begin(), input.end(),
        function_output_iterator{[&](T const& elem){ results.push_back(&elem); }, // <==
        noSamples, twisterEngine);
    return results;
}