// The MIT License (MIT) // Copyright (c) 2013-2017 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 "bind_traits.hpp" #include #include #include #include #include #ifdef SOL_CXX17_FEATURES #include #endif 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 is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; template struct unwrapped { typedef T type; }; template struct unwrapped> { typedef T type; }; template using unwrapped_t = typename unwrapped::type; template struct unwrap_unqualified : unwrapped> {}; template using unwrap_unqualified_t = typename unwrap_unqualified::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 all_same : std::true_type { }; template struct all_same : std::integral_constant ::value && all_same::value> { }; template struct any_same : std::false_type { }; template struct any_same : std::integral_constant ::value || any_same::value> {}; template using boolean = std::integral_constant; template using invoke_t = typename T::type; template using invoke_b = boolean; template using neg = boolean; template using condition = std::conditional_t; template struct all : boolean {}; template struct all : condition, boolean> {}; template struct any : boolean {}; template struct any : condition, any> {}; enum class enable_t { _ }; constexpr const auto enabler = enable_t::_; template using disable_if_t = std::enable_if_t; template using enable = std::enable_if_t::value, enable_t>; template using enable_any = std::enable_if_t::value, enable_t>; template using disable = std::enable_if_t>::value, enable_t>; template using disable_any = std::enable_if_t>::value, enable_t>; template struct find_in_pack_v : boolean { }; template struct find_in_pack_v : any, find_in_pack_v> { }; namespace meta_detail { template struct index_in_pack : std::integral_constant { }; template struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; } template struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; template struct index_in : meta_detail::index_in_pack<0, T, List> { }; template struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; template struct at_in_pack {}; template using at_in_pack_t = typename at_in_pack::type; template struct at_in_pack : std::conditional> {}; template struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; namespace meta_detail { template class Pred, typename... Ts> struct count_for_pack : std::integral_constant {}; template class Pred, typename T, typename... Ts> struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, std::integral_constant(Limit != 0 && Pred::value)>, count_for_pack(Pred::value), Pred, Ts...> > { }; template class Pred, typename... Ts> struct count_2_for_pack : std::integral_constant {}; template class Pred, typename T, typename U, typename... Ts> struct count_2_for_pack : std::conditional_t(Pred::value)>, count_2_for_pack(Pred::value), Pred, Ts...> > { }; } // meta_detail template class Pred, typename... Ts> struct count_for_pack : meta_detail::count_for_pack { }; template class Pred, typename List> struct count_for; template class Pred, typename... Args> struct count_for> : count_for_pack {}; template class Pred, typename... Ts> struct count_for_to_pack : meta_detail::count_for_pack { }; template class Pred, typename... Ts> struct count_2_for_pack : meta_detail::count_2_for_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_invokable_tester { template always_true()(std::declval()...))> static test(int); template std::false_type static test(...); }; } // meta_detail template struct is_invokable; template struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; namespace meta_detail { template struct is_callable : std::is_function> {}; template struct is_callable>::value && std::is_destructible>::value>> { 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 is_callable>::value && !std::is_destructible>::value>> { using yes = char; using no = struct { char s[2]; }; struct F { void operator()(); }; struct Derived : T, F { ~Derived() = delete; }; template struct Check; template static no test(Check*); template static yes test(...); static const bool value = sizeof(test(0)) == sizeof(yes); }; 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(...); }; struct has_key_type_impl { template, typename V = typename U::key_type> static std::true_type test(int); template static std::false_type test(...); }; struct has_mapped_type_impl { template, typename V = typename U::mapped_type> static std::true_type test(int); template static std::false_type test(...); }; struct has_value_type_impl { template, typename V = typename U::value_type> static std::true_type test(int); template static std::false_type test(...); }; struct has_iterator_impl { template, typename V = typename U::iterator> static std::true_type test(int); template static std::false_type test(...); }; 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_push_back_test { private: typedef std::array one; typedef std::array two; template static one test(decltype(std::declval().push_back(std::declval>()))*); template static two test(...); public: static const bool value = sizeof(test(0)) == sizeof(char); }; template struct has_insert_test { private: typedef std::array one; typedef std::array two; template static one test(decltype(std::declval().insert(std::declval>(), std::declval>()))*); template static two test(...); public: static const bool value = sizeof(test(0)) == sizeof(char); }; template struct has_insert_after_test { private: typedef std::array one; typedef std::array two; template static one test(decltype(std::declval().insert_after(std::declval>(), std::declval>()))*); template static two test(...); public: static const bool value = sizeof(test(0)) == sizeof(char); }; template struct has_size_test { private: typedef std::array one; typedef std::array two; template static one test(decltype(std::declval().size())*); template static two test(...); public: static const bool value = sizeof(test(0)) == sizeof(char); }; template struct has_to_string_test { private: typedef std::array one; typedef std::array two; template static one test(decltype(std::declval().to_string())*); template static two test(...); public: static const bool value = sizeof(test(0)) == sizeof(char); }; #if defined(_MSC_VER) && _MSC_VER <= 1910 template () < std::declval())> std::true_type supports_op_less_test(std::reference_wrapper, std::reference_wrapper); std::false_type supports_op_less_test(...); template () == std::declval())> std::true_type supports_op_equal_test(std::reference_wrapper, std::reference_wrapper); std::false_type supports_op_equal_test(...); template () <= std::declval())> std::true_type supports_op_less_equal_test(std::reference_wrapper, std::reference_wrapper); std::false_type supports_op_less_equal_test(...); template () << std::declval())> std::true_type supports_ostream_op(std::reference_wrapper, std::reference_wrapper); std::false_type supports_ostream_op(...); template ()))> std::true_type supports_adl_to_string(std::reference_wrapper); std::false_type supports_adl_to_string(...); #else template () < std::declval())> std::true_type supports_op_less_test(const T&, const U&); std::false_type supports_op_less_test(...); template () == std::declval())> std::true_type supports_op_equal_test(const T&, const U&); std::false_type supports_op_equal_test(...); template () <= std::declval())> std::true_type supports_op_less_equal_test(const T&, const U&); std::false_type supports_op_less_equal_test(...); template () << std::declval())> std::true_type supports_ostream_op(const T&, const OS&); std::false_type supports_ostream_op(...); template ()))> std::true_type supports_adl_to_string(const T&); std::false_type supports_adl_to_string(...); #endif } // meta_detail #if defined(_MSC_VER) && _MSC_VER <= 1910 template using supports_op_less = decltype(meta_detail::supports_op_less_test(std::ref(std::declval()), std::ref(std::declval()))); template using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::ref(std::declval()), std::ref(std::declval()))); template using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::ref(std::declval()), std::ref(std::declval()))); template using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::ref(std::declval()), std::ref(std::declval()))); template using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::ref(std::declval()))); #else template using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval(), std::declval())); template using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval(), std::declval())); template using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval(), std::declval())); template using supports_ostream_op = decltype(meta_detail::supports_ostream_op(std::declval(), std::declval())); template using supports_adl_to_string = decltype(meta_detail::supports_adl_to_string(std::declval())); #endif template using supports_to_string_member = meta::boolean::value>; template struct is_callable : boolean::value> {}; template struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; template struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; template struct has_key_type : decltype(meta_detail::has_key_type_impl::test(0)) {}; template struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test(0)) {}; template struct has_iterator : decltype(meta_detail::has_iterator_impl::test(0)) {}; template struct has_value_type : decltype(meta_detail::has_value_type_impl::test(0)) {}; template using has_push_back = meta::boolean::value>; template using has_insert = meta::boolean::value>; template using has_insert_after = meta::boolean::value>; template using has_size = meta::boolean::value>; template struct is_associative : meta::all, has_key_value_pair, has_mapped_type> {}; template struct is_lookup : meta::all, has_value_type> {}; template using is_string_constructible = any< std::is_same, const char*> , std::is_same, char> , std::is_same, std::string> , std::is_same, std::initializer_list> #ifdef SOL_CXX17_FEATURES , std::is_same, std::string_view> #endif >; template struct is_pair : std::false_type {}; template struct is_pair> : std::true_type {}; template using is_c_str = any< std::is_same>, const char*>, std::is_same>, char*>, std::is_same, std::string> >; template struct is_move_only : all< neg>, neg>>, std::is_move_constructible> > {}; template using is_not_move_only = neg>; namespace meta_detail { template >> = meta::enabler> decltype(auto) force_tuple(T&& x) { return std::forward_as_tuple(std::forward(x)); } template >> = meta::enabler> 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))...); } template struct iterator_tag { using type = std::input_iterator_tag; }; template struct iterator_tag> { using type = typename T::iterator_category; }; } // meta namespace detail { template struct is_pointer_like : std::is_pointer {}; template struct is_pointer_like> : std::true_type {}; template struct is_pointer_like> : std::true_type {}; 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>>> = meta::enabler> auto deref(T&& item) -> decltype(std::forward(item)) { return std::forward(item); } template>> = meta::enabler> inline auto deref(T&& item) -> decltype(*std::forward(item)) { return *std::forward(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