Lely core libraries  2.2.5
type_traits.hpp
Go to the documentation of this file.
1 
22 #ifndef LELY_LIBC_TYPE_TRAITS_HPP_
23 #define LELY_LIBC_TYPE_TRAITS_HPP_
24 
25 #include <lely/features.h>
26 
27 #include <type_traits>
28 #include <utility>
29 
30 namespace lely {
31 namespace compat {
32 
33 #if __cplusplus <= 201703L
34 
35 template <class T>
36 struct remove_cvref {
37  using type = typename ::std::remove_cv<
38  typename ::std::remove_reference<T>::type>::type;
39 };
40 
41 template <class T>
42 using remove_cvref_t = typename remove_cvref<T>::type;
43 
44 #endif // __cplusplus <= 201703L
45 
46 #if __cplusplus >= 201703L
47 
48 using ::std::bool_constant;
49 
50 using ::std::invoke_result;
51 using ::std::invoke_result_t;
52 
53 using ::std::is_invocable;
54 using ::std::is_invocable_r;
55 
56 using ::std::void_t;
57 
58 using ::std::conjunction;
59 using ::std::disjunction;
60 using ::std::negation;
61 
62 #else // __cplusplus < 201703L
63 
64 template <bool B>
65 using bool_constant = ::std::integral_constant<bool, B>;
66 
67 namespace detail {
68 
69 template <class T>
70 struct is_reference_wrapper : ::std::false_type {};
71 
72 template <class U>
73 struct is_reference_wrapper<::std::reference_wrapper<U>> : ::std::true_type {};
74 
75 template <class T>
76 struct invoke_impl {
77  template <class F, class... Args>
78  static auto
79  call(F&& f, Args&&... args)
80  -> decltype(::std::forward<F>(f)(::std::forward<Args>(args)...)) {
81  return ::std::forward<F>(f)(::std::forward<Args>(args)...);
82  }
83 
84  template <class F, class... Args>
85  static constexpr bool
86  is_nothrow() {
87  return noexcept(::std::declval<F>()(::std::declval<Args>()...));
88  }
89 };
90 
91 template <class MT, class B>
92 struct invoke_impl<MT B::*> {
93  template <
94  class T, class Td = typename ::std::decay<T>::type,
95  class = typename ::std::enable_if<::std::is_base_of<B, Td>::value>::type>
96  static T&&
97  get(T&& t) {
98  return static_cast<T&&>(t);
99  }
100 
101  template <
102  class T, class Td = typename ::std::decay<T>::type,
103  class = typename ::std::enable_if<is_reference_wrapper<Td>::value>::type>
104  static auto
105  get(T&& t) -> decltype(t.get()) {
106  return t.get();
107  }
108 
109  template <
110  class T, class Td = typename ::std::decay<T>::type,
111  class = typename ::std::enable_if<!::std::is_base_of<B, Td>::value>::type,
112  class = typename ::std::enable_if<!is_reference_wrapper<Td>::value>::type>
113  static auto
114  get(T&& t) -> decltype(*::std::forward<T>(t)) {
115  return *::std::forward<T>(t);
116  }
117 
118  template <
119  class T, class... Args, class MT1,
120  class = typename ::std::enable_if<::std::is_function<MT1>::value>::type>
121  static auto
122  call(MT1 B::*pmf, T&& t, Args&&... args)
123  -> decltype((invoke_impl::get(::std::forward<T>(t)).*
124  pmf)(::std::forward<Args>(args)...)) {
125  return (invoke_impl::get(::std::forward<T>(t)).*
126  pmf)(::std::forward<Args>(args)...);
127  }
128 
129  template <class T>
130  static auto
131  call(MT B::*pmd, T&& t)
132  -> decltype(invoke_impl::get(::std::forward<T>(t)).*pmd) {
133  return invoke_impl::get(::std::forward<T>(t)).*pmd;
134  }
135 };
136 
137 template <class F, class... Args, class Fd = typename ::std::decay<F>::type>
138 inline auto
139 invoke(F&& f, Args&&... args)
140  -> decltype(invoke_impl<Fd>::call(::std::forward<F>(f),
141  ::std::forward<Args>(args)...)) {
142  return invoke_impl<Fd>::call(::std::forward<F>(f),
143  ::std::forward<Args>(args)...);
144 }
145 
146 template <class, class, class...>
147 struct invoke_result {};
148 
149 template <class F, class... Args>
150 struct invoke_result<decltype(void(invoke(::std::declval<F>(),
151  ::std::declval<Args>()...))),
152  F, Args...> {
153  using type = decltype(invoke(::std::declval<F>(), ::std::declval<Args>()...));
154 };
155 
156 } // namespace detail
157 
165 template <class F, class... Args>
166 struct invoke_result : detail::invoke_result<void, F, Args...> {};
167 
168 template <class F, class... Args>
169 using invoke_result_t = typename invoke_result<F, Args...>::type;
170 
171 namespace detail {
172 
173 template <class>
174 struct make_void {
175  using type = void;
176 };
177 
178 } // namespace detail
179 
185 template <class... T>
186 using void_t = typename detail::make_void<T...>::type;
187 
188 namespace detail {
189 
190 template <class, class, class = void>
191 struct is_invocable : ::std::false_type {};
192 
193 template <class Result, class R>
194 struct is_invocable<Result, R, typename make_void<typename Result::type>::type>
195  : bool_constant<::std::is_void<R>::value ||
196  ::std::is_convertible<typename Result::type, R>::value> {};
197 
198 } // namespace detail
199 
205 template <class F, class... Args>
206 struct is_invocable : detail::is_invocable<invoke_result<F, Args...>, void> {};
207 
214 template <class R, class F, class... Args>
215 struct is_invocable_r : detail::is_invocable<invoke_result<F, Args...>, R> {};
216 
221 template <class... B>
222 struct conjunction : ::std::true_type {};
223 
224 template <class B1>
225 struct conjunction<B1> : B1 {};
226 
227 template <class B1, class... Bn>
228 struct conjunction<B1, Bn...>
229  : ::std::conditional<static_cast<bool>(B1::value), conjunction<Bn...>,
230  B1>::type {};
231 
236 template <class... B>
237 struct disjunction : ::std::false_type {};
238 
239 template <class B1>
240 struct disjunction<B1> : B1 {};
241 
242 template <class B1, class... Bn>
243 struct disjunction<B1, Bn...>
244  : ::std::conditional<static_cast<bool>(B1::value), B1,
245  disjunction<Bn...>>::type {};
246 
248 template <class B>
249 struct negation : bool_constant<!static_cast<bool>(B::value)> {};
250 
251 #endif // __cplusplus < 201703L
252 
253 } // namespace compat
254 } // namespace lely
255 
256 #endif // !LELY_LIBC_TYPE_TRAITS_HPP_
Determines whether F can be invoked with the arguments Args....
Forms the logical disjunction of the type traits B..., effectively performing a logical OR on the seq...
Forms the logical negation of the type trait B.
typename detail::make_void< T... >::type void_t
Utility metafunction that maps a sequence of any types to the type void.
Determines whether F can be invoked with the arguments Args... to yield a result that is convertable ...
invoke_result_t< F, Args... > invoke(F &&f, Args &&... args)
Invokes f with the arguments args... as if by INVOKE(forward<F>(f), forward<Args>(args)...).
Definition: functional.hpp:48
Definition: buf.hpp:32
This header file is part of the Lely libraries; it contains the compiler feature definitions.
Deduces the return type of an INVOKE expression at compile time.
Forms the logical conjunction of the type traits B..., effectively performing a logical AND on the se...