// Copyright Toru Niina 2017. // Distributed under the MIT License. #ifndef TOML11_TRAITS_HPP #define TOML11_TRAITS_HPP #include #include #include #include #include #include #if __cplusplus >= 201703L #if __has_include() #include #endif // has_include() #endif // cplusplus >= C++17 namespace toml { template class T, template class A> class basic_value; namespace detail { // --------------------------------------------------------------------------- // check whether type T is a kind of container/map class struct has_iterator_impl { template static std::true_type check(typename T::iterator*); template static std::false_type check(...); }; struct has_value_type_impl { template static std::true_type check(typename T::value_type*); template static std::false_type check(...); }; struct has_key_type_impl { template static std::true_type check(typename T::key_type*); template static std::false_type check(...); }; struct has_mapped_type_impl { template static std::true_type check(typename T::mapped_type*); template static std::false_type check(...); }; struct has_reserve_method_impl { template static std::false_type check(...); template static std::true_type check( decltype(std::declval().reserve(std::declval()))*); }; struct has_push_back_method_impl { template static std::false_type check(...); template static std::true_type check( decltype(std::declval().push_back(std::declval()))*); }; struct is_comparable_impl { template static std::false_type check(...); template static std::true_type check( decltype(std::declval() < std::declval())*); }; struct has_from_toml_method_impl { template class Tb, template class A> static std::true_type check( decltype(std::declval().from_toml( std::declval<::toml::basic_value>()))*); template class Tb, template class A> static std::false_type check(...); }; struct has_into_toml_method_impl { template static std::true_type check(decltype(std::declval().into_toml())*); template static std::false_type check(...); }; /// Intel C++ compiler can not use decltype in parent class declaration, here /// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076 #ifdef __INTEL_COMPILER #define decltype(...) std::enable_if::type #endif template struct has_iterator : decltype(has_iterator_impl::check(nullptr)){}; template struct has_value_type : decltype(has_value_type_impl::check(nullptr)){}; template struct has_key_type : decltype(has_key_type_impl::check(nullptr)){}; template struct has_mapped_type : decltype(has_mapped_type_impl::check(nullptr)){}; template struct has_reserve_method : decltype(has_reserve_method_impl::check(nullptr)){}; template struct has_push_back_method : decltype(has_push_back_method_impl::check(nullptr)){}; template struct is_comparable : decltype(is_comparable_impl::check(nullptr)){}; template class Tb, template class A> struct has_from_toml_method : decltype(has_from_toml_method_impl::check(nullptr)){}; template struct has_into_toml_method : decltype(has_into_toml_method_impl::check(nullptr)){}; #ifdef __INTEL_COMPILER #undef decltype #endif // --------------------------------------------------------------------------- // C++17 and/or/not #if __cplusplus >= 201703L using std::conjunction; using std::disjunction; using std::negation; #else template struct conjunction : std::true_type{}; template struct conjunction : T{}; template struct conjunction : std::conditional(T::value), conjunction, T>::type {}; template struct disjunction : std::false_type{}; template struct disjunction : T {}; template struct disjunction : std::conditional(T::value), T, disjunction>::type {}; template struct negation : std::integral_constant(T::value)>{}; #endif // --------------------------------------------------------------------------- // type checkers template struct is_std_pair : std::false_type{}; template struct is_std_pair> : std::true_type{}; template struct is_std_tuple : std::false_type{}; template struct is_std_tuple> : std::true_type{}; template struct is_std_forward_list : std::false_type{}; template struct is_std_forward_list> : std::true_type{}; template struct is_chrono_duration: std::false_type{}; template struct is_chrono_duration>: std::true_type{}; template struct is_map : conjunction< // map satisfies all the following conditions has_iterator, // has T::iterator has_value_type, // has T::value_type has_key_type, // has T::key_type has_mapped_type // has T::mapped_type >{}; template struct is_map : is_map{}; template struct is_map : is_map{}; template struct is_map : is_map{}; template struct is_map : is_map{}; template struct is_container : conjunction< negation>, // not a map negation>, // not a std::string #if __cplusplus >= 201703L negation>, // not a std::string_view #endif has_iterator, // has T::iterator has_value_type // has T::value_type >{}; template struct is_container : is_container{}; template struct is_container : is_container{}; template struct is_container : is_container{}; template struct is_container : is_container{}; template struct is_basic_value: std::false_type{}; template struct is_basic_value : is_basic_value{}; template struct is_basic_value : is_basic_value{}; template struct is_basic_value : is_basic_value{}; template struct is_basic_value : is_basic_value{}; template class M, template class V> struct is_basic_value<::toml::basic_value>: std::true_type{}; // --------------------------------------------------------------------------- // C++14 index_sequence #if __cplusplus >= 201402L using std::index_sequence; using std::make_index_sequence; #else template struct index_sequence{}; template struct push_back_index_sequence{}; template struct push_back_index_sequence, N> { typedef index_sequence type; }; template struct index_sequence_maker { typedef typename push_back_index_sequence< typename index_sequence_maker::type, N>::type type; }; template<> struct index_sequence_maker<0> { typedef index_sequence<0> type; }; template using make_index_sequence = typename index_sequence_maker::type; #endif // __cplusplus >= 2014 // --------------------------------------------------------------------------- // C++14 enable_if_t #if __cplusplus >= 201402L using std::enable_if_t; #else template using enable_if_t = typename std::enable_if::type; #endif // __cplusplus >= 2014 // --------------------------------------------------------------------------- // return_type_of_t #if __cplusplus >= 201703L template using return_type_of_t = std::invoke_result_t; #else // result_of is deprecated after C++17 template using return_type_of_t = typename std::result_of::type; #endif // --------------------------------------------------------------------------- // is_string_literal // // to use this, pass `typename remove_reference::type` to T. template struct is_string_literal: disjunction< std::is_same, conjunction< std::is_array, std::is_same::type> > >{}; // --------------------------------------------------------------------------- // C++20 remove_cvref_t template struct remove_cvref { using type = typename std::remove_cv< typename std::remove_reference::type>::type; }; template using remove_cvref_t = typename remove_cvref::type; }// detail }//toml #endif // TOML_TRAITS