| 318 | 1 //     Copyright Toru Niina 2017. | 
|  | 2 // Distributed under the MIT License. | 
|  | 3 #ifndef TOML11_TRAITS_HPP | 
|  | 4 #define TOML11_TRAITS_HPP | 
|  | 5 | 
|  | 6 #include "from.hpp" | 
|  | 7 #include "into.hpp" | 
|  | 8 #include "version.hpp" | 
|  | 9 | 
|  | 10 #include <chrono> | 
|  | 11 #include <forward_list> | 
|  | 12 #include <string> | 
|  | 13 #include <tuple> | 
|  | 14 #include <type_traits> | 
|  | 15 #include <utility> | 
|  | 16 | 
|  | 17 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L | 
|  | 18 #if __has_include(<string_view>) | 
|  | 19 #include <string_view> | 
|  | 20 #endif // has_include(<string_view>) | 
|  | 21 #endif // cplusplus   >= C++17 | 
|  | 22 | 
|  | 23 namespace toml | 
|  | 24 { | 
|  | 25 template<typename C, template<typename ...> class T, template<typename ...> class A> | 
|  | 26 class basic_value; | 
|  | 27 | 
|  | 28 namespace detail | 
|  | 29 { | 
|  | 30 // --------------------------------------------------------------------------- | 
|  | 31 // check whether type T is a kind of container/map class | 
|  | 32 | 
|  | 33 struct has_iterator_impl | 
|  | 34 { | 
|  | 35     template<typename T> static std::true_type  check(typename T::iterator*); | 
|  | 36     template<typename T> static std::false_type check(...); | 
|  | 37 }; | 
|  | 38 struct has_value_type_impl | 
|  | 39 { | 
|  | 40     template<typename T> static std::true_type  check(typename T::value_type*); | 
|  | 41     template<typename T> static std::false_type check(...); | 
|  | 42 }; | 
|  | 43 struct has_key_type_impl | 
|  | 44 { | 
|  | 45     template<typename T> static std::true_type  check(typename T::key_type*); | 
|  | 46     template<typename T> static std::false_type check(...); | 
|  | 47 }; | 
|  | 48 struct has_mapped_type_impl | 
|  | 49 { | 
|  | 50     template<typename T> static std::true_type  check(typename T::mapped_type*); | 
|  | 51     template<typename T> static std::false_type check(...); | 
|  | 52 }; | 
|  | 53 struct has_reserve_method_impl | 
|  | 54 { | 
|  | 55     template<typename T> static std::false_type check(...); | 
|  | 56     template<typename T> static std::true_type  check( | 
|  | 57         decltype(std::declval<T>().reserve(std::declval<std::size_t>()))*); | 
|  | 58 }; | 
|  | 59 struct has_push_back_method_impl | 
|  | 60 { | 
|  | 61     template<typename T> static std::false_type check(...); | 
|  | 62     template<typename T> static std::true_type  check( | 
|  | 63         decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))*); | 
|  | 64 }; | 
|  | 65 struct is_comparable_impl | 
|  | 66 { | 
|  | 67     template<typename T> static std::false_type check(...); | 
|  | 68     template<typename T> static std::true_type  check( | 
|  | 69         decltype(std::declval<T>() < std::declval<T>())*); | 
|  | 70 }; | 
|  | 71 | 
|  | 72 struct has_from_toml_method_impl | 
|  | 73 { | 
|  | 74     template<typename T, typename C, | 
|  | 75              template<typename ...> class Tb, template<typename ...> class A> | 
|  | 76     static std::true_type  check( | 
|  | 77         decltype(std::declval<T>().from_toml( | 
|  | 78                 std::declval<::toml::basic_value<C, Tb, A>>()))*); | 
|  | 79 | 
|  | 80     template<typename T, typename C, | 
|  | 81              template<typename ...> class Tb, template<typename ...> class A> | 
|  | 82     static std::false_type check(...); | 
|  | 83 }; | 
|  | 84 struct has_into_toml_method_impl | 
|  | 85 { | 
|  | 86     template<typename T> | 
|  | 87     static std::true_type  check(decltype(std::declval<T>().into_toml())*); | 
|  | 88     template<typename T> | 
|  | 89     static std::false_type check(...); | 
|  | 90 }; | 
|  | 91 | 
|  | 92 struct has_specialized_from_impl | 
|  | 93 { | 
|  | 94     template<typename T> | 
|  | 95     static std::false_type check(...); | 
|  | 96     template<typename T, std::size_t S = sizeof(::toml::from<T>)> | 
|  | 97     static std::true_type check(::toml::from<T>*); | 
|  | 98 }; | 
|  | 99 struct has_specialized_into_impl | 
|  | 100 { | 
|  | 101     template<typename T> | 
|  | 102     static std::false_type check(...); | 
|  | 103     template<typename T, std::size_t S = sizeof(::toml::into<T>)> | 
|  | 104     static std::true_type check(::toml::from<T>*); | 
|  | 105 }; | 
|  | 106 | 
|  | 107 | 
|  | 108 /// Intel C++ compiler can not use decltype in parent class declaration, here | 
|  | 109 /// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076 | 
|  | 110 #ifdef __INTEL_COMPILER | 
|  | 111 #define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type | 
|  | 112 #endif | 
|  | 113 | 
|  | 114 template<typename T> | 
|  | 115 struct has_iterator    : decltype(has_iterator_impl::check<T>(nullptr)){}; | 
|  | 116 template<typename T> | 
|  | 117 struct has_value_type  : decltype(has_value_type_impl::check<T>(nullptr)){}; | 
|  | 118 template<typename T> | 
|  | 119 struct has_key_type    : decltype(has_key_type_impl::check<T>(nullptr)){}; | 
|  | 120 template<typename T> | 
|  | 121 struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){}; | 
|  | 122 template<typename T> | 
|  | 123 struct has_reserve_method : decltype(has_reserve_method_impl::check<T>(nullptr)){}; | 
|  | 124 template<typename T> | 
|  | 125 struct has_push_back_method : decltype(has_push_back_method_impl::check<T>(nullptr)){}; | 
|  | 126 template<typename T> | 
|  | 127 struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){}; | 
|  | 128 | 
|  | 129 template<typename T, typename C, | 
|  | 130          template<typename ...> class Tb, template<typename ...> class A> | 
|  | 131 struct has_from_toml_method | 
|  | 132 : decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){}; | 
|  | 133 | 
|  | 134 template<typename T> | 
|  | 135 struct has_into_toml_method | 
|  | 136 : decltype(has_into_toml_method_impl::check<T>(nullptr)){}; | 
|  | 137 | 
|  | 138 template<typename T> | 
|  | 139 struct has_specialized_from : decltype(has_specialized_from_impl::check<T>(nullptr)){}; | 
|  | 140 template<typename T> | 
|  | 141 struct has_specialized_into : decltype(has_specialized_into_impl::check<T>(nullptr)){}; | 
|  | 142 | 
|  | 143 #ifdef __INTEL_COMPILER | 
|  | 144 #undef decltype | 
|  | 145 #endif | 
|  | 146 | 
|  | 147 // --------------------------------------------------------------------------- | 
|  | 148 // C++17 and/or/not | 
|  | 149 | 
|  | 150 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L | 
|  | 151 | 
|  | 152 using std::conjunction; | 
|  | 153 using std::disjunction; | 
|  | 154 using std::negation; | 
|  | 155 | 
|  | 156 #else | 
|  | 157 | 
|  | 158 template<typename ...> struct conjunction : std::true_type{}; | 
|  | 159 template<typename T>   struct conjunction<T> : T{}; | 
|  | 160 template<typename T, typename ... Ts> | 
|  | 161 struct conjunction<T, Ts...> : | 
|  | 162     std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type | 
|  | 163 {}; | 
|  | 164 | 
|  | 165 template<typename ...> struct disjunction : std::false_type{}; | 
|  | 166 template<typename T>   struct disjunction<T> : T {}; | 
|  | 167 template<typename T, typename ... Ts> | 
|  | 168 struct disjunction<T, Ts...> : | 
|  | 169     std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type | 
|  | 170 {}; | 
|  | 171 | 
|  | 172 template<typename T> | 
|  | 173 struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{}; | 
|  | 174 | 
|  | 175 #endif | 
|  | 176 | 
|  | 177 // --------------------------------------------------------------------------- | 
|  | 178 // type checkers | 
|  | 179 | 
|  | 180 template<typename T> struct is_std_pair : std::false_type{}; | 
|  | 181 template<typename T1, typename T2> | 
|  | 182 struct is_std_pair<std::pair<T1, T2>> : std::true_type{}; | 
|  | 183 | 
|  | 184 template<typename T> struct is_std_tuple : std::false_type{}; | 
|  | 185 template<typename ... Ts> | 
|  | 186 struct is_std_tuple<std::tuple<Ts...>> : std::true_type{}; | 
|  | 187 | 
|  | 188 template<typename T> struct is_std_forward_list : std::false_type{}; | 
|  | 189 template<typename T> | 
|  | 190 struct is_std_forward_list<std::forward_list<T>> : std::true_type{}; | 
|  | 191 | 
|  | 192 template<typename T> struct is_chrono_duration: std::false_type{}; | 
|  | 193 template<typename Rep, typename Period> | 
|  | 194 struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{}; | 
|  | 195 | 
|  | 196 template<typename T> | 
|  | 197 struct is_map : conjunction< // map satisfies all the following conditions | 
|  | 198     has_iterator<T>,         // has T::iterator | 
|  | 199     has_value_type<T>,       // has T::value_type | 
|  | 200     has_key_type<T>,         // has T::key_type | 
|  | 201     has_mapped_type<T>       // has T::mapped_type | 
|  | 202     >{}; | 
|  | 203 template<typename T> struct is_map<T&>                : is_map<T>{}; | 
|  | 204 template<typename T> struct is_map<T const&>          : is_map<T>{}; | 
|  | 205 template<typename T> struct is_map<T volatile&>       : is_map<T>{}; | 
|  | 206 template<typename T> struct is_map<T const volatile&> : is_map<T>{}; | 
|  | 207 | 
|  | 208 template<typename T> | 
|  | 209 struct is_container : conjunction< | 
|  | 210     negation<is_map<T>>,                         // not a map | 
|  | 211     negation<std::is_same<T, std::string>>,      // not a std::string | 
|  | 212 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L | 
|  | 213 #if __has_include(<string_view>) | 
|  | 214     negation<std::is_same<T, std::string_view>>, // not a std::string_view | 
|  | 215 #endif // has_include(<string_view>) | 
|  | 216 #endif | 
|  | 217     has_iterator<T>,                             // has T::iterator | 
|  | 218     has_value_type<T>                            // has T::value_type | 
|  | 219     >{}; | 
|  | 220 template<typename T> struct is_container<T&>                : is_container<T>{}; | 
|  | 221 template<typename T> struct is_container<T const&>          : is_container<T>{}; | 
|  | 222 template<typename T> struct is_container<T volatile&>       : is_container<T>{}; | 
|  | 223 template<typename T> struct is_container<T const volatile&> : is_container<T>{}; | 
|  | 224 | 
|  | 225 template<typename T> | 
|  | 226 struct is_basic_value: std::false_type{}; | 
|  | 227 template<typename T> struct is_basic_value<T&>                : is_basic_value<T>{}; | 
|  | 228 template<typename T> struct is_basic_value<T const&>          : is_basic_value<T>{}; | 
|  | 229 template<typename T> struct is_basic_value<T volatile&>       : is_basic_value<T>{}; | 
|  | 230 template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{}; | 
|  | 231 template<typename C, template<typename ...> class M, template<typename ...> class V> | 
|  | 232 struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{}; | 
|  | 233 | 
|  | 234 // --------------------------------------------------------------------------- | 
|  | 235 // C++14 index_sequence | 
|  | 236 | 
|  | 237 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L | 
|  | 238 | 
|  | 239 using std::index_sequence; | 
|  | 240 using std::make_index_sequence; | 
|  | 241 | 
|  | 242 #else | 
|  | 243 | 
|  | 244 template<std::size_t ... Ns> struct index_sequence{}; | 
|  | 245 | 
|  | 246 template<typename IS, std::size_t N> struct push_back_index_sequence{}; | 
|  | 247 template<std::size_t N, std::size_t ... Ns> | 
|  | 248 struct push_back_index_sequence<index_sequence<Ns...>, N> | 
|  | 249 { | 
|  | 250     typedef index_sequence<Ns..., N> type; | 
|  | 251 }; | 
|  | 252 | 
|  | 253 template<std::size_t N> | 
|  | 254 struct index_sequence_maker | 
|  | 255 { | 
|  | 256     typedef typename push_back_index_sequence< | 
|  | 257         typename index_sequence_maker<N-1>::type, N>::type type; | 
|  | 258 }; | 
|  | 259 template<> | 
|  | 260 struct index_sequence_maker<0> | 
|  | 261 { | 
|  | 262     typedef index_sequence<0> type; | 
|  | 263 }; | 
|  | 264 template<std::size_t N> | 
|  | 265 using make_index_sequence = typename index_sequence_maker<N-1>::type; | 
|  | 266 | 
|  | 267 #endif // cplusplus >= 2014 | 
|  | 268 | 
|  | 269 // --------------------------------------------------------------------------- | 
|  | 270 // C++14 enable_if_t | 
|  | 271 | 
|  | 272 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L | 
|  | 273 | 
|  | 274 using std::enable_if_t; | 
|  | 275 | 
|  | 276 #else | 
|  | 277 | 
|  | 278 template<bool B, typename T> | 
|  | 279 using enable_if_t = typename std::enable_if<B, T>::type; | 
|  | 280 | 
|  | 281 #endif // cplusplus >= 2014 | 
|  | 282 | 
|  | 283 // --------------------------------------------------------------------------- | 
|  | 284 // return_type_of_t | 
|  | 285 | 
|  | 286 #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L && defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable>=201703 | 
|  | 287 | 
|  | 288 template<typename F, typename ... Args> | 
|  | 289 using return_type_of_t = std::invoke_result_t<F, Args...>; | 
|  | 290 | 
|  | 291 #else | 
|  | 292 // result_of is deprecated after C++17 | 
|  | 293 template<typename F, typename ... Args> | 
|  | 294 using return_type_of_t = typename std::result_of<F(Args...)>::type; | 
|  | 295 | 
|  | 296 #endif | 
|  | 297 | 
|  | 298 // --------------------------------------------------------------------------- | 
|  | 299 // is_string_literal | 
|  | 300 // | 
|  | 301 // to use this, pass `typename remove_reference<T>::type` to T. | 
|  | 302 | 
|  | 303 template<typename T> | 
|  | 304 struct is_string_literal: | 
|  | 305 disjunction< | 
|  | 306     std::is_same<const char*, T>, | 
|  | 307     conjunction< | 
|  | 308         std::is_array<T>, | 
|  | 309         std::is_same<const char, typename std::remove_extent<T>::type> | 
|  | 310         > | 
|  | 311     >{}; | 
|  | 312 | 
|  | 313 // --------------------------------------------------------------------------- | 
|  | 314 // C++20 remove_cvref_t | 
|  | 315 | 
|  | 316 template<typename T> | 
|  | 317 struct remove_cvref | 
|  | 318 { | 
|  | 319     using type = typename std::remove_cv< | 
|  | 320         typename std::remove_reference<T>::type>::type; | 
|  | 321 }; | 
|  | 322 | 
|  | 323 template<typename T> | 
|  | 324 using remove_cvref_t = typename remove_cvref<T>::type; | 
|  | 325 | 
|  | 326 }// detail | 
|  | 327 }//toml | 
|  | 328 #endif // TOML_TRAITS |