How do I write a range pipeline that uses temporary containers?

前端 未结 6 2433
予麋鹿
予麋鹿 2020-11-30 02:09

I have a third-party function with this signature:

std::vector f(T t);

I also have an existing potentially infinite range (of the

6条回答
  •  一个人的身影
    2020-11-30 02:52

    UPDATE

    range-v3 now has views::cache1, a view that caches the most recent element in the view object itself, and returns a reference to that object. That is how this problem is cleanly and efficiently solved today, as pointed out by user @bradgonesurfing in his answer.

    Old, out-of-date answer below, preserved for historical curiosity.


    This is another solution that doesn't require much fancy hacking. It comes at the cost of a call to std::make_shared at each call to f. But you're allocating and populating a container in f anyway, so maybe this is an acceptable cost.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    std::vector f(int i) {
        return std::vector(3u, i);
    }
    
    template 
    struct shared_view : ranges::view_interface> {
    private:
        std::shared_ptr ptr_;
    public:
        shared_view() = default;
        explicit shared_view(Container &&c)
        : ptr_(std::make_shared(std::move(c)))
        {}
        ranges::range_iterator_t begin() const {
            return ranges::begin(*ptr_);
        }
        ranges::range_iterator_t end() const {
            return ranges::end(*ptr_);
        }
    };
    
    struct make_shared_view_fn {
        template ())>
        shared_view> operator()(Container &&c) const {
            return shared_view>{std::forward(c)};
        }
    };
    
    constexpr make_shared_view_fn make_shared_view{};
    
    int main() {
        using namespace ranges;
        auto rng = view::ints | view::transform(compose(make_shared_view, f)) | view::join;
        RANGES_FOR( int i, rng ) {
            std::cout << i << '\n';
        }
    }
    

提交回复
热议问题