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