diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 13d77a7..32f223d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -47,7 +47,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: SARIF file path: results.sarif @@ -55,6 +55,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 with: sarif_file: results.sarif diff --git a/include/magic_enum/magic_enum.hpp b/include/magic_enum/magic_enum.hpp index 158207e..7491fae 100644 --- a/include/magic_enum/magic_enum.hpp +++ b/include/magic_enum/magic_enum.hpp @@ -621,26 +621,37 @@ constexpr auto enum_name() noexcept { template inline constexpr auto enum_name_v = enum_name(); +// CWG1766: Values outside the range of the values of an enumeration +// https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307 +#if defined(__clang__) && __clang_major__ >= 16 +template +inline constexpr bool is_enum_constexpr_static_cast_valid = false; +template +inline constexpr bool is_enum_constexpr_static_cast_valid(V)>>> = true; +#else +template +inline constexpr bool is_enum_constexpr_static_cast_valid = true; +#endif + template constexpr bool is_valid() noexcept { -#if defined(__clang__) && __clang_major__ >= 16 - // https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307 - constexpr E v = __builtin_bit_cast(E, V); -#else - constexpr E v = static_cast(V); -#endif - [[maybe_unused]] constexpr auto custom = customize::enum_name(v); - static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); - if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { - constexpr auto name = custom.second; - static_assert(!name.empty(), "magic_enum::customize requires not empty string."); - return name.size() != 0; - } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { + if constexpr (is_enum_constexpr_static_cast_valid) { + constexpr E v = static_cast(V); + [[maybe_unused]] constexpr auto custom = customize::enum_name(v); + static_assert(std::is_same_v, customize::customize_t>, "magic_enum::customize requires customize_t type."); + if constexpr (custom.first == customize::detail::customize_tag::custom_tag) { + constexpr auto name = custom.second; + static_assert(!name.empty(), "magic_enum::customize requires not empty string."); + return name.size() != 0; + } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) { #if defined(MAGIC_ENUM_VS_2017_WORKAROUND) - return n().size_ != 0; + return n().size_ != 0; #else - return n().size_ != 0; + return n().size_ != 0; #endif + } else { + return false; + } } else { return false; } diff --git a/include/magic_enum/magic_enum_containers.hpp b/include/magic_enum/magic_enum_containers.hpp index f817306..9a0208a 100644 --- a/include/magic_enum/magic_enum_containers.hpp +++ b/include/magic_enum/magic_enum_containers.hpp @@ -52,10 +52,10 @@ namespace magic_enum::containers { namespace detail { template -static constexpr bool is_transparent_v{}; +inline constexpr bool is_transparent_v{}; template -static constexpr bool is_transparent_v>{true}; +inline constexpr bool is_transparent_v>{true}; template , typename T1, typename T2> constexpr bool equal(T1&& t1, T2&& t2, Eq&& eq = {}) { diff --git a/include/magic_enum/magic_enum_format.hpp b/include/magic_enum/magic_enum_format.hpp index 4997589..eadceec 100644 --- a/include/magic_enum/magic_enum_format.hpp +++ b/include/magic_enum/magic_enum_format.hpp @@ -35,44 +35,35 @@ #include "magic_enum.hpp" #include "magic_enum_flags.hpp" -#if !defined(MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT) -# define MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT 1 -# define MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT_AUTO_DEFINE -#endif +namespace magic_enum::detail { -namespace magic_enum::customize { - // customize enum to enable/disable automatic std::format - template - constexpr bool enum_format_enabled() noexcept { - return MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT; +template >, int> = 0> +std::string format_as(E e) { + using D = std::decay_t; + static_assert(std::is_same_v, "magic_enum::formatter requires string_view::value_type type same as char."); + if constexpr (magic_enum::detail::supported::value) { + if constexpr (magic_enum::detail::subtype_v == magic_enum::detail::enum_subtype::flags) { + if (const auto name = magic_enum::enum_flags_name(e); !name.empty()) { + return {name.data(), name.size()}; + } + } else { + if (const auto name = magic_enum::enum_name(e); !name.empty()) { + return {name.data(), name.size()}; + } + } } -} // magic_enum::customize + return std::to_string(magic_enum::enum_integer(e)); +} + +} // namespace magic_enum::format #if defined(__cpp_lib_format) -#ifndef MAGIC_ENUM_USE_STD_MODULE -#include -#endif - template -struct std::formatter> && magic_enum::customize::enum_format_enabled(), char>> : std::formatter { +struct std::formatter>, char>> : std::formatter { template auto format(E e, FormatContext& ctx) const { - static_assert(std::is_same_v, "formatter requires string_view::value_type type same as char."); - using D = std::decay_t; - - if constexpr (magic_enum::detail::supported::value) { - if constexpr (magic_enum::detail::subtype_v == magic_enum::detail::enum_subtype::flags) { - if (const auto name = magic_enum::enum_flags_name(e); !name.empty()) { - return formatter::format(std::string_view{name.data(), name.size()}, ctx); - } - } else { - if (const auto name = magic_enum::enum_name(e); !name.empty()) { - return formatter::format(std::string_view{name.data(), name.size()}, ctx); - } - } - } - return formatter::format(std::to_string(magic_enum::enum_integer(e)), ctx); + return std::formatter::format(magic_enum::detail::format_as(e), ctx); } }; @@ -80,35 +71,14 @@ struct std::formatter> && mag #if defined(FMT_VERSION) -#include - template -struct fmt::formatter> && magic_enum::customize::enum_format_enabled(), char>> : fmt::formatter { +struct fmt::formatter>, char>> : fmt::formatter { template auto format(E e, FormatContext& ctx) const { - static_assert(std::is_same_v, "formatter requires string_view::value_type type same as char."); - using D = std::decay_t; - - if constexpr (magic_enum::detail::supported::value) { - if constexpr (magic_enum::detail::subtype_v == magic_enum::detail::enum_subtype::flags) { - if (const auto name = magic_enum::enum_flags_name(e); !name.empty()) { - return formatter::format(std::string_view{name.data(), name.size()}, ctx); - } - } else { - if (const auto name = magic_enum::enum_name(e); !name.empty()) { - return formatter::format(std::string_view{name.data(), name.size()}, ctx); - } - } - } - return formatter::format(std::to_string(magic_enum::enum_integer(e)), ctx); + return fmt::formatter::format(magic_enum::detail::format_as(e), ctx); } }; #endif -#if defined(MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT_AUTO_DEFINE) -# undef MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT -# undef MAGIC_ENUM_DEFAULT_ENABLE_ENUM_FORMAT_AUTO_DEFINE -#endif - #endif // NEARGYE_MAGIC_ENUM_FORMAT_HPP diff --git a/test/test.cpp b/test/test.cpp index ef0459d..9d26eab 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1176,6 +1176,7 @@ TEST_CASE("multdimensional-switch-case") { #if defined(__cpp_lib_format) +#include #include TEST_CASE("format-base") {