// The MIT License (MIT) // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SOL_TRAITS_HPP #define SOL_TRAITS_HPP #include "tuple.hpp" #include #include #include namespace sol { template using index_value = std::integral_constant; namespace meta { template struct identity { typedef T type; }; template using identity_t = typename identity::type; template struct is_tuple : std::false_type{ }; template struct is_tuple> : std::true_type{ }; template struct unwrapped { typedef T type; }; template struct unwrapped> { typedef T type; }; template struct remove_member_pointer; template struct remove_member_pointer { typedef R type; }; template struct remove_member_pointer { typedef R type; }; template using remove_member_pointer_t = remove_member_pointer; template class Templ, typename T> struct is_specialization_of : std::false_type { }; template class Templ> struct is_specialization_of> : std::true_type { }; template struct are_same : std::true_type { }; template struct are_same : std::integral_constant ::value && are_same::value> { }; template using Type = typename T::type; template using Bool = std::integral_constant; template using Not = Bool; template using If = typename std::conditional::type; template using TypeIf = typename std::conditional, Type>::type; template struct And : Bool {}; template struct And : If, Bool> {}; template struct Or : Bool {}; template struct Or : If, Or> {}; template using EnableIf = typename std::enable_if::value, int>::type; template using DisableIf = typename std::enable_if>::value, int>::type; template using Unqualified = std::remove_cv_t>; template using Unwrapped = typename unwrapped::type; template using tuple_element = std::tuple_element>; template using tuple_element_t = std::tuple_element_t>; template struct find_in_pack_v : Bool { }; template struct find_in_pack_v : Or, find_in_pack_v> { }; template struct at_in_pack {}; template using at_in_pack_t = typename at_in_pack::type; template struct at_in_pack : std::conditional> {}; namespace meta_detail { template class Pred, typename... Ts> struct count_if_pack : std::integral_constant {}; template class Pred, typename T, typename... Ts> struct count_if_pack : std::conditional_t(Pred::value)>, count_if_pack(Pred::value), Pred, Ts...> > { }; template class Pred, typename... Ts> struct count_if_2_pack : std::integral_constant {}; template class Pred, typename T, typename U, typename... Ts> struct count_if_2_pack : std::conditional_t(Pred::value)>, count_if_2_pack(Pred::value), Pred, Ts...> > { }; } // meta_detail template class Pred, typename... Ts> struct count_if_pack : meta_detail::count_if_pack<0, Pred, Ts...> { }; template class Pred, typename... Ts> struct count_if_2_pack : meta_detail::count_if_2_pack<0, Pred, Ts...> { }; template struct return_type { typedef std::tuple type; }; template struct return_type { typedef T type; }; template<> struct return_type<> { typedef void type; }; template using return_type_t = typename return_type::type; namespace meta_detail { template struct always_true : std::true_type {}; struct is_callable_tester { template always_true()(std::declval()...))> static test(int); template std::false_type static test(...); }; } // meta_detail template struct is_callable; template struct is_callable : decltype(meta_detail::is_callable_tester::test(0)) {}; namespace meta_detail { template>::value> struct is_function_impl : std::is_function> {}; template struct is_function_impl { using yes = char; using no = struct { char s[2]; }; struct F { void operator()(); }; struct Derived : T, F {}; template struct Check; template static no test(Check*); template static yes test(...); static const bool value = sizeof(test(0)) == sizeof(yes); }; template struct check_deducible_signature { struct nat {}; template static auto test(int) -> decltype(&G::operator(), void()); template static auto test(...) -> nat; using type = std::is_void(0))>; }; } // meta_detail template struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; template struct Function : Bool::value> {}; namespace meta_detail { template struct void_tuple_element : meta::tuple_element {}; template struct void_tuple_element> { typedef void type; }; template using void_tuple_element_t = typename void_tuple_element::type; template::value> struct fx_traits; template struct fx_traits : fx_traits { }; template struct fx_traits { static const std::size_t arity = sizeof...(Args); static const bool is_member_function = true; typedef T object_type; typedef std::tuple args_tuple_type; typedef types args_type; typedef R(T::* function_pointer_type)(Args...); typedef std::remove_pointer_t function_type; typedef R(*free_function_pointer_type)(Args...); typedef R return_type; typedef std::remove_pointer_t signature_type; template using arg_at = void_tuple_element_t; }; template struct fx_traits { static const std::size_t arity = sizeof...(Args); static const bool is_member_function = true; typedef T object_type; typedef std::tuple args_tuple_type; typedef types args_type; typedef R(T::* function_pointer_type)(Args...); typedef std::remove_pointer_t function_type; typedef R(*free_function_pointer_type)(Args...); typedef R return_type; typedef std::remove_pointer_t signature_type; template using arg_at = void_tuple_element_t; }; template struct fx_traits { static const std::size_t arity = sizeof...(Args); static const bool is_member_function = false; typedef std::tuple args_tuple_type; typedef types args_type; typedef R(function_type)(Args...); typedef R(*function_pointer_type)(Args...); typedef R(*free_function_pointer_type)(Args...); typedef R return_type; typedef std::remove_pointer_t signature_type; template using arg_at = void_tuple_element_t; }; template struct fx_traits { static const std::size_t arity = sizeof...(Args); static const bool is_member_function = false; typedef std::tuple args_tuple_type; typedef types args_type; typedef R(function_type)(Args...); typedef R(*function_pointer_type)(Args...); typedef R(*free_function_pointer_type)(Args...); typedef R return_type; typedef std::remove_pointer_t signature_type; template using arg_at = void_tuple_element_t; }; template::value> struct callable_traits : fx_traits> { }; template struct callable_traits { typedef R Arg; typedef T object_type; using signature_type = R(T::*); static const bool is_member_function = false; static const std::size_t arity = 1; typedef std::tuple args_tuple_type; typedef types args_type; typedef R return_type; typedef R(function_type)(Arg); typedef R(*function_pointer_type)(Arg); typedef R(*free_function_pointer_type)(Arg); template using arg_at = void_tuple_element_t; }; } // meta_detail template struct bind_traits : meta_detail::callable_traits> {}; template using function_args_t = typename bind_traits::args_type; template using function_signature_t = typename bind_traits::signature_type; template using function_return_t = typename bind_traits::return_type; struct has_begin_end_impl { template, typename B = decltype(std::declval().begin()), typename E = decltype(std::declval().end())> static std::true_type test(int); template static std::false_type test(...); }; template struct has_begin_end : decltype(has_begin_end_impl::test(0)) {}; struct has_key_value_pair_impl { template, typename V = typename U::value_type, typename F = decltype(std::declval().first), typename S = decltype(std::declval().second)> static std::true_type test(int); template static std::false_type test(...); }; template struct has_key_value_pair : decltype(has_key_value_pair_impl::test(0)) {}; template using is_string_constructible = Or, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; template using is_c_str = Or< std::is_same>, const char*>, std::is_same>, char*>, std::is_same, std::string> >; namespace meta_detail { template >> = 0> decltype(auto) force_tuple(T&& x) { return std::forward_as_tuple(std::forward(x)); } template >> = 0> decltype(auto) force_tuple(T&& x) { return std::forward(x); } } // meta_detail template decltype(auto) tuplefy(X&&... x ) { return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); } } // meta namespace detail { template decltype(auto) forward_get( Tuple&& tuple ) { return std::forward>(std::get(tuple)); } template auto forward_tuple_impl( std::index_sequence, Tuple&& tuple ) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { return std::tuple(tuple))...>(std::move(std::get(tuple))...); } template auto forward_tuple( Tuple&& tuple ) { auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); return x; } template auto unwrap(T&& item) -> decltype(std::forward(item)) { return std::forward(item); } template T& unwrap(std::reference_wrapper arg) { return arg.get(); } template decltype(auto) deref(T&& item) { return std::forward(item); } template T& deref(T* item) { return *item; } template decltype(auto) deref(std::unique_ptr& item) { return *item; } template T& deref(std::shared_ptr& item) { return *item; } template decltype(auto) deref(const std::unique_ptr& item) { return *item; } template T& deref(const std::shared_ptr& item) { return *item; } template inline T* ptr(T& val) { return std::addressof(val); } template inline T* ptr(std::reference_wrapper val) { return std::addressof(val.get()); } template inline T* ptr(T* val) { return val; } } // detail } // sol #endif // SOL_TRAITS_HPP