Skip to content

Commit 9aafcd2

Browse files
committed
clean-up
1 parent 70f1f74 commit 9aafcd2

6 files changed

Lines changed: 92 additions & 24 deletions

File tree

.github/workflows/macos.yml

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,28 @@ jobs:
1212
os:
1313
- macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#xcode
1414
- macos-26 # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-Readme.md#xcode
15-
compiler: [Apple Clang, GCC 16]
15+
compiler: [Apple Clang, GCC]
1616
build_type: [Release, Debug]
1717

1818
name: "${{ matrix.os }} / ${{ matrix.compiler }} / ${{ matrix.build_type }}"
1919
runs-on: ${{ matrix.os }}
20-
env:
21-
CC: ${{ matrix.compiler == 'GCC 16' && 'gcc-16' || 'clang' }}
22-
CXX: ${{ matrix.compiler == 'GCC 16' && 'g++-16' || 'clang++' }}
2320

2421
steps:
2522
- uses: actions/checkout@v7
2623

27-
- name: Install GCC 16
28-
if: ${{ matrix.compiler == 'GCC 16' }}
29-
env:
30-
CC: clang
31-
CXX: clang++
24+
- name: Configure compiler
3225
run: |
33-
brew install gcc@16
34-
echo "$(brew --prefix gcc@16)/bin" >> "${GITHUB_PATH}"
26+
if [[ "${{ matrix.compiler }}" == "GCC" ]]; then
27+
brew install gcc
28+
gcc_bin="$(brew --prefix gcc)/bin"
29+
gcc_version="$(brew list --versions gcc | awk '{print $2}')"
30+
gcc_major="${gcc_version%%.*}"
31+
echo "CC=${gcc_bin}/gcc-${gcc_major}" >> "${GITHUB_ENV}"
32+
echo "CXX=${gcc_bin}/g++-${gcc_major}" >> "${GITHUB_ENV}"
33+
else
34+
echo "CC=clang" >> "${GITHUB_ENV}"
35+
echo "CXX=clang++" >> "${GITHUB_ENV}"
36+
fi
3537
3638
- name: Configure
3739
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}

.github/workflows/windows.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,9 @@ jobs:
2626
- name: Build
2727
run: cmake --build build --parallel --config ${{ matrix.build_type }}
2828

29+
- name: Build C++/CLI smoke test
30+
if: ${{ matrix.config.os == 'windows-2022' && matrix.platform == 'x64' && matrix.build_type == 'Release' }}
31+
run: cmake --build build --target test_clr --config ${{ matrix.build_type }}
32+
2933
- name: Test
3034
run: ctest --test-dir build --output-on-failure --no-tests=error -C ${{ matrix.build_type }}

