Skip to content

Commit

Permalink
improve nameof_enum
Browse files Browse the repository at this point in the history
  • Loading branch information
Neargye committed Oct 19, 2019
1 parent 240b3f4 commit 64499c3
Showing 1 changed file with 24 additions and 21 deletions.
45 changes: 24 additions & 21 deletions include/nameof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// |_| \_|\__,_|_| |_| |_|\___|\___/|_| \_____|
// https://github.com/Neargye/nameof
// vesion 0.9.1
// vesion 0.9.2
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
Expand Down Expand Up @@ -33,6 +34,7 @@
#define NEARGYE_NAMEOF_HPP

#include <array>
#include <cstdint>
#include <cstddef>
#include <iosfwd>
#include <iterator>
Expand Down Expand Up @@ -380,35 +382,39 @@ constexpr bool mixed_sign_less(L lhs, R rhs) noexcept {
}
}

template <typename L, typename R>
constexpr int mixed_sign_min_as_int(L lhs, R rhs) noexcept {
static_assert(std::is_integral_v<L> && std::is_integral_v<R>, "nameof::detail::mixed_sign_min_as_int requires integral type.");
template <typename E>
constexpr int reflected_min() noexcept {
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.");
template <typename E>
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) ? static_cast<int>(rhs) : static_cast<int>(lhs);
return mixed_sign_less(lhs, rhs) ? lhs : rhs;
}

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)());
inline constexpr int reflected_min_v = reflected_min<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_max_v = reflected_max<E>();

template <typename E>
constexpr std::size_t reflected_size() {
constexpr std::size_t reflected_size() noexcept {
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.");
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 < (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);
}
Expand All @@ -417,12 +423,12 @@ template <typename E, int... I>
constexpr auto values(std::integer_sequence<int, I...>) noexcept {
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::size_t count = ((valid[I] ? 1 : 0) + ...);
constexpr int count = ((valid[I] ? 1 : 0) + ...);

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]) {
values[v++] = static_cast<E>(static_cast<int>(i) + reflected_min_v<E>);
values[v++] = static_cast<E>(i + reflected_min_v<E>);
}
}

Expand All @@ -446,7 +452,7 @@ constexpr std::size_t range_size() noexcept {
static_assert(is_enum_v<E>, "nameof::detail::range_size requires enum type.");
constexpr auto size = max_v<E> - min_v<E> + 1;
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);
}
Expand Down Expand Up @@ -499,9 +505,6 @@ constexpr auto strings() noexcept {
template <typename E>
class enum_traits {
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.");
using U = std::underlying_type_t<E>;
inline static constexpr auto strings_ = strings<E>();
Expand Down

0 comments on commit 64499c3

Please sign in to comment.