diff --git a/toml.hpp b/toml.hpp index 3189b34..2a5c24e 100644 --- a/toml.hpp +++ b/toml.hpp @@ -108,24 +108,24 @@ namespace detail template using unwrap_t = typename std::decay::type; +template +constexpr inline value_t check_type() +{ + return std::is_same, toml::Boolean >::value ? value_t::Boolean : + std::is_integral>::value ? value_t::Integer : + std::is_floating_point>::value ? value_t::Float : + std::is_convertible, toml::String >::value ? value_t::String : + std::is_convertible, toml::Datetime>::value ? value_t::Datetime: + std::is_convertible, toml::Array >::value ? value_t::Array : + std::is_convertible, toml::Table >::value ? value_t::Table : + value_t::Unknown; +} + template struct is_toml_array : std::false_type{}; template<> struct is_toml_array : std::true_type {}; template struct is_toml_table : std::false_type{}; template<> struct is_toml_table : std::true_type {}; -template -constexpr inline value_t check_type() -{ - return std::is_same, bool>::value ? value_t::Boolean : - std::is_integral>::value ? value_t::Integer : - std::is_floating_point>::value ? value_t::Float : - std::is_same, String>::value ? value_t::String : - std::is_same, const char*>::value ? value_t::String : - toml::detail::is_toml_array>::value ? value_t::Array : - toml::detail::is_toml_table>::value ? value_t::Table : - value_t::Unknown; -} - template struct toml_default_type{}; template<> struct toml_default_type{typedef Boolean type;}; template<> struct toml_default_type{typedef Integer type;}; @@ -137,6 +137,56 @@ template<> struct toml_default_type{typedef Table type;}; template<> struct toml_default_type{typedef void type;}; template<> struct toml_default_type{typedef void type;}; +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(...); +}; + +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 is_container : std::integral_constant::value && has_value_type::value>{}; + +template +struct is_map : std::integral_constant::value && has_key_type::value && + has_mapped_type::value>{}; + +struct is_key_convertible_impl +{ + template + static std::is_convertible + check(typename T::key_type*); + + template static std::false_type check(...); +}; +template +struct is_key_convertible : decltype(is_key_convertible_impl::check(nullptr)){}; + struct storage_base { storage_base(): type(toml::value_t::Empty){} @@ -166,6 +216,33 @@ struct storage : public storage_base }; } // detail +// `is_castable` is used for explicit cast of values. +// implicit conversion is achieved by the same manner as value::ctor. +// so it allows integer->bool conversion. +template +struct is_castable : std::false_type{}; +template +struct is_castable : std::integral_constant::value>{}; +template +struct is_castable : std::integral_constant::value>{}; +template +struct is_castable : std::integral_constant::value>{}; +template +struct is_castable : std::integral_constant::value>{}; +template +struct is_castable : std::integral_constant::value>{}; +template +struct is_castable : std::integral_constant::value || toml::detail::is_container::value>{}; +template +struct is_castable : std::integral_constant::value && toml::detail::is_key_convertible::value>{}; + /* -------------------------------------------------------------------------- */ template inline std::unique_ptr make_unique(Ts&& ... args) @@ -241,6 +318,7 @@ class value template::is_toml_type, std::nullptr_t>::type = nullptr> value(T&& v); + template::is_toml_type, std::nullptr_t>::type = nullptr> value& operator=(T&& v); @@ -676,83 +754,49 @@ value::cast() namespace detail { -struct has_iterator_impl +template +struct to_toml_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(...); + typedef T result_type; + static_assert(toml::is_castable::value, + "type is not castable to any toml value type"); + + static toml::value invoke(const T& v) + { + return toml::value(v); + } + static toml::value invoke(T&& v) + { + return toml::value(std::move(v)); + } }; 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 is_container : std::integral_constant::value && has_value_type::value>{}; - -template -struct is_map : std::integral_constant::value && has_key_type::value && - has_mapped_type::value>{}; - -struct is_key_convertible_impl +struct to_toml_impl { - template - static std::is_convertible - check(typename T::key_type*); + typedef T result_type; - template static std::false_type check(...); + static toml::value invoke(const T& v) + { + return toml::is_same::value ? v : + toml::is_castable::value ? invoke_table(v) : + toml::is_castable::value ? invoke_array(v) : + toml::value(); + } + static toml::value invoke(T&& v) + { + } }; -template -struct is_key_convertible : decltype(is_key_convertible_impl::check(nullptr)){}; -} // detail +} + +template()> +inline toml::value to_toml(T&& x) +{ + return detail::to_toml_impl::invoke(std::forward(x)); +} + -template -struct is_castable : std::false_type{}; -template -struct is_castable : std::integral_constant::value>{}; -template -struct is_castable : std::integral_constant::value>{}; -template -struct is_castable : std::integral_constant::value>{}; -template -struct is_castable : std::integral_constant::value>{}; -template -struct is_castable : std::integral_constant::value>{}; -template -struct is_castable : std::integral_constant::value || toml::detail::is_container::value>{}; -template -struct is_castable : std::integral_constant::value && toml::detail::is_key_convertible::value>{}; -template -struct is_castable : std::true_type{};// XXX }// toml #endif// TOML_FOR_MODERN_CPP