mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1a55b1331 | ||
|
|
170b0d6b3f | ||
|
|
433636a06f | ||
|
|
9555817901 | ||
|
|
e54deacf1a | ||
|
|
b6f53cae7a | ||
|
|
f953a9cf23 | ||
|
|
117549bf70 | ||
|
|
4287160254 |
@@ -4,6 +4,7 @@ toml11
|
||||
[](https://travis-ci.org/ToruNiina/toml11)
|
||||
[](https://ci.appveyor.com/project/ToruNiina/toml11)
|
||||
[](LICENSE)
|
||||
[](https://doi.org/10.5281/zenodo.1209136)
|
||||
|
||||
c++11 header-only toml parser depending only on c++11 standard library.
|
||||
|
||||
|
||||
@@ -170,3 +170,22 @@ BOOST_AUTO_TEST_CASE(test_from_toml_tie)
|
||||
BOOST_CHECK_EQUAL(ut["val4"].cast<toml::value_t::String >(), "piyo");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_from_toml_tuple)
|
||||
{
|
||||
toml::Array a;
|
||||
a.emplace_back(2);
|
||||
a.emplace_back(7);
|
||||
a.emplace_back(1);
|
||||
a.emplace_back(8);
|
||||
a.emplace_back(2);
|
||||
toml::value v(a);
|
||||
|
||||
std::tuple<int, int, int, int, int> t;
|
||||
toml::from_toml(t, v);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::get<0>(t), 2);
|
||||
BOOST_CHECK_EQUAL(std::get<1>(t), 7);
|
||||
BOOST_CHECK_EQUAL(std::get<2>(t), 1);
|
||||
BOOST_CHECK_EQUAL(std::get<3>(t), 8);
|
||||
BOOST_CHECK_EQUAL(std::get<4>(t), 2);
|
||||
}
|
||||
|
||||
@@ -74,16 +74,11 @@ BOOST_AUTO_TEST_CASE(test_is_xxx)
|
||||
BOOST_CHECK(toml::detail::is_container<std_array_type>::value);
|
||||
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value);
|
||||
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value);
|
||||
BOOST_CHECK(toml::detail::is_container<std_map_type>::value);
|
||||
BOOST_CHECK(toml::detail::is_container<std_unordered_map_type>::value);
|
||||
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value);
|
||||
|
||||
BOOST_CHECK(!toml::detail::is_container<std_map_type>::value);
|
||||
BOOST_CHECK(!toml::detail::is_container<std_unordered_map_type>::value);
|
||||
|
||||
BOOST_CHECK(toml::detail::is_map<std_map_type>::value);
|
||||
BOOST_CHECK(toml::detail::is_map<std_unordered_map_type>::value);
|
||||
|
||||
BOOST_CHECK(toml::detail::is_key_convertible<std_map_type>::value);
|
||||
BOOST_CHECK(toml::detail::is_key_convertible<std_unordered_map_type>::value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,66 +1,14 @@
|
||||
#ifndef TOML11_FROM_TOML
|
||||
#define TOML11_FROM_TOML
|
||||
#include "value.hpp"
|
||||
#include "get.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
||||
template<typename T>
|
||||
void from_toml(T& x, const toml::value& v)
|
||||
{
|
||||
if(v.type() != vT)
|
||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
||||
std::string(" is not arguemnt type: ") + stringize(vT));
|
||||
x = v.cast<vT>();
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
(!toml::detail::is_map<T>::value) &&
|
||||
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
|
||||
void from_toml(T& x, const toml::value& v)
|
||||
{
|
||||
// TODO the case of x is not dynamic container case
|
||||
if(v.type() != value_t::Array)
|
||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
||||
std::string(" is not argument type: Array"));
|
||||
const auto& ar = v.cast<value_t::Array>();
|
||||
try
|
||||
{
|
||||
toml::resize(x, ar.size());
|
||||
}
|
||||
catch(std::invalid_argument& iv)
|
||||
{
|
||||
throw toml::type_error("toml::from_toml: static array size is not enough");
|
||||
}
|
||||
auto iter = x.begin();
|
||||
for(const auto& val : ar)
|
||||
{
|
||||
typename T::value_type v;
|
||||
from_toml(v, val);
|
||||
*iter = std::move(v);
|
||||
++iter;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
||||
void from_toml(T& x, const toml::value& v)
|
||||
{
|
||||
if(v.type() != value_t::Table)
|
||||
throw type_error("from_toml: value type: " + stringize(v.type()) +
|
||||
std::string(" is not argument type: Table"));
|
||||
x.clear();
|
||||
const auto& tb = v.cast<value_t::Table>();
|
||||
for(const auto& kv : tb)
|
||||
{
|
||||
x.insert(kv);
|
||||
}
|
||||
x = toml::get<T>(v);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
114
toml/get.hpp
114
toml/get.hpp
@@ -6,55 +6,121 @@
|
||||
namespace toml
|
||||
{
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
||||
inline T get(const toml::value& v)
|
||||
template<typename T, typename std::enable_if<
|
||||
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||
inline T& get(value& v)
|
||||
{
|
||||
return static_cast<T>(v.cast<vT>());
|
||||
constexpr value_t kind = detail::check_type<T>();
|
||||
return v.cast<kind>();
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<
|
||||
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||
inline T const& get(const value& v)
|
||||
{
|
||||
constexpr value_t kind = detail::check_type<T>();
|
||||
return v.cast<kind>();
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>,
|
||||
detail::negation<std::is_same<T, bool>>, std::is_integral<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
inline T get(const value& v)
|
||||
{
|
||||
return static_cast<T>(v.cast<value_t::Integer>());
|
||||
}
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, std::is_floating_point<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
inline T get(const value& v)
|
||||
{
|
||||
return static_cast<T>(v.cast<value_t::Float>());
|
||||
}
|
||||
|
||||
// array-like type
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
(!toml::detail::is_map<T>::value) &&
|
||||
toml::detail::is_container<T>::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>>, detail::is_container<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
T get(const value& v)
|
||||
{
|
||||
if(v.type() != value_t::Array)
|
||||
throw type_error("get: value type: " + stringize(v.type()) +
|
||||
std::string(" is not argument type: Array"));
|
||||
|
||||
const auto& ar = v.cast<value_t::Array>();
|
||||
T tmp;
|
||||
try
|
||||
{
|
||||
toml::resize(tmp, ar.size());
|
||||
::toml::resize(tmp, ar.size());
|
||||
}
|
||||
catch(std::invalid_argument& iv)
|
||||
{
|
||||
throw toml::type_error("toml::get: static array size is not enough");
|
||||
throw type_error("toml::get: static array: size is not enough");
|
||||
}
|
||||
std::transform(ar.cbegin(), ar.cend(), tmp.begin(),
|
||||
[](toml::value const& elem){return get<typename T::value_type>(elem);});
|
||||
[](value const& elem){return get<typename T::value_type>(elem);});
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// table-like case
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, detail::is_map<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
T get(const toml::value& v)
|
||||
{
|
||||
if(v.type() != value_t::Table)
|
||||
throw type_error("get: value type: " + stringize(v.type()) +
|
||||
std::string(" is not argument type: Table"));
|
||||
T tmp;
|
||||
const auto& tb = v.cast<value_t::Table>();
|
||||
T tmp;
|
||||
for(const auto& kv : tb){tmp.insert(kv);}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// array -> pair
|
||||
template<typename T, typename std::enable_if<detail::is_std_pair<T>::value,
|
||||
std::nullptr_t>::type = nullptr>
|
||||
T get(const value& v)
|
||||
{
|
||||
using first_type = typename T::first_type;
|
||||
using second_type = typename T::second_type;
|
||||
const auto& ar = v.cast<value_t::Array>();
|
||||
if(ar.size() != 2)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
"toml::get<std::pair>: value does not have 2 elements.");
|
||||
}
|
||||
|
||||
T tmp;
|
||||
tmp.first = get<first_type >(ar.at(0));
|
||||
tmp.second = get<second_type>(ar.at(1));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T, std::size_t ...I>
|
||||
T get_tuple_impl(const toml::Array& a, index_sequence<I...>)
|
||||
{
|
||||
return std::make_tuple(
|
||||
::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
// array -> tuple
|
||||
template<typename T, typename std::enable_if<detail::is_std_tuple<T>::value,
|
||||
std::nullptr_t>::type = nullptr>
|
||||
T get(const value& v)
|
||||
{
|
||||
const auto& ar = v.cast<value_t::Array>();
|
||||
if(ar.size() != std::tuple_size<T>::value)
|
||||
{
|
||||
throw std::out_of_range(
|
||||
"toml::get<std::tuple>: array value does not have " +
|
||||
std::to_string(std::tuple_size<T>::value) +
|
||||
std::string(" elements (array has ") + std::to_string(ar.size()) +
|
||||
std::string(" elements)."));
|
||||
}
|
||||
return detail::get_tuple_impl<T>(ar,
|
||||
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
||||
}
|
||||
|
||||
// get_or -----------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -5,47 +5,76 @@
|
||||
namespace toml
|
||||
{
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT != toml::value_t::Unknown &&
|
||||
vT != value_t::Empty), std::nullptr_t>::type = nullptr>
|
||||
inline toml::value to_toml(T&& x)
|
||||
template<typename T, typename std::enable_if<
|
||||
detail::is_exact_toml_type<T>::value, std::nullptr_t>::type = nullptr>
|
||||
inline value to_toml(const T& x)
|
||||
{
|
||||
return toml::value(std::forward<T>(x));
|
||||
return value(x);
|
||||
}
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
(!toml::detail::is_map<T>::value) &&
|
||||
toml::detail::is_container<T>::value, std::nullptr_t>::type = nullptr>
|
||||
toml::value to_toml(T&& x)
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, std::is_integral<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
inline value to_toml(const T& x)
|
||||
{
|
||||
toml::Array tmp; tmp.reserve(std::distance(std::begin(x), std::end(x)));
|
||||
return value(::toml::Integer(x));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, std::is_floating_point<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
inline value to_toml(const T& x)
|
||||
{
|
||||
return value(::toml::Float(x));
|
||||
}
|
||||
|
||||
inline value to_toml(const char* str)
|
||||
{
|
||||
return value(::toml::String(str));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, detail::is_container<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
value to_toml(const T& x)
|
||||
{
|
||||
Array tmp;
|
||||
tmp.reserve(std::distance(std::begin(x), std::end(x)));
|
||||
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
|
||||
{
|
||||
tmp.emplace_back(*iter);
|
||||
return toml::value(std::move(tmp));
|
||||
}
|
||||
return value(std::move(tmp));
|
||||
}
|
||||
|
||||
template<typename T, toml::value_t vT = toml::detail::check_type<T>(),
|
||||
typename std::enable_if<(vT == toml::value_t::Unknown) &&
|
||||
toml::detail::is_map<T>::value, std::nullptr_t>::type = nullptr>
|
||||
toml::value to_toml(T&& x)
|
||||
template<typename T, typename std::enable_if<detail::conjunction<
|
||||
detail::negation<detail::is_exact_toml_type<T>>, detail::is_map<T>
|
||||
>::value, std::nullptr_t>::type = nullptr>
|
||||
value to_toml(const T& x)
|
||||
{
|
||||
toml::Table tmp;
|
||||
Table tmp;
|
||||
for(auto iter = std::begin(x); iter != std::end(x); ++iter)
|
||||
{
|
||||
tmp.emplace(iter->first, to_toml(iter->second));
|
||||
return toml::value(std::move(tmp));
|
||||
}
|
||||
return value(std::move(tmp));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline toml::value to_toml(std::initializer_list<T> init)
|
||||
inline value to_toml(std::initializer_list<T> init)
|
||||
{
|
||||
return toml::value(std::move(init));
|
||||
return value(std::move(init));
|
||||
}
|
||||
|
||||
inline toml::value
|
||||
to_toml(std::initializer_list<std::pair<std::string, toml::value>> init)
|
||||
inline value to_toml(std::initializer_list<std::pair<std::string, value>> init)
|
||||
{
|
||||
return toml::value(std::move(init));
|
||||
return value(std::move(init));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline value to_toml(const value& x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
} // toml
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef TOML11_TRAITS
|
||||
#define TOML11_TRAITS
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -58,14 +60,54 @@ struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){}
|
||||
#undef decltype(...)
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct is_container : std::integral_constant<bool,
|
||||
has_iterator<T>::value && has_value_type<T>::value>{};
|
||||
template<typename ...> struct conjunction : std::true_type{};
|
||||
template<typename T> struct conjunction<T> : T{};
|
||||
template<typename T, typename ... Ts>
|
||||
struct conjunction<T, Ts...> :
|
||||
std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
|
||||
{};
|
||||
|
||||
template<typename ...> struct disjunction : std::false_type{};
|
||||
template<typename T> struct disjunction<T> : T {};
|
||||
template<typename T, typename ... Ts>
|
||||
struct disjunction<T, Ts...> :
|
||||
std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct is_map : std::integral_constant<bool,
|
||||
has_iterator<T>::value && has_key_type<T>::value &&
|
||||
has_mapped_type<T>::value>{};
|
||||
struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
|
||||
|
||||
template<typename T> struct is_std_pair : std::false_type{};
|
||||
template<typename T1, typename T2>
|
||||
struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
|
||||
|
||||
template<typename T> struct is_std_tuple : std::false_type{};
|
||||
template<typename ... Ts>
|
||||
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
|
||||
|
||||
// to use toml::get<std::tuple<T1, T2, ...>> in C++11
|
||||
template<std::size_t ... Ns> struct index_sequence{};
|
||||
|
||||
template<typename IS, std::size_t N> struct push_back_index_sequence{};
|
||||
template<std::size_t N, std::size_t ... Ns>
|
||||
struct push_back_index_sequence<index_sequence<Ns...>, N>
|
||||
{
|
||||
typedef index_sequence<Ns..., N> type;
|
||||
};
|
||||
|
||||
template<std::size_t N>
|
||||
struct index_sequence_maker
|
||||
{
|
||||
typedef typename push_back_index_sequence<
|
||||
typename index_sequence_maker<N-1>::type, N>::type type;
|
||||
};
|
||||
template<>
|
||||
struct index_sequence_maker<0>
|
||||
{
|
||||
typedef index_sequence<0> type;
|
||||
};
|
||||
template<std::size_t N>
|
||||
using make_index_sequence = typename index_sequence_maker<N-1>::type;
|
||||
|
||||
}// detail
|
||||
}//toml
|
||||
|
||||
@@ -99,33 +99,6 @@ constexpr inline bool is_valid(value_t vt)
|
||||
return vt != value_t::Unknown;
|
||||
}
|
||||
|
||||
template<typename T> struct is_toml_array : std::false_type{};
|
||||
template<> struct is_toml_array<toml::Array> : std::true_type {};
|
||||
template<typename T> struct is_toml_table : std::false_type{};
|
||||
template<> struct is_toml_table<toml::Table> : std::true_type {};
|
||||
|
||||
struct is_key_convertible_impl
|
||||
{
|
||||
template<typename T>
|
||||
static std::is_convertible<typename T::key_type, toml::key>
|
||||
check(typename T::key_type*);
|
||||
|
||||
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
|
||||
#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct is_key_convertible : decltype(is_key_convertible_impl::check<T>(nullptr)){};
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#undef decltype(...)
|
||||
#endif
|
||||
|
||||
template<value_t t> struct toml_default_type{};
|
||||
template<> struct toml_default_type<value_t::Boolean >{typedef Boolean type;};
|
||||
template<> struct toml_default_type<value_t::Integer >{typedef Integer type;};
|
||||
@@ -137,6 +110,33 @@ template<> struct toml_default_type<value_t::Table >{typedef Table type;};
|
||||
template<> struct toml_default_type<value_t::Empty >{typedef void type;};
|
||||
template<> struct toml_default_type<value_t::Unknown >{typedef void type;};
|
||||
|
||||
template<typename T>
|
||||
struct is_exact_toml_type : disjunction<
|
||||
std::is_same<T, Boolean >,
|
||||
std::is_same<T, Integer >,
|
||||
std::is_same<T, Float >,
|
||||
std::is_same<T, String >,
|
||||
std::is_same<T, Datetime>,
|
||||
std::is_same<T, Array >,
|
||||
std::is_same<T, Table >
|
||||
>{};
|
||||
|
||||
template<typename T>
|
||||
struct is_map : conjunction<
|
||||
has_iterator<T>,
|
||||
has_value_type<T>,
|
||||
has_key_type<T>,
|
||||
has_mapped_type<T>
|
||||
>{};
|
||||
|
||||
template<typename T>
|
||||
struct is_container : conjunction<
|
||||
negation<is_map<T>>,
|
||||
negation<std::is_same<T, String>>,
|
||||
has_iterator<T>,
|
||||
has_value_type<T>
|
||||
>{};
|
||||
|
||||
struct storage_base
|
||||
{
|
||||
storage_base(): type(toml::value_t::Empty){}
|
||||
@@ -148,7 +148,8 @@ struct storage_base
|
||||
template<typename T>
|
||||
struct storage : public storage_base
|
||||
{
|
||||
static_assert(is_toml_array<T>::value || is_toml_table<T>::value,
|
||||
static_assert(std::is_same<T, toml::Array>::value ||
|
||||
std::is_same<T, toml::Table>::value,
|
||||
"toml::detail::storage is for toml::Array or toml::Table!");
|
||||
typedef T value_type;
|
||||
|
||||
@@ -591,21 +592,21 @@ template<typename T, typename std::enable_if<
|
||||
value_traits<T>::is_toml_type, std::nullptr_t>::type>
|
||||
value::value(T&& v) : type_(toml::detail::check_type<T>())
|
||||
{
|
||||
switch_assign<toml::detail::check_type<T>()>::invoke(
|
||||
*this, std::forward<T>(v));
|
||||
constexpr value_t kind = toml::detail::check_type<T>();
|
||||
switch_assign<kind>::invoke(*this, std::forward<T>(v));
|
||||
}
|
||||
|
||||
template<typename T, typename std::enable_if<
|
||||
value_traits<T>::is_toml_type, std::nullptr_t>::type>
|
||||
value& value::operator=(T&& v)
|
||||
{
|
||||
constexpr value_t kind = toml::detail::check_type<T>();
|
||||
if(should_be_cleaned(this->type_))
|
||||
{
|
||||
switch_clean(this->type_);
|
||||
}
|
||||
this->type_ = toml::detail::check_type<T>();
|
||||
switch_assign<toml::detail::check_type<T>()>::invoke(
|
||||
*this, std::forward<T>(v));
|
||||
this->type_ = kind;
|
||||
switch_assign<kind>::invoke(*this, std::forward<T>(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user