From 756b139368aba753c9024ccf87f13478ca6bef79 Mon Sep 17 00:00:00 2001 From: neargye Date: Wed, 16 Feb 2022 19:01:14 +0200 Subject: [PATCH] remove throw from enum_fuse --- include/magic_enum.hpp | 14 ++++++-------- test/test.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index f23891f..2a484b4 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -912,8 +912,7 @@ namespace fusion_detail { template 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. - std::size_t index = enum_index(value).has_value() ? (enum_index(value).value() + 1) : 0; - return (hash << detail::log2(enum_count() + 1)) | index; + return (hash << detail::log2(enum_count() + 1)) | (enum_index(value).value() + 1); } template @@ -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. template -[[nodiscard]] constexpr auto enum_fuse(Es... values) -> std::enable_if_t<(std::is_enum_v> && ...), std::size_t>{ +[[nodiscard]] constexpr auto enum_fuse(Es... values) -> std::enable_if_t<(std::is_enum_v> && ...), std::optional> { static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 enums"); static_assert((detail::log2(enum_count() + 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() && ...); -#if defined(__cpp_lib_is_constant_evaluated) && (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS)) - if (std::is_constant_evaluated() && !has_values) { - throw std::logic_error{"magic_enum::enum_fuse accepts only in-range enum values"}; + if (has_values) { + return fusion_detail::fuse_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 { diff --git a/test/test.cpp b/test/test.cpp index 348ff30..2486df8 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1015,10 +1015,10 @@ TEST_CASE("constexpr_for") { } static int switch_case_2d(Color color, Directions direction) { - switch (magic_enum::enum_fuse(color, direction)) { - case magic_enum::enum_fuse(Color::RED, Directions::Up): + switch (magic_enum::enum_fuse(color, direction).value()) { + case magic_enum::enum_fuse(Color::RED, Directions::Up).value(): return 1; - case magic_enum::enum_fuse(Color::BLUE, Directions::Down): + case magic_enum::enum_fuse(Color::BLUE, Directions::Down).value(): return 2; default: return 0; @@ -1028,11 +1028,11 @@ static int switch_case_2d(Color color, Directions direction) { enum class Index { zero = 0, one = 1, two = 2 }; static int switch_case_3d(Color color, Directions direction, Index index) { - switch (magic_enum::enum_fuse(color, direction, index)) { - case magic_enum::enum_fuse(Color::RED, Directions::Up, Index::zero): + switch (magic_enum::enum_fuse(color, direction, index).value()) { + case magic_enum::enum_fuse(Color::RED, Directions::Up, Index::zero).value(): return 1; // 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; default: return 0;