improve nameof_enum

This commit is contained in:
neargye 2019-10-19 16:23:36 +05:00
parent 240b3f4d6a
commit 64499c3763

View file

@ -6,6 +6,7 @@
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____| // |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
// https://github.com/Neargye/nameof // https://github.com/Neargye/nameof
// vesion 0.9.1 // vesion 0.9.1
// vesion 0.9.2
// //
// Licensed under the MIT License <http://opensource.org/licenses/MIT>. // Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -33,6 +34,7 @@
#define NEARGYE_NAMEOF_HPP #define NEARGYE_NAMEOF_HPP
#include <array> #include <array>
#include <cstdint>
#include <cstddef> #include <cstddef>
#include <iosfwd> #include <iosfwd>
#include <iterator> #include <iterator>
@ -380,35 +382,39 @@ constexpr bool mixed_sign_less(L lhs, R rhs) noexcept {
} }
} }
template <typename L, typename R> template <typename E>
constexpr int mixed_sign_min_as_int(L lhs, R rhs) noexcept { constexpr int reflected_min() noexcept {
static_assert(std::is_integral_v<L> && std::is_integral_v<R>, "nameof::detail::mixed_sign_min_as_int requires integral type."); static_assert(is_enum_v<E>, "nameof::detail::reflected_min requires enum type.");
constexpr auto lhs = enum_range<E>::min;
static_assert(lhs > (std::numeric_limits<std::int16_t>::min)(), "nameof::enum_range requires min must be greater than INT16_MIN.");
constexpr auto rhs = (std::numeric_limits<std::underlying_type_t<E>>::min)();
return mixed_sign_less(lhs, rhs) ? static_cast<int>(lhs) : static_cast<int>(rhs); return mixed_sign_less(lhs, rhs) ? rhs : lhs;
}
template <typename L, typename R>
constexpr int mixed_sign_max_as_int(L lhs, R rhs) noexcept {
static_assert(std::is_integral_v<L> && std::is_integral_v<R>, "nameof::detail::mixed_sign_max_as_int requires integral type.");
return mixed_sign_less(lhs, rhs) ? static_cast<int>(rhs) : static_cast<int>(lhs);
} }
template <typename E> template <typename E>
inline constexpr int reflected_min_v = mixed_sign_max_as_int(enum_range<E>::min, (std::numeric_limits<std::underlying_type_t<E>>::min)()); constexpr int reflected_max() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::reflected_max requires enum type.");
constexpr auto lhs = enum_range<E>::max;
static_assert(lhs < (std::numeric_limits<std::int16_t>::max)(), "nameof::enum_range requires max must be less than INT16_MAX.");
constexpr auto rhs = (std::numeric_limits<std::underlying_type_t<E>>::max)();
return mixed_sign_less(lhs, rhs) ? lhs : rhs;
}
template <typename E> template <typename E>
inline constexpr int reflected_max_v = mixed_sign_min_as_int(enum_range<E>::max, (std::numeric_limits<std::underlying_type_t<E>>::max)()); inline constexpr int reflected_min_v = reflected_min<E>();
template <typename E> template <typename E>
constexpr std::size_t reflected_size() { inline constexpr int reflected_max_v = reflected_max<E>();
template <typename E>
constexpr std::size_t reflected_size() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::reflected_size requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::reflected_size requires enum type.");
static_assert(reflected_min_v<E> > (std::numeric_limits<std::int16_t>::min)(), "nameof::enum_range requires min must be greater than INT16_MIN.");
static_assert(reflected_max_v<E> < (std::numeric_limits<std::int16_t>::max)(), "nameof::enum_range requires max must be less than INT16_MAX.");
static_assert(reflected_max_v<E> > reflected_min_v<E>, "nameof::enum_range requires max > min."); static_assert(reflected_max_v<E> > reflected_min_v<E>, "nameof::enum_range requires max > min.");
constexpr auto size = reflected_max_v<E> - reflected_min_v<E> + 1; constexpr auto size = reflected_max_v<E> - reflected_min_v<E> + 1;
static_assert(size > 0, "nameof::enum_range requires valid size."); static_assert(size > 0, "nameof::enum_range requires valid size.");
static_assert(size < (std::numeric_limits<std::int16_t>::max)(), "nameof::enum_range requires valid size."); static_assert(size < (std::numeric_limits<std::uint16_t>::max)(), "nameof::enum_range requires valid size.");
return static_cast<std::size_t>(size); return static_cast<std::size_t>(size);
} }
@ -417,12 +423,12 @@ template <typename E, int... I>
constexpr auto values(std::integer_sequence<int, I...>) noexcept { constexpr auto values(std::integer_sequence<int, I...>) noexcept {
static_assert(is_enum_v<E>, "nameof::detail::values requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::values requires enum type.");
constexpr std::array<bool, sizeof...(I)> valid{{(n<E, static_cast<E>(I + reflected_min_v<E>)>().size() != 0)...}}; constexpr std::array<bool, sizeof...(I)> valid{{(n<E, static_cast<E>(I + reflected_min_v<E>)>().size() != 0)...}};
constexpr std::size_t count = ((valid[I] ? 1 : 0) + ...); constexpr int count = ((valid[I] ? 1 : 0) + ...);
std::array<E, count> values{}; std::array<E, count> values{};
for (std::size_t i = 0, v = 0; v < count; ++i) { for (int i = 0, v = 0; v < count; ++i) {
if (valid[i]) { if (valid[i]) {
values[v++] = static_cast<E>(static_cast<int>(i) + reflected_min_v<E>); values[v++] = static_cast<E>(i + reflected_min_v<E>);
} }
} }
@ -446,7 +452,7 @@ constexpr std::size_t range_size() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::range_size requires enum type."); static_assert(is_enum_v<E>, "nameof::detail::range_size requires enum type.");
constexpr auto size = max_v<E> - min_v<E> + 1; constexpr auto size = max_v<E> - min_v<E> + 1;
static_assert(size > 0, "nameof::enum_range requires valid size."); static_assert(size > 0, "nameof::enum_range requires valid size.");
static_assert(size < (std::numeric_limits<std::int16_t>::max)(), "nameof::enum_range requires valid size."); static_assert(size < (std::numeric_limits<std::uint16_t>::max)(), "nameof::enum_range requires valid size.");
return static_cast<std::size_t>(size); return static_cast<std::size_t>(size);
} }
@ -499,9 +505,6 @@ constexpr auto strings() noexcept {
template <typename E> template <typename E>
class enum_traits { class enum_traits {
static_assert(is_enum_v<E>, "nameof::enum_traits requires enum type."); static_assert(is_enum_v<E>, "nameof::enum_traits requires enum type.");
static_assert(enum_range<E>::min > (std::numeric_limits<std::int16_t>::min)(), "nameof::enum_range requires min must be greater than INT16_MIN.");
static_assert(enum_range<E>::max < (std::numeric_limits<std::int16_t>::max)(), "nameof::enum_range requires max must be less than INT16_MAX.");
static_assert(enum_range<E>::max > enum_range<E>::min, "nameof::enum_range requires max > min.");
static_assert(count_v<E> > 0, "nameof::enum_range requires enum implementation or valid max and min."); static_assert(count_v<E> > 0, "nameof::enum_range requires enum implementation or valid max and min.");
using U = std::underlying_type_t<E>; using U = std::underlying_type_t<E>;
inline static constexpr auto strings_ = strings<E>(); inline static constexpr auto strings_ = strings<E>();