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
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.