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