Simulant  21.09-46
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 namespace smlt {
26 inline namespace v1 {
27 
28 /* custom type traits */
29 /* tuple_size is used by unpack, so we expect it to be available.
30  * We also expect ::std::get<N> to be available for the give type T
31  */
32 template <class T>
34  template <class U> using tuple_size_t = typename ::std::tuple_size<U>::type;
35  template <class U> static void check (tuple_size_t<U>*) noexcept;
36  template <class> static void check (...) noexcept(false);
37 public:
38  static constexpr bool value = noexcept(check<T>(nullptr));
39 };
40 
41 /* Used for types that have a .at(size_type) member function */
42 template <class T>
44  template <class U>
45  static auto check (U* u) noexcept -> decltype(u->at(0ul), void());
46  template <class> static void check (...) noexcept(false);
47 public:
48  static constexpr bool value = noexcept(check<T>(nullptr));
49 };
50 
51 /* extracts the class of a member function ponter */
52 template <class T> struct class_of { using type = T; };
53 template <class Signature, class Type>
54 struct class_of<Signature Type::*> { using type = Type; };
55 
56 /* forward declaration */
57 template <class... Args> struct invokable;
58 template <class... Args> struct invoke_of;
59 template <class T> struct result_of; /* SFINAE result_of */
60 
61 /* C++14 style aliases for standard traits */
62 template <class T>
63 using remove_volatile_t = typename ::std::remove_volatile<T>::type;
64 
65 template <class T>
66 using remove_const_t = typename ::std::remove_const<T>::type;
67 template <class T> using remove_cv_t = typename ::std::remove_cv<T>::type;
68 
69 template <class T>
70 using add_volatile_t = typename ::std::add_volatile<T>::type;
71 template <class T> using add_const_t = typename ::std::add_const<T>::type;
72 template <class T> using add_cv_t = typename ::std::add_cv<T>::type;
73 
74 template <class T>
75 using add_lvalue_reference_t = typename ::std::add_lvalue_reference<T>::type;
76 
77 template <class T>
78 using add_rvalue_reference_t = typename ::std::add_rvalue_reference<T>::type;
79 
80 template <class T>
81 using remove_reference_t = typename ::std::remove_reference<T>::type;
82 
83 template <class T>
84 using remove_pointer_t = typename ::std::remove_pointer<T>::type;
85 
86 template <class T> using add_pointer_t = typename ::std::add_pointer<T>::type;
87 
88 template <class T>
89 using make_unsigned_t = typename ::std::make_unsigned<T>::type;
90 template <class T> using make_signed_t = typename ::std::make_signed<T>::type;
91 
92 template <class T>
93 using remove_extent_t = typename ::std::remove_extent<T>::type;
94 
95 template <class T>
96 using remove_all_extents_t = typename ::std::remove_all_extents<T>::type;
97 
98 template < ::std::size_t Len, ::std::size_t Align>
99 using aligned_storage_t = typename ::std::aligned_storage<Len, Align>::type;
100 
101 template <class T> using decay_t = typename ::std::decay<T>::type;
102 
103 template <bool B, class T = void>
104 using enable_if_t = typename ::std::enable_if<B, T>::type;
105 
106 template <bool B, class T, class F>
107 using conditional_t = typename ::std::conditional<B, T, F>::type;
108 
109 template <class T>
110 using underlying_type_t = typename ::std::underlying_type<T>::type;
111 
112 /* custom type trait specializations */
113 template <class... Args> using invoke_of_t = typename invoke_of<Args...>::type;
114 template <class T> using class_of_t = typename class_of<T>::type;
115 
116 namespace impl {
117 
118 struct undefined { undefined (...); };
119 
120 /* Get the result of an attempt at the INVOKE expression */
121 /* fallback */
122 template <class... Args> auto invoke_expr (undefined, Args&&...) -> undefined;
123 
124 template <class Functor, class Object, class... Args>
125 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
126  ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
127  ::std::is_base_of<
128  class_of_t<remove_reference_t<Functor>>,
129  remove_reference_t<Object>
130  >::value,
131  decltype((::std::forward<Object>(obj).*fun)(::std::forward<Args>(args)...))
132 >;
133 
134 template <class Functor, class Object, class... Args>
135 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
136  ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
137  not ::std::is_base_of<
138  class_of_t<remove_reference_t<Functor>>,
139  remove_reference_t<Object>
140  >::value,
141  decltype(
142  ((*::std::forward<Object>(obj)).*fun)(::std::forward<Args>(args)...)
143  )
144 >;
145 
146 template <class Functor, class Object>
147 auto invoke_expr (Functor&& functor, Object&& object) -> enable_if_t<
148  ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
149  ::std::is_base_of<
150  class_of_t<remove_reference_t<Functor>>,
151  remove_reference_t<Object>
152  >::value,
153  decltype(::std::forward<Object>(object).*functor)
154 >;
155 
156 template <class Functor, class Object>
157 auto invoke_expr (Functor&& functor, Object&& object) -> enable_if_t<
158  ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
159  not ::std::is_base_of<
160  class_of_t<remove_reference_t<Functor>>,
161  remove_reference_t<Object>
162  >::value,
163  decltype((*::std::forward<Object>(object)).*functor)
164 >;
165 
166 template <class Functor, class... Args>
167 auto invoke_expr (Functor&& functor, Args&&... args) -> decltype(
168  ::std::forward<Functor>(functor)(::std::forward<Args>(args)...)
169 );
170 
171 template <bool, class... Args> struct invoke_of { };
172 template <class... Args>
173 struct invoke_of<true, Args...> {
174  using type = decltype(invoke_expr(::std::declval<Args>()...));
175 };
176 
177 /* swappable implementation details */
178 using ::std::declval;
179 using ::std::swap;
180 
181 template <class T, class U>
183  template <class X, class Y>
184  static auto check (int) noexcept -> decltype(
185  swap(declval<X&>(), declval<Y&>()),
186  void()
187  );
188  template <class X, class Y> static void check (...) noexcept(false);
189 public:
190  static constexpr bool value =
191  noexcept(check<T, U>(0)) and noexcept(check<U, T>(0));
192 };
193 
194 template <class T, class U>
195 struct is_nothrow_swappable : ::std::integral_constant<
196  bool,
197  is_swappable<T, U>::value and noexcept(swap(declval<T&>(), declval<U&>()))
198 > { };
199 
200 } /* namespace impl */
201 
202 template <class... Args> struct invokable : ::std::integral_constant<
203  bool,
204  not ::std::is_same<
205  decltype(impl::invoke_expr(::std::declval<Args>()...)),
206  impl::undefined
207  >::value
208 > { };
209 
210 template <class... Args> struct invoke_of :
211  impl::invoke_of<invokable<Args...>::value, Args...>
212 { };
213 
214 template <class F, class... Args>
215 struct result_of<F(Args...)> : invoke_of<F, Args...> { };
216 
217 template <class T> using result_of_t = typename result_of<T>::type;
218 
219 template <class... Ts> struct common_type;
220 
221 template <class T> struct common_type<T> { using type = decay_t<T>; };
222 template <class T, class U>
223 struct common_type<T, U> {
224  using type = decay_t<
225  decltype(true ? ::std::declval<T>() : ::std::declval<U>())
226  >;
227 };
228 
229 template <class T, class U, class... Ts>
230 struct common_type<T, U, Ts...> {
231  using type = typename common_type<
232  typename common_type<T, U>::type,
233  Ts...
234  >::type;
235 };
236 
237 template <class... T> using common_type_t = typename common_type<T...>::type;
238 
239 /* is_null_pointer */
240 template <class T> struct is_null_pointer : ::std::false_type { };
241 
242 template <>
243 struct is_null_pointer<add_cv_t< ::std::nullptr_t>> : ::std::true_type { };
244 template <>
245 struct is_null_pointer< ::std::nullptr_t volatile> : ::std::true_type { };
246 template <>
247 struct is_null_pointer< ::std::nullptr_t const> : ::std::true_type { };
248 template <>
249 struct is_null_pointer< ::std::nullptr_t> : ::std::true_type { };
250 
251 /* is_swappable */
252 template <class T, class U=T>
253 using is_swappable = ::std::integral_constant<
254  bool,
256 >;
257 
258 /* is_nothrow_swappable */
259 template <class T, class U=T>
261 
262 /* all-traits */
263 template <class...> struct all_traits;
264 template <class T, class... Args>
265 struct all_traits<T, Args...> : ::std::integral_constant<bool,
266  T::value and all_traits<Args...>::value
267 > { };
268 template <> struct all_traits<> : ::std::true_type { };
269 
270 /* any-traits */
271 template <class...> struct any_traits;
272 template <class T, class... Args>
273 struct any_traits<T, Args...> : ::std::integral_constant<bool,
274  T::value or any_traits<Args...>::value
275 > { };
276 template <> struct any_traits<> : ::std::false_type { };
277 
278 /* no-traits */
279 template <class... Args> struct no_traits : ::std::integral_constant<bool,
280  not all_traits<Args...>::value
281 > { };
282 
283 }} /* namespace core::v1 */
284 
285 #endif /* CORE_TYPE_TRAITS_HPP */
smlt::v1::common_type
Definition: type_traits.h:219
smlt::v1::no_traits
Definition: type_traits.h:281
smlt::v1::is_runpackable
Definition: type_traits.h:43
smlt::v1::impl::is_nothrow_swappable
Definition: type_traits.h:198
smlt::v1::result_of
Definition: type_traits.h:59
smlt::v1::all_traits
Definition: type_traits.h:263
smlt::v1::impl::is_swappable
Definition: type_traits.h:182
smlt::v1::impl::invoke_of
Definition: type_traits.h:171
smlt
Definition: animation.cpp:25
smlt::v1::invokable
Definition: type_traits.h:208
smlt::v1::any_traits
Definition: type_traits.h:271
smlt::v1::is_unpackable
Definition: type_traits.h:33
smlt::v1::is_null_pointer
Definition: type_traits.h:240
smlt::v1::invoke_of
Definition: type_traits.h:212
smlt::v1::impl::undefined
Definition: type_traits.h:118
smlt::v1::class_of
Definition: type_traits.h:52