1 // The MIT License (MIT) 2 3 // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 // this software and associated documentation files (the "Software"), to deal in 7 // the Software without restriction, including without limitation the rights to 8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 // the Software, and to permit persons to whom the Software is furnished to do so, 10 // subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SOL_TRAITS_HPP 23 #define SOL_TRAITS_HPP 24 25 #include "tuple.hpp" 26 #include "bind_traits.hpp" 27 #include <type_traits> 28 #include <memory> 29 #include <functional> 30 31 namespace sol { 32 template<std::size_t I> 33 using index_value = std::integral_constant<std::size_t, I>; 34 35 namespace meta { 36 template<typename T> 37 struct identity { typedef T type; }; 38 39 template<typename T> 40 using identity_t = typename identity<T>::type; 41 42 template<typename... Args> 43 struct is_tuple : std::false_type { }; 44 45 template<typename... Args> 46 struct is_tuple<std::tuple<Args...>> : std::true_type { }; 47 48 template <typename T> 49 struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {}; 50 51 template<typename T> 52 struct unwrapped { 53 typedef T type; 54 }; 55 56 template<typename T> 57 struct unwrapped<std::reference_wrapper<T>> { 58 typedef T type; 59 }; 60 61 template<typename T> 62 using unwrapped_t = typename unwrapped<T>::type; 63 64 template <typename T> 65 struct unwrap_unqualified : unwrapped<unqualified_t<T>> {}; 66 67 template <typename T> 68 using unwrap_unqualified_t = typename unwrap_unqualified<T>::type; 69 70 template<typename T> 71 struct remove_member_pointer; 72 73 template<typename R, typename T> 74 struct remove_member_pointer<R T::*> { 75 typedef R type; 76 }; 77 78 template<typename R, typename T> 79 struct remove_member_pointer<R T::* const> { 80 typedef R type; 81 }; 82 83 template<typename T> 84 using remove_member_pointer_t = remove_member_pointer<T>; 85 86 template<template<typename...> class Templ, typename T> 87 struct is_specialization_of : std::false_type { }; 88 template<typename... T, template<typename...> class Templ> 89 struct is_specialization_of<Templ, Templ<T...>> : std::true_type { }; 90 91 template<class T, class...> 92 struct all_same : std::true_type { }; 93 94 template<class T, class U, class... Args> 95 struct all_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { }; 96 97 template<class T, class...> 98 struct any_same : std::false_type { }; 99 100 template<class T, class U, class... Args> 101 struct any_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { }; 102 103 template<typename T> 104 using invoke_t = typename T::type; 105 106 template<bool B> 107 using boolean = std::integral_constant<bool, B>; 108 109 template<typename T> 110 using neg = boolean<!T::value>; 111 112 template<typename Condition, typename Then, typename Else> 113 using condition = std::conditional_t<Condition::value, Then, Else>; 114 115 template<typename... Args> 116 struct all : boolean<true> {}; 117 118 template<typename T, typename... Args> 119 struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {}; 120 121 template<typename... Args> 122 struct any : boolean<false> {}; 123 124 template<typename T, typename... Args> 125 struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {}; 126 127 enum class enable_t { 128 _ 129 }; 130 131 constexpr const auto enabler = enable_t::_; 132 133 template<bool value, typename T = void> 134 using disable_if_t = std::enable_if_t<!value, T>; 135 136 template<typename... Args> 137 using enable = std::enable_if_t<all<Args...>::value, enable_t>; 138 139 template<typename... Args> 140 using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>; 141 142 template<typename... Args> 143 using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>; 144 145 template<typename V, typename... Vs> 146 struct find_in_pack_v : boolean<false> { }; 147 148 template<typename V, typename Vs1, typename... Vs> 149 struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { }; 150 151 namespace meta_detail { 152 template<std::size_t I, typename T, typename... Args> 153 struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { }; 154 155 template<std::size_t I, typename T, typename T1, typename... Args> 156 struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { }; 157 } 158 159 template<typename T, typename... Args> 160 struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; 161 162 template<typename T, typename List> 163 struct index_in : meta_detail::index_in_pack<0, T, List> { }; 164 165 template<typename T, typename... Args> 166 struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { }; 167 168 template<std::size_t I, typename... Args> 169 struct at_in_pack {}; 170 171 template<std::size_t I, typename... Args> 172 using at_in_pack_t = typename at_in_pack<I, Args...>::type; 173 174 template<std::size_t I, typename Arg, typename... Args> 175 struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {}; 176 177 template<typename Arg, typename... Args> 178 struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; 179 180 namespace meta_detail { 181 template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename... Ts> 182 struct count_for_pack : std::integral_constant<std::size_t, 0> {}; 183 template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename T, typename... Ts> 184 struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, 185 std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>, 186 count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> 187 > { }; 188 template<std::size_t I, template<typename...> class Pred, typename... Ts> 189 struct count_2_for_pack : std::integral_constant<std::size_t, 0> {}; 190 template<std::size_t I, template<typename...> class Pred, typename T, typename U, typename... Ts> 191 struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0, 192 std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>, 193 count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> 194 > { }; 195 } // meta_detail 196 197 template<template<typename...> class Pred, typename... Ts> 198 struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> { }; 199 200 template<template<typename...> class Pred, typename List> 201 struct count_for; 202 203 template<template<typename...> class Pred, typename... Args> 204 struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {}; 205 206 template<std::size_t Limit, template<typename...> class Pred, typename... Ts> 207 struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> { }; 208 209 template<template<typename...> class Pred, typename... Ts> 210 struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; 211 212 template<typename... Args> 213 struct return_type { 214 typedef std::tuple<Args...> type; 215 }; 216 217 template<typename T> 218 struct return_type<T> { 219 typedef T type; 220 }; 221 222 template<> 223 struct return_type<> { 224 typedef void type; 225 }; 226 227 template <typename... Args> 228 using return_type_t = typename return_type<Args...>::type; 229 230 namespace meta_detail { 231 template <typename> struct always_true : std::true_type {}; 232 struct is_invokable_tester { 233 template <typename Fun, typename... Args> 234 always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); 235 template <typename...> 236 std::false_type static test(...); 237 }; 238 } // meta_detail 239 240 template <typename T> 241 struct is_invokable; 242 template <typename Fun, typename... Args> 243 struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {}; 244 245 namespace meta_detail { 246 247 template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value> 248 struct is_callable : std::is_function<std::remove_pointer_t<T>> {}; 249 250 template<typename T> 251 struct is_callable<T, true> { 252 using yes = char; 253 using no = struct { char s[2]; }; 254 operator ()sol::meta::meta_detail::is_callable::F255 struct F { void operator()() {}; }; 256 struct Derived : T, F {}; 257 template<typename U, U> struct Check; 258 259 template<typename V> 260 static no test(Check<void (F::*)(), &V::operator()>*); 261 262 template<typename> 263 static yes test(...); 264 265 static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); 266 }; 267 268 struct has_begin_end_impl { 269 template<typename T, typename U = unqualified_t<T>, 270 typename B = decltype(std::declval<U&>().begin()), 271 typename E = decltype(std::declval<U&>().end())> 272 static std::true_type test(int); 273 274 template<typename...> 275 static std::false_type test(...); 276 }; 277 278 struct has_key_value_pair_impl { 279 template<typename T, typename U = unqualified_t<T>, 280 typename V = typename U::value_type, 281 typename F = decltype(std::declval<V&>().first), 282 typename S = decltype(std::declval<V&>().second)> 283 static std::true_type test(int); 284 285 template<typename...> 286 static std::false_type test(...); 287 }; 288 289 template <typename T, typename U = T, typename = decltype(std::declval<T&>() < std::declval<U&>())> 290 std::true_type supports_op_less_test(const T&); 291 std::false_type supports_op_less_test(...); 292 template <typename T, typename U = T, typename = decltype(std::declval<T&>() == std::declval<U&>())> 293 std::true_type supports_op_equal_test(const T&); 294 std::false_type supports_op_equal_test(...); 295 template <typename T, typename U = T, typename = decltype(std::declval<T&>() <= std::declval<U&>())> 296 std::true_type supports_op_less_equal_test(const T&); 297 std::false_type supports_op_less_equal_test(...); 298 299 } // meta_detail 300 301 template <typename T> 302 using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>())); 303 template <typename T> 304 using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>())); 305 template <typename T> 306 using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>())); 307 308 template<typename T> 309 struct is_callable : boolean<meta_detail::is_callable<T>::value> {}; 310 311 template<typename T> 312 struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {}; 313 314 template<typename T> 315 struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {}; 316 317 template <typename T> 318 using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>; 319 320 template <typename T> 321 using is_c_str = any< 322 std::is_same<std::decay_t<unqualified_t<T>>, const char*>, 323 std::is_same<std::decay_t<unqualified_t<T>>, char*>, 324 std::is_same<unqualified_t<T>, std::string> 325 >; 326 327 template <typename T> 328 struct is_move_only : all< 329 neg<std::is_reference<T>>, 330 neg<std::is_copy_constructible<unqualified_t<T>>>, 331 std::is_move_constructible<unqualified_t<T>> 332 > {}; 333 334 template <typename T> 335 using is_not_move_only = neg<is_move_only<T>>; 336 337 namespace meta_detail { 338 template <typename T, meta::disable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> force_tuple(T && x)339 decltype(auto) force_tuple(T&& x) { 340 return std::forward_as_tuple(std::forward<T>(x)); 341 } 342 343 template <typename T, meta::enable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> force_tuple(T && x)344 decltype(auto) force_tuple(T&& x) { 345 return std::forward<T>(x); 346 } 347 } // meta_detail 348 349 template <typename... X> tuplefy(X &&...x)350 decltype(auto) tuplefy(X&&... x) { 351 return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...); 352 } 353 } // meta 354 namespace detail { 355 template <std::size_t I, typename Tuple> forward_get(Tuple && tuple)356 decltype(auto) forward_get(Tuple&& tuple) { 357 return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple)); 358 } 359 360 template <std::size_t... I, typename Tuple> forward_tuple_impl(std::index_sequence<I...>,Tuple && tuple)361 auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) { 362 return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...); 363 } 364 365 template <typename Tuple> forward_tuple(Tuple && tuple)366 auto forward_tuple(Tuple&& tuple) { 367 auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple)); 368 return x; 369 } 370 371 template<typename T> unwrap(T && item)372 auto unwrap(T&& item) -> decltype(std::forward<T>(item)) { 373 return std::forward<T>(item); 374 } 375 376 template<typename T> unwrap(std::reference_wrapper<T> arg)377 T& unwrap(std::reference_wrapper<T> arg) { 378 return arg.get(); 379 } 380 381 template<typename T> deref(T && item)382 auto deref(T&& item) -> decltype(std::forward<T>(item)) { 383 return std::forward<T>(item); 384 } 385 386 template<typename T> deref(T * item)387 inline T& deref(T* item) { 388 return *item; 389 } 390 391 template<typename T, typename Dx> deref(std::unique_ptr<T,Dx> & item)392 inline std::add_lvalue_reference_t<T> deref(std::unique_ptr<T, Dx>& item) { 393 return *item; 394 } 395 396 template<typename T> deref(std::shared_ptr<T> & item)397 inline std::add_lvalue_reference_t<T> deref(std::shared_ptr<T>& item) { 398 return *item; 399 } 400 401 template<typename T, typename Dx> deref(const std::unique_ptr<T,Dx> & item)402 inline std::add_lvalue_reference_t<T> deref(const std::unique_ptr<T, Dx>& item) { 403 return *item; 404 } 405 406 template<typename T> deref(const std::shared_ptr<T> & item)407 inline std::add_lvalue_reference_t<T> deref(const std::shared_ptr<T>& item) { 408 return *item; 409 } 410 411 template<typename T> ptr(T & val)412 inline T* ptr(T& val) { 413 return std::addressof(val); 414 } 415 416 template<typename T> ptr(std::reference_wrapper<T> val)417 inline T* ptr(std::reference_wrapper<T> val) { 418 return std::addressof(val.get()); 419 } 420 421 template<typename T> ptr(T * val)422 inline T* ptr(T* val) { 423 return val; 424 } 425 } // detail 426 } // sol 427 428 #endif // SOL_TRAITS_HPP 429