| 1 | #pragma once |
| 2 | |
| 3 | #include <type_traits> |
| 4 | #include <boost/iterator/transform_iterator.hpp> |
| 5 | |
| 6 | |
| 7 | namespace ext |
| 8 | { |
| 9 | /// \brief Strip type off top level reference and cv-qualifiers thus allowing storage in containers |
| 10 | template <typename T> |
| 11 | using unqualified_t = std::remove_cv_t<std::remove_reference_t<T>>; |
| 12 | |
| 13 | /** \brief Returns collection of the same container-type as the input collection, |
| 14 | * with each element transformed by the application of `mapper`. |
| 15 | */ |
| 16 | template <template <typename...> class Collection, typename... Params, typename Mapper> |
| 17 | auto map(const Collection<Params...> & collection, const Mapper mapper) |
| 18 | { |
| 19 | using value_type = unqualified_t<decltype(mapper(*std::begin(collection)))>; |
| 20 | |
| 21 | return Collection<value_type>( |
| 22 | boost::make_transform_iterator(std::begin(collection), mapper), |
| 23 | boost::make_transform_iterator(std::end(collection), mapper)); |
| 24 | } |
| 25 | |
| 26 | /** \brief Returns collection of specified container-type, |
| 27 | * with each element transformed by the application of `mapper`. |
| 28 | * Allows conversion between different container-types, e.g. std::vector to std::list |
| 29 | */ |
| 30 | template <template <typename...> class ResultCollection, typename Collection, typename Mapper> |
| 31 | auto map(const Collection & collection, const Mapper mapper) |
| 32 | { |
| 33 | using value_type = unqualified_t<decltype(mapper(*std::begin(collection)))>; |
| 34 | |
| 35 | return ResultCollection<value_type>( |
| 36 | boost::make_transform_iterator(std::begin(collection), mapper), |
| 37 | boost::make_transform_iterator(std::end(collection), mapper)); |
| 38 | } |
| 39 | |
| 40 | /** \brief Returns collection of specified type, |
| 41 | * with each element transformed by the application of `mapper`. |
| 42 | * Allows leveraging implicit conversion between the result of applying `mapper` and R::value_type. |
| 43 | */ |
| 44 | template <typename ResultCollection, typename Collection, typename Mapper> |
| 45 | auto map(const Collection & collection, const Mapper mapper) |
| 46 | { |
| 47 | return ResultCollection( |
| 48 | boost::make_transform_iterator(std::begin(collection), mapper), |
| 49 | boost::make_transform_iterator(std::end(collection), mapper)); |
| 50 | } |
| 51 | } |
| 52 | |