improved support for using enums with value_or()
This commit is contained in:
parent
42a428f8ea
commit
941341fce6
@ -33,6 +33,10 @@ template:
|
|||||||
- fixed `for_each()` compilation error on GCC <= 7 (#197) (@sagi-ottopia, @damirbarr)
|
- fixed `for_each()` compilation error on GCC <= 7 (#197) (@sagi-ottopia, @damirbarr)
|
||||||
- fixed `FLT_RADIX` check getting broken by Intel MKL headers (#202) (@iago-lito)
|
- fixed `FLT_RADIX` check getting broken by Intel MKL headers (#202) (@iago-lito)
|
||||||
|
|
||||||
|
#### Additions
|
||||||
|
|
||||||
|
- improved support for using enums with `value_or()`
|
||||||
|
|
||||||
#### Changes:
|
#### Changes:
|
||||||
|
|
||||||
- renamed header files to have `.hpp` extension (`toml.h` is still present for backwards-compatibility)
|
- renamed header files to have `.hpp` extension (`toml.h` is still present for backwards-compatibility)
|
||||||
|
@ -476,10 +476,22 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
template <typename T, typename... U>
|
template <typename T, typename... U>
|
||||||
inline constexpr bool first_is_same<T, T, U...> = true;
|
inline constexpr bool first_is_same<T, T, U...> = true;
|
||||||
|
|
||||||
|
template <typename T, bool = std::is_enum_v<T>>
|
||||||
|
struct underlying_type_
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<T>;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct underlying_type_<T, false>
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
using underlying_type = typename underlying_type_<T>::type;
|
||||||
|
|
||||||
// general value traits
|
// general value traits
|
||||||
// (as they relate to their equivalent native TOML type)
|
// (as they relate to their equivalent native TOML type)
|
||||||
template <typename T>
|
struct default_value_traits
|
||||||
struct value_traits
|
|
||||||
{
|
{
|
||||||
using native_type = void;
|
using native_type = void;
|
||||||
static constexpr bool is_native = false;
|
static constexpr bool is_native = false;
|
||||||
@ -489,6 +501,27 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
static constexpr auto type = node_type::none;
|
static constexpr auto type = node_type::none;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits;
|
||||||
|
|
||||||
|
template <typename T, bool = std::is_enum_v<T>>
|
||||||
|
struct value_traits_base_selector
|
||||||
|
{
|
||||||
|
static_assert(!is_cvref<T>);
|
||||||
|
|
||||||
|
using type = default_value_traits;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits_base_selector<T, true>
|
||||||
|
{
|
||||||
|
static_assert(!is_cvref<T>);
|
||||||
|
|
||||||
|
using type = value_traits<underlying_type<T>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits : value_traits_base_selector<T>::type
|
||||||
|
{};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct value_traits<const T> : value_traits<T>
|
struct value_traits<const T> : value_traits<T>
|
||||||
{};
|
{};
|
||||||
@ -509,22 +542,23 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct integer_limits
|
struct integer_limits
|
||||||
{
|
{
|
||||||
static constexpr auto min = (std::numeric_limits<T>::min)();
|
static constexpr T min = T{ (std::numeric_limits<underlying_type<T>>::min)() };
|
||||||
static constexpr auto max = (std::numeric_limits<T>::max)();
|
static constexpr T max = T{ (std::numeric_limits<underlying_type<T>>::max)() };
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct integer_traits_base : integer_limits<T>
|
struct integer_traits_base : integer_limits<T>
|
||||||
{
|
{
|
||||||
using native_type = int64_t;
|
using native_type = int64_t;
|
||||||
static constexpr bool is_native = std::is_same_v<T, native_type>;
|
static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>;
|
||||||
static constexpr bool is_signed = static_cast<T>(-1) < T{}; // for impls not specializing std::is_signed<T>
|
static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{};
|
||||||
static constexpr auto type = node_type::integer;
|
static constexpr auto type = node_type::integer;
|
||||||
static constexpr bool can_partially_represent_native = true;
|
static constexpr bool can_partially_represent_native = true;
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unsigned_integer_traits : integer_traits_base<T>
|
struct unsigned_integer_traits : integer_traits_base<T>
|
||||||
{
|
{
|
||||||
static constexpr bool is_losslessly_convertible_to_native = integer_limits<T>::max <= 9223372036854775807ULL;
|
static constexpr bool is_losslessly_convertible_to_native =
|
||||||
|
integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL;
|
||||||
static constexpr bool can_represent_native = false;
|
static constexpr bool can_represent_native = false;
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -532,9 +566,11 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
{
|
{
|
||||||
using native_type = int64_t;
|
using native_type = int64_t;
|
||||||
static constexpr bool is_losslessly_convertible_to_native =
|
static constexpr bool is_losslessly_convertible_to_native =
|
||||||
integer_limits<T>::min >= (-9223372036854775807LL - 1LL) && integer_limits<T>::max <= 9223372036854775807LL;
|
integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL)
|
||||||
|
&& integer_limits<underlying_type<T>>::max <= 9223372036854775807LL;
|
||||||
static constexpr bool can_represent_native =
|
static constexpr bool can_represent_native =
|
||||||
integer_limits<T>::min <= (-9223372036854775807LL - 1LL) && integer_limits<T>::max >= 9223372036854775807LL;
|
integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL)
|
||||||
|
&& integer_limits<underlying_type<T>>::max >= 9223372036854775807LL;
|
||||||
};
|
};
|
||||||
template <typename T, bool S = integer_traits_base<T>::is_signed>
|
template <typename T, bool S = integer_traits_base<T>::is_signed>
|
||||||
struct integer_traits : signed_integer_traits<T>
|
struct integer_traits : signed_integer_traits<T>
|
||||||
|
@ -59,7 +59,7 @@ TOML_DISABLE_ARITHMETIC_WARNINGS;
|
|||||||
TOML_SA_LIST_END \
|
TOML_SA_LIST_END \
|
||||||
\
|
\
|
||||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" \
|
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" \
|
||||||
TOML_SA_LIST_BEG "any other integer type" \
|
TOML_SA_LIST_BEG "any other integral type" \
|
||||||
TOML_SA_LIST_SEP "any floating-point type" \
|
TOML_SA_LIST_SEP "any floating-point type" \
|
||||||
TOML_SA_LIST_END \
|
TOML_SA_LIST_END \
|
||||||
\
|
\
|
||||||
@ -1221,7 +1221,7 @@ TOML_NAMESPACE_START
|
|||||||
TOML_SA_LIST_END
|
TOML_SA_LIST_END
|
||||||
|
|
||||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
||||||
TOML_SA_LIST_BEG "any other integer type"
|
TOML_SA_LIST_BEG "any other integral type"
|
||||||
TOML_SA_LIST_SEP "any floating-point type"
|
TOML_SA_LIST_SEP "any floating-point type"
|
||||||
TOML_SA_LIST_END
|
TOML_SA_LIST_END
|
||||||
|
|
||||||
|
@ -393,4 +393,23 @@ b = []
|
|||||||
y = 2
|
y = 2
|
||||||
)"sv);
|
)"sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("tomlplusplus/issues/207") // https://github.com/marzer/tomlplusplus/issues/207
|
||||||
|
{
|
||||||
|
enum class an_enum
|
||||||
|
{
|
||||||
|
zero,
|
||||||
|
one,
|
||||||
|
two,
|
||||||
|
three
|
||||||
|
};
|
||||||
|
|
||||||
|
parsing_should_succeed(FILE_LINE_ARGS,
|
||||||
|
"val = 2\n",
|
||||||
|
[](auto&& tbl)
|
||||||
|
{
|
||||||
|
const auto val = tbl["val"].template value_or<an_enum>(an_enum::zero);
|
||||||
|
CHECK(val == an_enum::two);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
58
toml.hpp
58
toml.hpp
@ -1742,10 +1742,22 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
template <typename T, typename... U>
|
template <typename T, typename... U>
|
||||||
inline constexpr bool first_is_same<T, T, U...> = true;
|
inline constexpr bool first_is_same<T, T, U...> = true;
|
||||||
|
|
||||||
|
template <typename T, bool = std::is_enum_v<T>>
|
||||||
|
struct underlying_type_
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<T>;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct underlying_type_<T, false>
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
using underlying_type = typename underlying_type_<T>::type;
|
||||||
|
|
||||||
// general value traits
|
// general value traits
|
||||||
// (as they relate to their equivalent native TOML type)
|
// (as they relate to their equivalent native TOML type)
|
||||||
template <typename T>
|
struct default_value_traits
|
||||||
struct value_traits
|
|
||||||
{
|
{
|
||||||
using native_type = void;
|
using native_type = void;
|
||||||
static constexpr bool is_native = false;
|
static constexpr bool is_native = false;
|
||||||
@ -1755,6 +1767,27 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
static constexpr auto type = node_type::none;
|
static constexpr auto type = node_type::none;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits;
|
||||||
|
|
||||||
|
template <typename T, bool = std::is_enum_v<T>>
|
||||||
|
struct value_traits_base_selector
|
||||||
|
{
|
||||||
|
static_assert(!is_cvref<T>);
|
||||||
|
|
||||||
|
using type = default_value_traits;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits_base_selector<T, true>
|
||||||
|
{
|
||||||
|
static_assert(!is_cvref<T>);
|
||||||
|
|
||||||
|
using type = value_traits<underlying_type<T>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct value_traits : value_traits_base_selector<T>::type
|
||||||
|
{};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct value_traits<const T> : value_traits<T>
|
struct value_traits<const T> : value_traits<T>
|
||||||
{};
|
{};
|
||||||
@ -1775,22 +1808,23 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct integer_limits
|
struct integer_limits
|
||||||
{
|
{
|
||||||
static constexpr auto min = (std::numeric_limits<T>::min)();
|
static constexpr T min = T{ (std::numeric_limits<underlying_type<T>>::min)() };
|
||||||
static constexpr auto max = (std::numeric_limits<T>::max)();
|
static constexpr T max = T{ (std::numeric_limits<underlying_type<T>>::max)() };
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct integer_traits_base : integer_limits<T>
|
struct integer_traits_base : integer_limits<T>
|
||||||
{
|
{
|
||||||
using native_type = int64_t;
|
using native_type = int64_t;
|
||||||
static constexpr bool is_native = std::is_same_v<T, native_type>;
|
static constexpr bool is_native = std::is_same_v<underlying_type<T>, native_type>;
|
||||||
static constexpr bool is_signed = static_cast<T>(-1) < T{}; // for impls not specializing std::is_signed<T>
|
static constexpr bool is_signed = static_cast<underlying_type<T>>(-1) < underlying_type<T>{};
|
||||||
static constexpr auto type = node_type::integer;
|
static constexpr auto type = node_type::integer;
|
||||||
static constexpr bool can_partially_represent_native = true;
|
static constexpr bool can_partially_represent_native = true;
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unsigned_integer_traits : integer_traits_base<T>
|
struct unsigned_integer_traits : integer_traits_base<T>
|
||||||
{
|
{
|
||||||
static constexpr bool is_losslessly_convertible_to_native = integer_limits<T>::max <= 9223372036854775807ULL;
|
static constexpr bool is_losslessly_convertible_to_native =
|
||||||
|
integer_limits<underlying_type<T>>::max <= 9223372036854775807ULL;
|
||||||
static constexpr bool can_represent_native = false;
|
static constexpr bool can_represent_native = false;
|
||||||
};
|
};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1798,9 +1832,11 @@ TOML_IMPL_NAMESPACE_START
|
|||||||
{
|
{
|
||||||
using native_type = int64_t;
|
using native_type = int64_t;
|
||||||
static constexpr bool is_losslessly_convertible_to_native =
|
static constexpr bool is_losslessly_convertible_to_native =
|
||||||
integer_limits<T>::min >= (-9223372036854775807LL - 1LL) && integer_limits<T>::max <= 9223372036854775807LL;
|
integer_limits<underlying_type<T>>::min >= (-9223372036854775807LL - 1LL)
|
||||||
|
&& integer_limits<underlying_type<T>>::max <= 9223372036854775807LL;
|
||||||
static constexpr bool can_represent_native =
|
static constexpr bool can_represent_native =
|
||||||
integer_limits<T>::min <= (-9223372036854775807LL - 1LL) && integer_limits<T>::max >= 9223372036854775807LL;
|
integer_limits<underlying_type<T>>::min <= (-9223372036854775807LL - 1LL)
|
||||||
|
&& integer_limits<underlying_type<T>>::max >= 9223372036854775807LL;
|
||||||
};
|
};
|
||||||
template <typename T, bool S = integer_traits_base<T>::is_signed>
|
template <typename T, bool S = integer_traits_base<T>::is_signed>
|
||||||
struct integer_traits : signed_integer_traits<T>
|
struct integer_traits : signed_integer_traits<T>
|
||||||
@ -4765,7 +4801,7 @@ TOML_DISABLE_ARITHMETIC_WARNINGS;
|
|||||||
TOML_SA_LIST_END \
|
TOML_SA_LIST_END \
|
||||||
\
|
\
|
||||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" \
|
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type" \
|
||||||
TOML_SA_LIST_BEG "any other integer type" \
|
TOML_SA_LIST_BEG "any other integral type" \
|
||||||
TOML_SA_LIST_SEP "any floating-point type" \
|
TOML_SA_LIST_SEP "any floating-point type" \
|
||||||
TOML_SA_LIST_END \
|
TOML_SA_LIST_END \
|
||||||
\
|
\
|
||||||
@ -5743,7 +5779,7 @@ TOML_NAMESPACE_START
|
|||||||
TOML_SA_LIST_END
|
TOML_SA_LIST_END
|
||||||
|
|
||||||
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
TOML_SA_LIST_NXT "A non-view type capable of (reasonably) representing a native TOML value type"
|
||||||
TOML_SA_LIST_BEG "any other integer type"
|
TOML_SA_LIST_BEG "any other integral type"
|
||||||
TOML_SA_LIST_SEP "any floating-point type"
|
TOML_SA_LIST_SEP "any floating-point type"
|
||||||
TOML_SA_LIST_END
|
TOML_SA_LIST_END
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user