Mercury Currency Engine
function_utility.hpp
Go to the documentation of this file.
1 //SPDX-License-Identifier: Apache-2.0
2 //Author: Blayne Dennis
7 #ifndef __MERCURY_COROUTINE_ENGINE_FUNCTION_UTILITY__
8 #define __MERCURY_COROUTINE_ENGINE_FUNCTION_UTILITY__
9 
10 // c++
11 #include <type_traits>
12 #include <functional>
13 
14 namespace mce {
15 namespace detail {
16 
17 template <typename T>
18 using unqualified = typename std::decay<T>::type;
19 
20 // handle pre and post c++17
21 #if __cplusplus >= 201703L
22 template <typename F, typename... Ts>
23 using function_return_type = typename std::invoke_result<unqualified<F>,Ts...>::type;
24 #else
25 template <typename F, typename... Ts>
26 using function_return_type = typename std::result_of<unqualified<F>(Ts...)>::type;
27 #endif
28 
29 // Convert void type to int
30 template <typename T>
32 {
33  typedef T type;
34 };
35 
36 template <>
37 struct convert_void_<void>
38 {
39  typedef int type;
40 };
41 
42 template <typename F, typename... A>
43 using convert_void_return = typename convert_void_<function_return_type<F,A...>>::type;
44 
45 template<typename T, typename _ = void>
46 struct is_container : std::false_type {};
47 
48 template<typename... Ts>
50 
51 template< bool B, class T, class F >
52 using conditional_t = typename std::conditional<B,T,F>::type;
53 
54 template<typename T>
55 struct is_container<
56  T,
57  conditional_t<
58  false,
60  typename T::value_type,
61  typename T::iterator,
62  decltype(std::declval<T>().begin()),
63  decltype(std::declval<T>().end())
64  >,
65  void
66  >
67  > : public std::true_type {};
68 
69 }
70 
72 using thunk = std::function<void()>;
73 
74 namespace detail {
75 
77 template <typename F, typename... A>
78 std::function<detail::function_return_type<F,A...>()>
79 wrap_args(F&& func, A&&... args)
80 {
81  return std::bind(std::forward<F>(func), std::forward<A>(args)...);
82 }
83 
84 // implicitly convertable to thunk
85 inline thunk wrap_return(std::true_type, thunk th)
86 {
87  return th;
88 }
89 
90 // fallback template to wrap Callable with non-void return type
91 template <typename Callable>
92 thunk wrap_return(std::false_type, Callable&& cb)
93 {
94  // Convertable to thunk whose 'inner' procedure can be rvalue constructed.
95  // This is a workaround to a limitation in c++11 lambdas which don't have an
96  // obvious mechanism for rvalue copy capturing
97  struct wrapper
98  {
99  inline void operator()(){ inner(); } // ignores return type
100  Callable inner; // move or copy constructable
101  };
102 
103  return wrapper{ std::forward<Callable>(cb) };
104 }
105 
106 }
107 
108 // handle case where Callable is passed no bind arguments
109 template <typename Callable>
110 thunk make_thunk(Callable&& cb)
111 {
112  // determine return type
113  using isv = typename std::is_void<detail::function_return_type<Callable>>;
114  return detail::wrap_return(
115  std::integral_constant<bool,isv::value>(),
116  std::forward<Callable>(cb));
117 }
118 
119 /*
120 Allows any input function (assuming any required input arguments are passed to
121 this procedure) to be converted to a thunk, abstracting away the function's
122 behavior.
123 */
124 template <typename Callable, typename A, typename... As>
125 thunk make_thunk(Callable&& cb, A&& a, As&&... as)
126 {
127  return make_thunk(
128  // convert to a Callable with no arguments
129  detail::wrap_args(
130  std::forward<Callable>(cb),
131  std::forward<A>(a),
132  std::forward<As>(as)...));
133 }
134 
135 }
136 
137 #endif
std::function< void()> thunk
thunk type definition. Also known as a nullary function
Definition: function_utility.hpp:72
std::function< detail::function_return_type< F, A... >)> wrap_args(F &&func, A &&... args)
std::bind arguments to an std::function
Definition: function_utility.hpp:79
Definition: function_utility.hpp:32
Definition: function_utility.hpp:49
Definition: function_utility.hpp:46