uTL
micro Template library
invoke.h
Go to the documentation of this file.
1 
20 #ifndef __utl_utility_invoke_h__
21 #define __utl_utility_invoke_h__
22 
23 #include <utl/core/impl.h>
24 #include <utl/meta/meta.h>
25 
26 #include <type_traits>
27 #include <functional>
28 #include <utility>
29 
34 namespace utl {
36 
37  namespace detail {
38 
39  template <class T>
41  template <class U>
42  struct is_ref_wrapper<std::reference_wrapper<U>> : meta::true_ {};
43 
44  // 1
45  template <class T, class Type, class T1, class... Args,
47  std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
48  std::is_base_of<T, std::decay_t<T1>>::value,
49  int> =0
50  >
51  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
52  return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
53  }
54 
55  // 2
56  template <class T, class Type, class T1, class... Args,
58  std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
59  is_ref_wrapper<std::decay_t<T1>>::value,
60  int> =0
61  >
62  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
63  return (t1.get().*f)(std::forward<Args>(args)...);
64  }
65 
66  // 3
67  template <class T, class Type, class T1, class... Args,
69  std::is_member_function_pointer<std::decay_t<Type T::*>>::value &&
70  !std::is_base_of<T, std::decay_t<T1>>::value &&
71  !is_ref_wrapper<std::decay_t<T1>>::value,
72  int> =0
73  >
74  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
75  return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
76  }
77 
78  // 4
79  template <class T, class Type, class T1, class... Args,
81  std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
82  std::is_base_of<T, std::decay_t<T1>>::value,
83  int> =0
84  >
85  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
86  return std::forward<T1>(t1).*f;
87  }
88 
89  // 5
90  template <class T, class Type, class T1, class... Args,
92  std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
93  is_ref_wrapper<std::decay_t<T1>>::value,
94  int> =0
95  >
96  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
97  return t1.get().*f;
98  }
99 
100  // 6
101  template <class T, class Type, class T1, class... Args,
103  std::is_member_object_pointer<std::decay_t<Type T::*>>::value &&
104  !std::is_base_of<T, std::decay_t<T1>>::value &&
105  !is_ref_wrapper<std::decay_t<T1>>::value,
106  int> =0
107  >
108  decltype(auto) invoke_impl_(Type T::* f, T1&& t1, Args&&... args) {
109  return (*std::forward<T1>(t1)).*f;
110  }
111 
112  template <class F, class... Args>
113  decltype(auto) invoke_impl_(F&& f, Args&&... args) {
114  return std::forward<F>(f)(std::forward<Args>(args)...);
115  }
116 
117  } // namespace detail
118 
120  template<typename _Callable, typename... _Args>
121  inline decltype(auto) invoke(_Callable&& fn, _Args&&... args) {
122  return detail::invoke_impl_(
123  std::forward<_Callable>(fn), std::forward<_Args>(args)...
124  );
125  }
127 
129  template <typename F, typename... Args>
130  struct is_invocable :
131  std::is_constructible<
132  std::function<void(Args ...)>,
133  std::reference_wrapper<typename std::remove_reference<F>::type>
134  > { };
135 
137  template <typename R, typename F, typename... Args>
138  struct is_invocable_r :
139  std::is_constructible<
140  std::function<R(Args ...)>,
141  std::reference_wrapper<typename std::remove_reference<F>::type>
142  > { };
143 
147  namespace detail {
149  template<typename _Callable, typename... _Args>
150  struct try_invoke {
151  using type = decltype (
152  detail::invoke_impl_(std::declval<_Callable&&>(), std::declval<_Args&&>()...)
153  );
154  };
155 
156  template<bool B, typename _Callable, typename... _Args>
157  struct invoke_result_ {
158  using type = meta::nil_;
159  };
160 
161  template <typename _Callable, typename... _Args>
162  struct invoke_result_ <true, _Callable, _Args...> {
163  using type = meta::invoke_t<
164  meta::quote<try_invoke>, _Callable, _Args...
165  >;
166  };
167  }
169  template <typename _Callable, typename... _Args>
171  is_invocable<_Callable, _Args...>::value,
172  _Callable,
173  _Args...
174  >;
175 
177  template<typename _Callable, typename... _Args>
178  using invoke_result_t = meta::eval <
179  invoke_result<_Callable, _Args...>
180  >;
181 }
182 
184 
185 
186 #endif /* __utl_utility_invoke_h__ */
decltype(auto) invoke_impl_(Type T::*f, T1 &&t1, Args &&... args)
Definition: invoke.h:51
Include all meta library.
decltype(auto) invoke(_Callable &&fn, _Args &&... args)
Invoke a callable object (for C++14)
Definition: invoke.h:121
bool_< true > true_
The type used as a compile-time boolean with true value.
Definition: integral.h:68
STL namespace.
meta::invoke_t< meta::quote< try_invoke >, _Callable, _Args... > type
Definition: invoke.h:165
bool_< false > false_
The type used as a compile-time boolean with false value.
Definition: integral.h:69
typename Tp::type eval
Type alias for Tp::type. Used to evaluate/extract return type of metafunctions.
Definition: integral.h:49
STL&#39;s core language concepts.
Definition: _1wire.h:30
eval< enable_if< If, _Tp > > enable_if_t
alias template for enable_if
Definition: sfinae.h:63
meta::eval< invoke_result< _Callable, _Args... > > invoke_result_t
invoke_result_t (for C++14)
Definition: invoke.h:180
std::is_invocable_r trait for C++11
Definition: invoke.h:138
decltype(detail::invoke_impl_(std::declval< _Callable && >(), std::declval< _Args && >()...)) type
Definition: invoke.h:153
eval< invoke< Fn, Args... > > invoke_t
Definition: invoke.h:88
Implementation detail main forward header.
std::is_invocable trait for C++11
Definition: invoke.h:130