Merge pull request #38 from ToruNiina/get-any-type

extended conversions
This commit is contained in:
Toru Niina
2019-03-17 13:11:59 +09:00
committed by GitHub
8 changed files with 405 additions and 0 deletions

20
toml/from.hpp Normal file
View File

@@ -0,0 +1,20 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_FROM_HPP
#define TOML11_FROM_HPP
#include "traits.hpp"
namespace toml
{
template<typename T>
struct from;
// {
// static T from_toml(const toml::value& v)
// {
// // User-defined conversions ...
// }
// };
} // toml
#endif // TOML11_FROM_HPP

View File

@@ -2,6 +2,7 @@
// Distributed under the MIT License.
#ifndef TOML11_GET_HPP
#define TOML11_GET_HPP
#include "from.hpp"
#include "result.hpp"
#include "value.hpp"
#include <algorithm>
@@ -173,6 +174,20 @@ template<typename T, typename std::enable_if<detail::conjunction<
>::value, std::nullptr_t>::type = nullptr>
T get(const toml::value& v);
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
detail::has_from_toml_method<T>, // but has from_toml(toml::value) memfn
std::is_default_constructible<T> // and default constructible
>::value, std::nullptr_t>::type = nullptr>
T get(const toml::value& v);
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>> // not a toml::value
>::value, std::nullptr_t>::type = nullptr,
std::size_t = sizeof(::toml::from<T>) // and has from<T> specialization
>
T get(const toml::value& v);
// ============================================================================
// array-like types; most likely STL container, like std::vector, etc.
@@ -297,6 +312,29 @@ T get(const toml::value& v)
return map;
}
// ============================================================================
// user-defined, but compatible types.
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
detail::has_from_toml_method<T>, // but has from_toml(toml::value) memfn
std::is_default_constructible<T> // and default constructible
>::value, std::nullptr_t>::type>
T get(const toml::value& v)
{
T ud;
ud.from_toml(v);
return ud;
}
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>> // not a toml::value
>::value, std::nullptr_t>::type, std::size_t> // and has from<T>
T get(const toml::value& v)
{
return ::toml::from<T>::from_toml(v);
}
// ============================================================================
// find and get

20
toml/into.hpp Normal file
View File

@@ -0,0 +1,20 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_INTO_HPP
#define TOML11_INTO_HPP
#include "traits.hpp"
namespace toml
{
template<typename T>
struct into;
// {
// static toml::value into_toml(const T& user_defined_type)
// {
// // User-defined conversions ...
// }
// };
} // toml
#endif // TOML11_INTO_HPP

View File

@@ -9,6 +9,9 @@
namespace toml
{
class value; // forward decl
namespace detail
{
@@ -45,6 +48,22 @@ struct has_resize_method_impl
template<typename T> static std::false_type check(...);
};
struct has_from_toml_method_impl
{
template<typename T>
static std::true_type check(
decltype(std::declval<T>().from_toml(std::declval<::toml::value>()))*);
template<typename T>
static std::false_type check(...);
};
struct has_into_toml_method_impl
{
template<typename T>
static std::true_type check(decltype(std::declval<T>().into_toml())*);
template<typename T>
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
@@ -62,6 +81,14 @@ struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
template<typename T>
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
template<typename T>
struct has_from_toml_method
: decltype(has_from_toml_method_impl::check<T>(nullptr)){};
template<typename T>
struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
#ifdef __INTEL_COMPILER
#undef decltype(...)
#endif

View File

@@ -3,6 +3,7 @@
#ifndef TOML11_VALUE_HPP
#define TOML11_VALUE_HPP
#include "traits.hpp"
#include "into.hpp"
#include "utility.hpp"
#include "exception.hpp"
#include "storage.hpp"
@@ -533,6 +534,46 @@ class value
return *this;
}
// user-defined =========================================================
// convert using into_toml() method -------------------------------------
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
detail::has_into_toml_method<T> // but has `into_toml` method
>::value, std::nullptr_t>::type = nullptr>
value(const T& ud): value(ud.into_toml()) {}
template<typename T, typename std::enable_if<detail::conjunction<
detail::negation<detail::is_exact_toml_type<T>>, // not a toml::value
detail::has_into_toml_method<T> // but has `into_toml` method
>::value, std::nullptr_t>::type = nullptr>
value& operator=(const T& ud)
{
*this = ud.into_toml();
return *this;
}
// convert using into<T> struct -----------------------------------------
template<typename T, typename std::enable_if<
detail::negation<detail::is_exact_toml_type<T>>::value,
std::nullptr_t>::type = nullptr,
std::size_t S = sizeof(::toml::into<T>)>
value(const T& ud): value(::toml::into<T>::into_toml(ud)) {}
template<typename T, typename std::enable_if<
detail::negation<detail::is_exact_toml_type<T>>::value,
std::nullptr_t>::type = nullptr,
std::size_t S = sizeof(::toml::into<T>)>
value& operator=(const T& ud)
{
*this = ::toml::into<T>::into_toml(ud);
return *this;
}
// type checking and casting ============================================
template<typename T>
bool is() const noexcept {return value_traits<T>::type_index == this->type_;}
bool is(value_t t) const noexcept {return t == this->type_;}