The std::transform-like function that returns transformed container

后端 未结 5 918
心在旅途
心在旅途 2020-12-04 21:59

I\'m trying to implement a function similar to std::transform algorithm but instead of taking the output iterator by an argument I want to create and return a c

5条回答
  •  自闭症患者
    2020-12-04 22:37

    I wrote a blog post to solve a similar problem recently. Using templates and the iterator interface was the route I chose to follow.

    for_each:

    To cut down on the amount of boilerplate, we're going to create a using clause that allows us to grab the type contained within an iterator:

    template 
    using ItemType = typename std::iterator_traits::value_type;
    

    With that in place, we can implement a helper function for_each like so:

    template 
    void for_each(IteratorType &items, std::function const &item)> forEachCb)
    {
        for (typename IteratorType::iterator ptr = items.begin(); ptr != items.end(); ++ptr)
            forEachCb(*ptr);
    }
    

    transform_container:

    Finally transform_container, could be implemented like so:

    template 
    ReturnType transform_container(IteratorType &items, std::function(ItemType const &item)> mapCb)
    {
        ReturnType mappedIterator;
        for_each(items, [&mappedIterator, &mapCb](auto &item) { mappedIterator.insert(mappedIterator.end(), mapCb(item)); });
        return mappedIterator;
    }
    

    Which will allow us to call your two examples in the following way:

    std::vector vi{ 1, 2, 3, 4, 5 };
    auto vs = transform_container, std::vector>(vi, [](int i){return std::to_string(i);});
    assert(vs == std::vector({"1", "2", "3", "4", "5"}));
    
    std::set si{ 5, 10, 15 };
    auto sd = transform_container, std::set>(si, [] (int i) { return i / 2.; }); 
    assert(sd == std::set({5/2., 10/2., 15/2.}));
    

    My blog post also goes into a little more detail if that's helpful.

提交回复
热议问题