xref: /openbmc/telemetry/src/utils/transform.hpp (revision f32f6fef)
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
50