include/magic_enum/magic_enum.hpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -622,11 +622,21 @@ constexpr auto MAGIC_ENUM_CALLING_CONVENTION n() noexcept {
622622
// CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
623623
str_view name;
624624
name.str_ = __FUNCSIG__;
625-
name.size_ = sizeof(__FUNCSIG__) - 17;
626-
std::size_t p = 0;
625+
name.size_ = sizeof(__FUNCSIG__) - 1;
626+
while (name.size_ > 0 && name.str_[name.size_ - 1] != '>') {
627+
--name.size_;
628+
}
629+
if (name.size_ > 0) {
630+
--name.size_;
631+
}
632+
std::size_t p = 0, depth = 0;
627633
for (std::size_t i = name.size_; i > 0; --i) {
628-
if (name.str_[i] == ',' || name.str_[i] == ':') {
629-
p = i + 1;
634+
if (name.str_[i - 1] == '>') {
635+
++depth;
636+
} else if (name.str_[i - 1] == '<' && depth > 0) {
637+
--depth;
638+
} else if (name.str_[i - 1] == ',' && depth == 0) {
639+
p = i;
630640
break;
631641
}
632642
}
@@ -636,6 +646,14 @@ constexpr auto MAGIC_ENUM_CALLING_CONVENTION n() noexcept {
636646
}
637647
if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
638648
name = str_view{};
649+
} else {
650+
for (std::size_t i = name.size_; i > 0; --i) {
651+
if (name.str_[i - 1] == ':') {
652+
name.size_ -= i;
653+
name.str_ += i;
654+
break;
655+
}
656+
}
639657
}
640658
return name;
641659
# endif
@@ -1059,7 +1077,7 @@ inline constexpr Hash hash_v{};
10591077

10601078
template <auto* GlobValues, typename Hash>
10611079
constexpr auto calculate_cases(std::size_t Page) noexcept {
1062-
constexpr std::array values = *GlobValues;
1080+
constexpr auto values = *GlobValues;
10631081
constexpr std::size_t size = values.size();
10641082

10651083
using switch_t = std::invoke_result_t<Hash, typename decltype(values)::value_type>;
@@ -1174,9 +1192,9 @@ constexpr decltype(auto) constexpr_switch(
11741192
using result_t = std::invoke_result_t<ResultGetterType>;
11751193
using hash_t = std::conditional_t<has_unique_hashes<GlobValues, Hash>(), Hash, typename Hash::secondary_hash>;
11761194
static_assert(has_unique_hashes<GlobValues, hash_t>(), "magic_enum::detail::constexpr_switch duplicated hash found, please report it: https://github.com/Neargye/magic_enum/issues.");
1177-
constexpr std::array values = *GlobValues;
1195+
constexpr auto values = *GlobValues;
11781196
constexpr std::size_t size = values.size();
1179-
constexpr std::array cases = calculate_cases<GlobValues, hash_t>(Page);
1197+
constexpr auto cases = calculate_cases<GlobValues, hash_t>(Page);
11801198

11811199
switch (hash_v<hash_t>(searched)) {
11821200
MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_CASE)
@@ -1595,6 +1613,7 @@ constexpr E& operator^=(E& lhs, E rhs) noexcept {
15951613

15961614
#undef MAGIC_ENUM_GET_ENUM_NAME_BUILTIN
15971615
#undef MAGIC_ENUM_GET_TYPE_NAME_BUILTIN
1616+
#undef MAGIC_ENUM_CALLING_CONVENTION
15981617
#undef MAGIC_ENUM_VS_2017_WORKAROUND
15991618
#undef MAGIC_ENUM_ARRAY_CONSTEXPR
16001619
#undef MAGIC_ENUM_FOR_EACH_256

include/magic_enum/magic_enum_utility.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ namespace magic_enum {
4242

4343
namespace detail {
4444

45+
template <typename E, enum_subtype S, typename F, std::size_t J>
46+
using enum_for_each_result_t = std::decay_t<std::invoke_result_t<F&, enum_constant<values_v<E, S>[J]>>>;
47+
4548
template <typename E, enum_subtype S, typename F, std::size_t... J>
4649
constexpr auto for_each(F&& f, std::index_sequence<J...>) {
4750
constexpr bool has_void_return = (std::is_void_v<std::invoke_result_t<F&, enum_constant<values_v<E, S>[J]>>> || ...);
@@ -50,9 +53,9 @@ constexpr auto for_each(F&& f, std::index_sequence<J...>) {
5053
if constexpr (has_void_return) {
5154
(f(enum_constant<values_v<E, S>[J]>{}), ...);
5255
} else if constexpr (all_same_return) {
53-
return std::array{f(enum_constant<values_v<E, S>[J]>{})...};
56+
return std::array<enum_for_each_result_t<E, S, F, 0>, sizeof...(J)>{{f(enum_constant<values_v<E, S>[J]>{})...}};
5457
} else {
55-
return std::tuple{f(enum_constant<values_v<E, S>[J]>{})...};
58+
return std::tuple<enum_for_each_result_t<E, S, F, J>...>{f(enum_constant<values_v<E, S>[J]>{})...};
5659
}
5760
}
5861

test/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,27 @@ endfunction()
144144
magic_enum_add_tests(cpp17 c++17)
145145
magic_enum_make_test(test_range.cpp test_range-cpp17 c++17)
146146

147+
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
148+
target_compile_definitions(test-cpp17 PRIVATE MAGIC_ENUM_TEST_VS_2017_WORKAROUND=1)
149+
if(MSVC_VERSION GREATER_EQUAL 1920)
150+
# Exercise the Visual Studio 2017 fallback on current MSVC too.
151+
target_compile_definitions(test-cpp17 PRIVATE MAGIC_ENUM_VS_2017_WORKAROUND=1)
152+
endif()
153+
endif()
154+
155+
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
156+
set(MAGIC_ENUM_TEST_CLR_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/test_clr.obj")
157+
add_custom_command(
158+
OUTPUT "${MAGIC_ENUM_TEST_CLR_OBJECT}"
159+
COMMAND "${CMAKE_CXX_COMPILER}" /nologo /std:c++17 /clr /EHa /W4 /WX /permissive-
160+
"/I${PROJECT_SOURCE_DIR}/include" /c "${PROJECT_SOURCE_DIR}/example/example.cpp"
161+
"/Fo${MAGIC_ENUM_TEST_CLR_OBJECT}"
162+
DEPENDS "${PROJECT_SOURCE_DIR}/example/example.cpp" "${PROJECT_SOURCE_DIR}/include/magic_enum/magic_enum.hpp"
163+
VERBATIM
164+
)
165+
add_custom_target(test_clr DEPENDS "${MAGIC_ENUM_TEST_CLR_OBJECT}")
166+
endif()
167+
147168
foreach(MAGIC_ENUM_TEST_STANDARD IN LISTS MAGIC_ENUM_TEST_STANDARDS)
148169
set(MAGIC_ENUM_HAS_STANDARD_FLAG MAGIC_ENUM_HAS_CPP${MAGIC_ENUM_TEST_STANDARD}_FLAG)
149170
if(NOT ${MAGIC_ENUM_HAS_STANDARD_FLAG})

test/test.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
#include <magic_enum/magic_enum_switch.hpp>
1616
#include <magic_enum/magic_enum_utility.hpp>
1717

18+
#if defined(MAGIC_ENUM_CALLING_CONVENTION) || defined(MAGIC_ENUM_VS_2017_WORKAROUND) || defined(MAGIC_ENUM_ARRAY_CONSTEXPR)
19+
# error Internal macro leaked from magic_enum.hpp.
20+
#endif
21+
1822
#include "test_helpers.hpp"
1923

2024
#include <array>
@@ -35,6 +39,14 @@ constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<Co
3539

3640
enum class Numbers : int { one = 1, two, three, many = 127 };
3741

42+
#if defined(MAGIC_ENUM_TEST_VS_2017_WORKAROUND)
43+
template <typename, typename>
44+
struct templated_scope {
45+
enum class Value { ONE, TWO };
46+
};
47+
using TemplatedValue = templated_scope<int, long>::Value;
48+
#endif
49+
3850
enum Directions { Up = 85, Down = -42, Right = 120, Left = -120 };
3951

4052
enum number : unsigned long {
@@ -522,6 +534,10 @@ TEST_CASE("enum_count") {
522534

523535
constexpr auto s6 = enum_count<MaxUsedAsInvalid>();
524536
REQUIRE(s6 == 2);
537+
538+
#if defined(MAGIC_ENUM_TEST_VS_2017_WORKAROUND)
539+
REQUIRE(enum_count<TemplatedValue>() == 2);
540+
#endif
525541
}
526542

527543
enum lt1 { s1, loooooooooooooooooooong1 };
@@ -628,6 +644,9 @@ TEST_CASE("enum_name") {
628644
REQUIRE(enum_name(static_cast<number>(0)).empty());
629645

630646
REQUIRE(enum_name(MaxUsedAsInvalid::ONE) == "ONE");
647+
#if defined(MAGIC_ENUM_TEST_VS_2017_WORKAROUND)
648+
REQUIRE(enum_name(TemplatedValue::ONE) == "ONE");
649+
#endif
631650

632651
REQUIRE(enum_name(lt1::s1) == "s1");
633652
REQUIRE(enum_name(lt1::loooooooooooooooooooong1) == "loooooooooooooooooooong1");
@@ -1113,7 +1132,7 @@ TEST_CASE("extrema") {
11131132
REQUIRE(magic_enum::detail::reflected_min<Directions, as_common<>>() == MAGIC_ENUM_RANGE_MIN);
11141133
REQUIRE(magic_enum::detail::min_v<Directions, as_common<>> == -120);
11151134

1116-
REQUIRE(magic_enum::customize::enum_range<number>::min == 100);
1135+
REQUIRE(static_cast<int>(magic_enum::customize::enum_range<number>::min) == 100);
11171136
REQUIRE(magic_enum::detail::reflected_min<number, as_common<>>() == 100);
11181137
REQUIRE(magic_enum::detail::min_v<number, as_common<>> == 100);
11191138

@@ -1141,7 +1160,7 @@ TEST_CASE("extrema") {
11411160
REQUIRE(magic_enum::detail::reflected_max<Directions, as_common<>>() == MAGIC_ENUM_RANGE_MAX);
11421161
REQUIRE(magic_enum::detail::max_v<Directions, as_common<>> == 120);
11431162

1144-
REQUIRE(magic_enum::customize::enum_range<number>::max == 300);
1163+
REQUIRE(static_cast<int>(magic_enum::customize::enum_range<number>::max) == 300);
11451164
REQUIRE(magic_enum::detail::reflected_max<number, as_common<>>() == 300);
11461165
REQUIRE(magic_enum::detail::max_v<number, as_common<>> == 300);
11471166

@@ -1275,13 +1294,13 @@ TEST_CASE("enum_for_each") {
12751294
constexpr auto workResults = enum_for_each<Color>([](auto val) {
12761295
return DoWork<val>();
12771296
});
1278-
REQUIRE(workResults == std::array<std::string_view, 3>{"default", "override", "default"});
1297+
REQUIRE(workResults == std::array<std::string_view, 3>{{"default", "override", "default"}});
12791298

12801299
constexpr auto colorSequence = std::make_index_sequence<enum_count<Color>()>{};
12811300
static_assert(detail::all_invocable<Color, detail::subtype_v<Color>, LvalueOnlyForEach>(colorSequence));
12821301
static_assert(!detail::all_invocable<Color, detail::subtype_v<Color>, RvalueOnlyForEach>(colorSequence));
12831302
constexpr auto colorValues = enum_for_each<Color>(LvalueOnlyForEach{});
1284-
REQUIRE(colorValues == std::array<int, 3>{-12, 7, 15});
1303+
REQUIRE(colorValues == std::array<int, 3>{{-12, 7, 15}});
12851304
}
12861305

12871306
SUBCASE("different return type") {

0 commit comments

Comments
 (0)