General Utility Library for C++14  2.12
traits.h
Go to the documentation of this file.
1 
15 #ifndef GUL14_TRAITS_H_
16 #define GUL14_TRAITS_H_
17 
18 #include <functional> // for std::invoke on C++17 compilers
19 #include <type_traits>
20 #include <utility>
21 
22 #include "gul14/internal.h"
23 
24 namespace gul14 {
25 
46 template <typename T, typename = int>
47 struct IsContainerLike : std::false_type { };
48 
49 template <typename T>
50 struct IsContainerLike <T,
51  typename std::enable_if_t<true,
52  decltype(std::declval<T>().cbegin(),
53  std::declval<T>().cend(),
54  std::declval<typename T::value_type>(),
55  0)
56  >>
57  : std::true_type { };
58 
68 template <typename T>
69 using remove_cvref = typename std::remove_cv<std::remove_reference_t<T>>;
70 
80 template <typename T>
82 
91 template <typename...>
92 using void_t = void;
93 
94 
95 //
96 // invoke & friends
97 //
98 #if __cplusplus >= 201703L
99 
100 using std::invoke;
101 using std::invoke_result;
103 using std::is_invocable;
104 using std::is_invocable_r;
105 
106 #else
107 
108 namespace detail_invoke {
109 
110 #define GUL14_INVOKE_RETURN(...) \
111  noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
112 
113 template <typename T>
114 struct is_reference_wrapper : std::false_type {};
115 
116 template <typename T>
117 struct is_reference_wrapper<std::reference_wrapper<T>>
118  : std::true_type {};
119 
120 template <bool, int>
121 struct Invoke;
122 
123 template <>
124 struct Invoke<true /* pmf */, 0 /* is_base_of */> {
125  template <typename R, typename T, typename Arg, typename... Args>
126  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
127  GUL14_INVOKE_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
128 };
129 
130 template <>
131 struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
132  template <typename R, typename T, typename Arg, typename... Args>
133  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
134  GUL14_INVOKE_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
135 };
136 
137 template <>
138 struct Invoke<true /* pmf */, 2 /* otherwise */> {
139  template <typename R, typename T, typename Arg, typename... Args>
140  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
141  GUL14_INVOKE_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
142 };
143 
144 template <>
145 struct Invoke<false /* pmo */, 0 /* is_base_of */> {
146  template <typename R, typename T, typename Arg>
147  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
148  GUL14_INVOKE_RETURN(std::forward<Arg>(arg).*pmo)
149 };
150 
151 template <>
152 struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
153  template <typename R, typename T, typename Arg>
154  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
155  GUL14_INVOKE_RETURN(std::forward<Arg>(arg).get().*pmo)
156 };
157 
158 template <>
159 struct Invoke<false /* pmo */, 2 /* otherwise */> {
160  template <typename R, typename T, typename Arg>
161  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
162  GUL14_INVOKE_RETURN((*std::forward<Arg>(arg)).*pmo)
163 };
164 
165 template <typename R, typename T, typename Arg, typename... Args>
166 inline constexpr auto invoke(R T::*f, Arg&& arg, Args&&... args)
167  GUL14_INVOKE_RETURN(
168  Invoke<std::is_function<R>::value,
169  (std::is_base_of<T, std::decay_t<Arg>>::value
170  ? 0
171  : is_reference_wrapper<std::decay_t<Arg>>::value
172  ? 1
173  : 2)>::invoke(f, std::forward<Arg>(arg),
174  std::forward<Args>(args)...))
175 
176 #ifdef _MSC_VER
177 #pragma warning(push)
178 #pragma warning(disable : 4100)
179 #endif
180 template <typename F, typename... Args>
181 inline constexpr auto invoke(F &&f, Args &&... args)
182  GUL14_INVOKE_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
183 #ifdef _MSC_VER
184 #pragma warning(pop)
185 #endif
186 
187 #undef GUL14_INVOKE_RETURN
188 
189 } // namespace detail_invoke
190 
199 template <typename F, typename... Args>
200 inline constexpr auto
201 invoke(F&& f, Args&&... args) noexcept(
202  noexcept(detail_invoke::invoke(std::forward<F>(f), std::forward<Args>(args)...)))
203  -> decltype(detail_invoke::invoke(std::forward<F>(f), std::forward<Args>(args)...))
204 {
205  return detail_invoke::invoke(std::forward<F>(f), std::forward<Args>(args)...);
206 }
207 
208 
209 namespace detail_invoke_result {
210 
211 template <typename T>
212 struct identity { using type = T; };
213 
214 template <typename Void, typename, typename...>
215 struct invoke_result {};
216 
217 template <typename F, typename... Args>
218 struct invoke_result<void_t<decltype(invoke(
219  std::declval<F>(), std::declval<Args>()...))>,
220  F,
221  Args...>
222  : identity<decltype(
223  invoke(std::declval<F>(), std::declval<Args>()...))> {};
224 
225 } // namespace detail_invoke_result
226 
236 template <typename F, typename... Args>
238 
247 template <typename F, typename... Args>
248 using invoke_result_t = typename invoke_result<F, Args...>::type;
249 
250 
251 namespace detail_invocable {
252 
253 template <typename Void, typename, typename...>
254 struct is_invocable : std::false_type {};
255 
256 template <typename F, typename... Args>
257 struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
258  : std::true_type {};
259 
260 template <typename Void, typename, typename, typename...>
261 struct is_invocable_r : std::false_type {};
262 
263 template <typename R, typename F, typename... Args>
264 struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
265  R,
266  F,
267  Args...>
268  : std::is_convertible<invoke_result_t<F, Args...>, R> {};
269 
270 } // namespace detail_invocable
271 
281 template <typename F, typename... Args>
283 
294 template <typename R, typename F, typename... Args>
296 
297 #endif // __cplusplus < 201703L
298 
300 
301 } // namespace gul14
302 
303 #endif
304 
305 // vi:ts=4:sw=4:sts=4:et
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
typename remove_cvref< T >::type remove_cvref_t
A template metafunction that removes const, volatile, and reference qualifiers from a type.
Definition: traits.h:81
typename invoke_result< F, Args... >::type invoke_result_t
A shortcut for invoke_result<...>::type.
Definition: traits.h:248
detail_invoke_result::invoke_result< void, F, Args... > invoke_result
A metafunction that computes the result of invoking a callable object of type F with the given argume...
Definition: traits.h:237
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Invoke a callable object f with the given arguments.
Definition: traits.h:201
void void_t
A type mapping an arbitrary list of types to void (for SFINAE).
Definition: traits.h:92
typename std::remove_cv< std::remove_reference_t< T > > remove_cvref
A template metafunction that removes const, volatile, and reference qualifiers from a type.
Definition: traits.h:69
detail_invocable::is_invocable< void, F, Args... > is_invocable
A type trait that checks whether a callable object of type F can be invoked with the given arguments.
Definition: traits.h:282
detail_invocable::is_invocable_r< void, R, F, Args... > is_invocable_r
A type trait that checks whether a callable object of type F can be invoked with the given arguments ...
Definition: traits.h:295
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
Helper type trait object to determine if a type is a container.
Definition: traits.h:47