1
0
Fork 0
mirror of https://github.com/Neargye/magic_enum.git synced 2026-01-09 23:34:23 +00:00

remove throw from enum_fuse

This commit is contained in:
neargye 2022-02-16 19:01:14 +02:00
parent 9bfb90760a
commit 756b139368
2 changed files with 12 additions and 14 deletions

View file

@ -912,8 +912,7 @@ namespace fusion_detail {
template <typename E> template <typename E>
constexpr std::size_t fuse_one_enum(std::size_t hash, E value) noexcept { constexpr std::size_t fuse_one_enum(std::size_t hash, E value) noexcept {
// Add 1 to prevent matching 2D fusions with 3D fusions etc. // Add 1 to prevent matching 2D fusions with 3D fusions etc.
std::size_t index = enum_index(value).has_value() ? (enum_index(value).value() + 1) : 0; return (hash << detail::log2(enum_count<E>() + 1)) | (enum_index(value).value() + 1);
return (hash << detail::log2(enum_count<E>() + 1)) | index;
} }
template <typename E> template <typename E>
@ -930,16 +929,15 @@ constexpr std::size_t fuse_enum(E head, Es... tail) noexcept {
// Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements. // Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements.
template <typename... Es> template <typename... Es>
[[nodiscard]] constexpr auto enum_fuse(Es... values) -> std::enable_if_t<(std::is_enum_v<std::decay_t<Es>> && ...), std::size_t>{ [[nodiscard]] constexpr auto enum_fuse(Es... values) -> std::enable_if_t<(std::is_enum_v<std::decay_t<Es>> && ...), std::optional<std::size_t>> {
static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 enums"); static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 enums");
static_assert((detail::log2(enum_count<Es>() + 1) + ...) <= (sizeof(std::size_t) * 8), "magic_enum::enum_fuse does not work for large enums"); static_assert((detail::log2(enum_count<Es>() + 1) + ...) <= (sizeof(std::size_t) * 8), "magic_enum::enum_fuse does not work for large enums");
const bool has_values = (enum_index(values).has_value() && ...); const bool has_values = (enum_index(values).has_value() && ...);
#if defined(__cpp_lib_is_constant_evaluated) && (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS)) if (has_values) {
if (std::is_constant_evaluated() && !has_values) { return fusion_detail::fuse_enum(values...);
throw std::logic_error{"magic_enum::enum_fuse accepts only in-range enum values"}; } else {
return assert(has_values), std::nullopt;
} }
#endif
return assert(has_values), (has_values ? fusion_detail::fuse_enum(values...) : 0);
} }
namespace ostream_operators { namespace ostream_operators {

View file

@ -1015,10 +1015,10 @@ TEST_CASE("constexpr_for") {
} }
static int switch_case_2d(Color color, Directions direction) { static int switch_case_2d(Color color, Directions direction) {
switch (magic_enum::enum_fuse(color, direction)) { switch (magic_enum::enum_fuse(color, direction).value()) {
case magic_enum::enum_fuse(Color::RED, Directions::Up): case magic_enum::enum_fuse(Color::RED, Directions::Up).value():
return 1; return 1;
case magic_enum::enum_fuse(Color::BLUE, Directions::Down): case magic_enum::enum_fuse(Color::BLUE, Directions::Down).value():
return 2; return 2;
default: default:
return 0; return 0;
@ -1028,11 +1028,11 @@ static int switch_case_2d(Color color, Directions direction) {
enum class Index { zero = 0, one = 1, two = 2 }; enum class Index { zero = 0, one = 1, two = 2 };
static int switch_case_3d(Color color, Directions direction, Index index) { static int switch_case_3d(Color color, Directions direction, Index index) {
switch (magic_enum::enum_fuse(color, direction, index)) { switch (magic_enum::enum_fuse(color, direction, index).value()) {
case magic_enum::enum_fuse(Color::RED, Directions::Up, Index::zero): case magic_enum::enum_fuse(Color::RED, Directions::Up, Index::zero).value():
return 1; return 1;
// model accidental removal of last index, must not match anything // model accidental removal of last index, must not match anything
case magic_enum::enum_fuse(Color::BLUE, Directions::Up): case magic_enum::enum_fuse(Color::BLUE, Directions::Up).value():
return 2; return 2;
default: default:
return 0; return 0;