Simulant  21.12-1197
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
type_traits.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef CORE_TYPE_TRAITS_HPP
20 #define CORE_TYPE_TRAITS_HPP
21 
22 #include <type_traits>
23 #include <utility>
24 
25 #if defined(_MSC_VER)
26 #if __cplusplus >= 202002L
27 // C++20 (and later) code
28 #include <version>
29 #else
30 #include <ciso646>
31 #endif
32 #endif
33 
34 namespace smlt {
35 inline namespace v1 {
36 
37 /* custom type traits */
38 /* tuple_size is used by unpack, so we expect it to be available.
39  * We also expect ::std::get<N> to be available for the give type T
40  */
41 template <class T>
43  template <class U> using tuple_size_t = typename ::std::tuple_size<U>::type;
44  template <class U> static void check (tuple_size_t<U>*) noexcept;
45  template <class> static void check (...) noexcept(false);
46 public:
47  static constexpr bool value = noexcept(check<T>(nullptr));
48 };
49 
50 /* Used for types that have a .at(size_type) member function */
51 template <class T>
53  template <class U>
54  static auto check (U* u) noexcept -> decltype(u->at(0ul), void());
55  template <class> static void check (...) noexcept(false);
56 public:
57  static constexpr bool value = noexcept(check<T>(nullptr));
58 };
59 
60 /* extracts the class of a member function ponter */
61 template <class T> struct class_of { using type = T; };
62 template <class Signature, class Type>
63 struct class_of<Signature Type::*> { using type = Type; };
64 
65 /* forward declaration */
66 template <class... Args> struct invokable;
67 template <class... Args> struct invoke_of;
68 template <class T> struct result_of; /* SFINAE result_of */
69 
70 /* C++14 style aliases for standard traits */
71 template <class T>
72 using remove_volatile_t = typename ::std::remove_volatile<T>::type;
73 
74 template <class T>
75 using remove_const_t = typename ::std::remove_const<T>::type;
76 template <class T> using remove_cv_t = typename ::std::remove_cv<T>::type;
77 
78 template <class T>
79 using add_volatile_t = typename ::std::add_volatile<T>::type;
80 template <class T> using add_const_t = typename ::std::add_const<T>::type;
81 template <class T> using add_cv_t = typename ::std::add_cv<T>::type;
82 
83 template <class T>
84 using add_lvalue_reference_t = typename ::std::add_lvalue_reference<T>::type;
85 
86 template <class T>
87 using add_rvalue_reference_t = typename ::std::add_rvalue_reference<T>::type;
88 
89 template <class T>
90 using remove_reference_t = typename ::std::remove_reference<T>::type;
91 
92 template <class T>
93 using remove_pointer_t = typename ::std::remove_pointer<T>::type;
94 
95 template <class T> using add_pointer_t = typename ::std::add_pointer<T>::type;
96 
97 template <class T>
98 using make_unsigned_t = typename ::std::make_unsigned<T>::type;
99 template <class T> using make_signed_t = typename ::std::make_signed<T>::type;
100 
101 template <class T>
102 using remove_extent_t = typename ::std::remove_extent<T>::type;
103 
104 template <class T>
105 using remove_all_extents_t = typename ::std::remove_all_extents<T>::type;
106 
107 template < ::std::size_t Len, ::std::size_t Align>
108 using aligned_storage_t = typename ::std::aligned_storage<Len, Align>::type;
109 
110 template <class T> using decay_t = typename ::std::decay<T>::type;
111 
112 template <bool B, class T = void>
113 using enable_if_t = typename ::std::enable_if<B, T>::type;
114 
115 template <bool B, class T, class F>
116 using conditional_t = typename ::std::conditional<B, T, F>::type;
117 
118 template <class T>
119 using underlying_type_t = typename ::std::underlying_type<T>::type;
120 
121 /* custom type trait specializations */
122 template <class... Args> using invoke_of_t = typename invoke_of<Args...>::type;
123 template <class T> using class_of_t = typename class_of<T>::type;
124 
125 namespace _any_impl {
126 
127 struct undefined { undefined (...); };
128 
129 /* Get the result of an attempt at the INVOKE expression */
130 /* fallback */
131 template <class... Args> auto invoke_expr (undefined, Args&&...) -> undefined;
132 
133 template <class Functor, class Object, class... Args>
134 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
135  ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
136  ::std::is_base_of<
137  class_of_t<remove_reference_t<Functor>>,
138  remove_reference_t<Object>
139  >::value,
140  decltype((::std::forward<Object>(obj).*fun)(::std::forward<Args>(args)...))
141 >;
142 
143 template <class Functor, class Object, class... Args>
144 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
145  ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
146  not ::std::is_base_of<
147  class_of_t<remove_reference_t<Functor>>,
148  remove_reference_t<Object>
149  >::value,
150  decltype(
151  ((*::std::forward<Object>(obj)).*fun)(::std::forward<Args>(args)...)
152  )
153 >;
154 
155 template <class Functor, class Object>
156 auto invoke_expr (Functor&& functor, Object&& object) -> enable_if_t<
157  ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
158  ::std::is_base_of<
159  class_of_t<remove_reference_t<Functor>>,
160  remove_reference_t<Object>
161  >::value,
162  decltype(::std::forward<Object>(object).*functor)
163 >;
164 
165 template <class Functor, class Object>
166 auto invoke_expr (Functor&& functor, Object&& object) -> enable_if_t<
167  ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
168  not ::std::is_base_of<
169  class_of_t<remove_reference_t<Functor>>,
170  remove_reference_t<Object>
171  >::value,
172  decltype((*::std::forward<Object>(object)).*functor)
173 >;
174 
175 template <class Functor, class... Args>
176 auto invoke_expr (Functor&& functor, Args&&... args) -> decltype(
177  ::std::forward<Functor>(functor)(::std::forward<Args>(args)...)
178 );
179 
180 template <bool, class... Args> struct invoke_of { };
181 template <class... Args>
182 struct invoke_of<true, Args...> {
183  using type = decltype(invoke_expr(::std::declval<Args>()...));
184 };
185 
186 /* swappable implementation details */
187 using ::std::declval;
188 using ::std::swap;
189 
190 template <class T, class U>
192  template <class X, class Y>
193  static auto check (int) noexcept -> decltype(
194  swap(declval<X&>(), declval<Y&>()),
195  void()
196  );
197  template <class X, class Y> static void check (...) noexcept(false);
198 public:
199  static constexpr bool value =
200  noexcept(check<T, U>(0)) and noexcept(check<U, T>(0));
201 };
202 
203 template <class T, class U>
204 struct is_nothrow_swappable : ::std::integral_constant<
205  bool,
206  is_swappable<T, U>::value and noexcept(swap(declval<T&>(), declval<U&>()))
207 > { };
208 
209 } /* namespace impl */
210 
211 template <class... Args> struct invokable : ::std::integral_constant<
212  bool,
213  not ::std::is_same<
214  decltype(_any_impl::invoke_expr(::std::declval<Args>()...)),
215  _any_impl::undefined
216  >::value
217 > { };
218 
219 template <class... Args> struct invoke_of :
220  _any_impl::invoke_of<invokable<Args...>::value, Args...>
221 { };
222 
223 template <class F, class... Args>
224 struct result_of<F(Args...)> : invoke_of<F, Args...> { };
225 
226 template <class T> using result_of_t = typename result_of<T>::type;
227 
228 template <class... Ts> struct common_type;
229 
230 template <class T> struct common_type<T> { using type = decay_t<T>; };
231 template <class T, class U>
232 struct common_type<T, U> {
233  using type = decay_t<
234  decltype(true ? ::std::declval<T>() : ::std::declval<U>())
235  >;
236 };
237 
238 template <class T, class U, class... Ts>
239 struct common_type<T, U, Ts...> {
240  using type = typename common_type<
241  typename common_type<T, U>::type,
242  Ts...
243  >::type;
244 };
245 
246 template <class... T> using common_type_t = typename common_type<T...>::type;
247 
248 /* is_null_pointer */
249 template <class T> struct is_null_pointer : ::std::false_type { };
250 
251 template <>
252 struct is_null_pointer<add_cv_t< ::std::nullptr_t>> : ::std::true_type { };
253 template <>
254 struct is_null_pointer< ::std::nullptr_t volatile> : ::std::true_type { };
255 template <>
256 struct is_null_pointer< ::std::nullptr_t const> : ::std::true_type { };
257 template <>
258 struct is_null_pointer< ::std::nullptr_t> : ::std::true_type { };
259 
260 /* is_swappable */
261 template <class T, class U=T>
262 using is_swappable = ::std::integral_constant<
263  bool,
265 >;
266 
267 /* is_nothrow_swappable */
268 template <class T, class U=T>
270 
271 /* all-traits */
272 template <class...> struct all_traits;
273 template <class T, class... Args>
274 struct all_traits<T, Args...> : ::std::integral_constant<bool,
275  T::value and all_traits<Args...>::value
276 > { };
277 template <> struct all_traits<> : ::std::true_type { };
278 
279 /* any-traits */
280 template <class...> struct any_traits;
281 template <class T, class... Args>
282 struct any_traits<T, Args...> : ::std::integral_constant<bool,
283  T::value or any_traits<Args...>::value
284 > { };
285 template <> struct any_traits<> : ::std::false_type { };
286 
287 /* no-traits */
288 template <class... Args> struct no_traits : ::std::integral_constant<bool,
289  not all_traits<Args...>::value
290 > { };
291 
292 }} /* namespace core::v1 */
293 
294 #endif /* CORE_TYPE_TRAITS_HPP */
smlt::v1::common_type
Definition: type_traits.h:228
smlt::v1::_any_impl::is_nothrow_swappable
Definition: type_traits.h:207
smlt::v1::no_traits
Definition: type_traits.h:290
smlt::v1::is_runpackable
Definition: type_traits.h:52
smlt::v1::result_of
Definition: type_traits.h:68
smlt::v1::all_traits
Definition: type_traits.h:272
smlt::v1::_any_impl::undefined
Definition: type_traits.h:127
smlt
Definition: animation.cpp:25
smlt::v1::invokable
Definition: type_traits.h:217
smlt::v1::any_traits
Definition: type_traits.h:280
smlt::v1::_any_impl::is_swappable
Definition: type_traits.h:191
smlt::v1::is_unpackable
Definition: type_traits.h:42
smlt::v1::is_null_pointer
Definition: type_traits.h:249
smlt::v1::invoke_of
Definition: type_traits.h:221
smlt::v1::class_of
Definition: type_traits.h:61
smlt::v1::_any_impl::invoke_of
Definition: type_traits.h:180