Lely core libraries 2.3.4
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
30namespace lely {
31namespace compat {
32
33#if __cplusplus <= 201703L
34
35template <class T>
37 using type = typename ::std::remove_cv<
38 typename ::std::remove_reference<T>::type>::type;
39};
40
41template <class T>
42using remove_cvref_t = typename remove_cvref<T>::type;
43
44#endif // __cplusplus <= 201703L
45
46#if __cplusplus >= 201703L
47
48using ::std::bool_constant;
49
50using ::std::invoke_result;
51using ::std::invoke_result_t;
52
53using ::std::is_invocable;
54using ::std::is_invocable_r;
55
56using ::std::void_t;
57
58using ::std::conjunction;
59using ::std::disjunction;
60using ::std::negation;
61
62#else // __cplusplus < 201703L
63
64template <bool B>
65using bool_constant = ::std::integral_constant<bool, B>;
66
67namespace detail {
68
69template <class T>
70struct is_reference_wrapper : ::std::false_type {};
71
72template <class U>
73struct is_reference_wrapper<::std::reference_wrapper<U>> : ::std::true_type {};
74
75template <class T>
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
91template <class MT, class B>
92struct 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
137template <class F, class... Args, class Fd = typename ::std::decay<F>::type>
138inline auto
139invoke(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
146template <class, class, class...>
148
149template <class F, class... Args>
150struct 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
165template <class F, class... Args>
166struct invoke_result : detail::invoke_result<void, F, Args...> {};
167
168template <class F, class... Args>
169using invoke_result_t = typename invoke_result<F, Args...>::type;
170
171namespace detail {
172
173template <class>
174struct make_void {
175 using type = void;
176};
177
178} // namespace detail
179
185template <class... T>
186using void_t = typename detail::make_void<T...>::type;
187
188namespace detail {
189
190template <class, class, class = void>
191struct is_invocable : ::std::false_type {};
192
193template <class Result, class R>
194struct 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
205template <class F, class... Args>
206struct is_invocable : detail::is_invocable<invoke_result<F, Args...>, void> {};
207
214template <class R, class F, class... Args>
215struct is_invocable_r : detail::is_invocable<invoke_result<F, Args...>, R> {};
216
221template <class... B>
222struct conjunction : ::std::true_type {};
223
224template <class B1>
225struct conjunction<B1> : B1 {};
226
227template <class B1, class... Bn>
228struct conjunction<B1, Bn...>
229 : ::std::conditional<static_cast<bool>(B1::value), conjunction<Bn...>,
230 B1>::type {};
231
236template <class... B>
237struct disjunction : ::std::false_type {};
238
239template <class B1>
240struct disjunction<B1> : B1 {};
241
242template <class B1, class... Bn>
243struct disjunction<B1, Bn...>
244 : ::std::conditional<static_cast<bool>(B1::value), B1,
245 disjunction<Bn...>>::type {};
246
248template <class B>
249struct 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_
This header file is part of the Lely libraries; it contains the compiler feature definitions.
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
typename detail::make_void< T... >::type void_t
Utility metafunction that maps a sequence of any types to the type void.
Forms the logical conjunction of the type traits B..., effectively performing a logical AND on the se...
Forms the logical disjunction of the type traits B..., effectively performing a logical OR on the seq...
Deduces the return type of an INVOKE expression at compile time.
Determines whether F can be invoked with the arguments Args... to yield a result that is convertable ...
Determines whether F can be invoked with the arguments Args....
Forms the logical negation of the type trait B.