1#pragma once
2
3#include <type_traits>
4#include <boost/iterator/transform_iterator.hpp>
5
6
7namespace 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