Wludzik, Jozef | e236279 | 2020-10-27 17:23:55 +0100 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include <algorithm> |
| 4 | #include <iterator> |
| 5 | |
| 6 | namespace utils |
| 7 | { |
| 8 | namespace detail |
| 9 | { |
| 10 | |
| 11 | template <class T> |
| 12 | struct has_member_reserve |
| 13 | { |
| 14 | template <class U> |
| 15 | static U& ref(); |
| 16 | |
| 17 | template <class U> |
| 18 | static std::true_type check(decltype(ref<U>().reserve(size_t{}))*); |
| 19 | |
| 20 | template <class> |
| 21 | static std::false_type check(...); |
| 22 | |
| 23 | static constexpr bool value = |
| 24 | decltype(check<std::decay_t<T>>(nullptr))::value; |
| 25 | }; |
| 26 | |
| 27 | template <class T> |
| 28 | constexpr bool has_member_reserve_v = has_member_reserve<T>::value; |
| 29 | |
| 30 | } // namespace detail |
| 31 | |
| 32 | template <template <class, class...> class Container, class T, class... Args, |
| 33 | class F> |
| 34 | auto transform(const Container<T, Args...>& container, F&& functor) |
| 35 | { |
| 36 | using R = decltype(functor(*container.begin())); |
| 37 | |
| 38 | Container<R> result; |
| 39 | if constexpr (detail::has_member_reserve_v<Container<T, Args...>>) |
| 40 | { |
| 41 | result.reserve(container.size()); |
| 42 | } |
| 43 | std::transform(container.begin(), container.end(), |
| 44 | std::inserter(result, result.end()), |
| 45 | std::forward<F>(functor)); |
| 46 | return result; |
| 47 | } |
| 48 | |
| 49 | } // namespace utils |