Skip to content

Commit 3a558e5

Browse files
committed
add the basic support of c++17
1 parent 1e74d95 commit 3a558e5

29 files changed

+2351
-2499
lines changed

CMakeLists.txt

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
1-
cmake_minimum_required(VERSION 3.26)
2-
project(magic)
1+
cmake_minimum_required(VERSION 3.22)
2+
project(magic-cpp)
33

44
set(CMAKE_CXX_STANDARD 20)
5-
# set(CMAKE_CXX_FLAGS "-Werror -Wall -Waddress -Woverflow")
6-
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
76

8-
include_directories(include)
7+
if(NOT MSVC)
8+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
9+
endif()
910

10-
add_executable(main test/main.cpp)
1111

12-
add_executable(struct test/struct.cpp)
12+
include(FetchContent)
13+
FetchContent_Declare(
14+
googletest
15+
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
16+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
17+
)
18+
# For Windows: Prevent overriding the parent project's compiler/linker settings
19+
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
20+
FetchContent_MakeAvailable(googletest)
1321

14-
add_executable(type test/type.cpp)
22+
enable_testing()
23+
24+
include_directories(include)
25+
26+
# 使用通配符一次性添加多个测试文件
27+
file(GLOB TEST_SOURCES "test/*.cpp")
28+
29+
# 创建一个包含所有测试文件的可执行文件
30+
add_executable(all_tests ${TEST_SOURCES})
31+
add_executable(main main.cpp)
32+
33+
target_link_libraries(all_tests GTest::gtest_main)
34+
# 链接Google Test库到测试可执行文件
35+
36+
# 使用Google Test自动发现所有测试并将其添加到测试套件中
37+
include(GoogleTest)
38+
gtest_discover_tests(all_tests)
1539

16-
add_executable(enum test/enum.cpp)

generate.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ def main():
2121
with open(path.join(src, "struct_bind_of_field_access.code"), "w") as f:
2222
f.write(generate_struct_bind_of_field_access(args.fields))
2323

24-
with open(path.join(src, "template_parse.code"), "w") as f:
25-
f.write(generate_template_parse(args.templates))
24+
with open(path.join(src, "template.code"), "w") as f:
25+
f.write(generate_template_traits(args.templates))
2626

2727

2828
if __name__ == "__main__":
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef MAGIC_CPP_CUSTOMIZED_TYPE_NAME_H
2+
#define MAGIC_CPP_CUSTOMIZED_TYPE_NAME_H
3+
#include "type_tree.h"
4+
5+
template <>
6+
struct magic::type_info<std::size_t>
7+
{
8+
constexpr static const char* name = "std::size_t";
9+
};
10+
11+
template <>
12+
struct magic::type_info<std::string>
13+
{
14+
constexpr static const char* name = "std::string";
15+
};
16+
17+
template <>
18+
struct magic::type_info<std::string_view>
19+
{
20+
constexpr static const char* name = "std::string_view";
21+
};
22+
23+
#endif

include/magic/enum.h

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,30 @@
22
#define MAGIC_CPP_ENUM_H
33

44
#include "macro.h"
5-
#include "string_view.h"
5+
6+
#ifdef MAGIC_CPP_20
7+
#include "raw_name.h"
68
#include <array>
7-
#include <iostream>
8-
#include <type_traits>
99

1010
#define ENUM_SEARCH_RANGE 32
1111
namespace magic
1212
{
1313
template <typename T>
1414
struct type_info;
15-
16-
template <auto value>
17-
requires std::is_enum_v<decltype(value)>
18-
constexpr auto name_of()
19-
{
20-
// clang-format off
21-
string_view name = MAGIC_CPP_FUNCTION_NAME;
22-
#if __clang__ || __GNUC__
23-
std::size_t r1 = name.rfind("::");
24-
std::size_t r2 = name.rfind("value = ");
25-
std::size_t last = name.rfind("]");
26-
name = (r1 != string_view::npos && r1 > r2) ? name.substr(r1 + 2, last) : name.substr(r2 + 8 , last);
27-
return name.find(")") != string_view::npos ? "" : name;
28-
#elif _MSC_VER
29-
std::size_t r1 = name.rfind("::");
30-
std::size_t r2 = name.rfind("name_of<");
31-
std::size_t last = name.rfind(">");
32-
name = (r1 != string_view::npos && r1 > r2) ? name.substr(r1 + 2, last) : name.substr(r2 + 8, last);
33-
return name.find(")") != string_view::npos ? "" : name;
34-
#else
35-
static_assert(false, "not supported compiler");
36-
#endif
37-
// clang-format on
38-
}
3915
} // namespace magic
4016

4117
namespace magic::details
4218
{
4319
template <typename T, std::ptrdiff_t N = 0>
4420
consteval std::ptrdiff_t search_possible_enum_start()
4521
{
46-
if constexpr (name_of<static_cast<T>(N)>() != "")
22+
if constexpr (raw_name_of_enum<static_cast<T>(N)>() != "")
4723
{
4824
return N;
4925
}
5026
else if constexpr (std::is_signed_v<std::underlying_type_t<T>>)
5127
{
52-
if constexpr (name_of<static_cast<T>(-N)>() != "")
28+
if constexpr (raw_name_of_enum<static_cast<T>(-N)>() != "")
5329
{
5430
return -N;
5531
}
@@ -68,7 +44,7 @@ namespace magic::details
6844
consteval std::ptrdiff_t search_possible_continuous_enum_max()
6945
{
7046
constexpr auto is_end = []<std::size_t... Is>(std::index_sequence<Is...>)
71-
{ return (name_of<static_cast<T>(N + Is)>().empty() && ...); }(std::make_index_sequence<8>{});
47+
{ return (raw_name_of_enum<static_cast<T>(N + Is)>().empty() && ...); }(std::make_index_sequence<8>{});
7248

7349
if constexpr (is_end)
7450
{
@@ -130,9 +106,9 @@ namespace magic::details
130106
consteval auto search_possible_bit_field_enum_length()
131107
{
132108
constexpr auto max = sizeof(T) * 8;
133-
std::size_t result = name_of<static_cast<T>(0)>() != "";
109+
std::size_t result = raw_name_of_enum<static_cast<T>(0)>() != "";
134110
[&]<std::size_t... Is>(std::index_sequence<Is...>)
135-
{ ((name_of<static_cast<T>(1 << Is)>() != "" ? result++ : result), ...); }(std::make_index_sequence<max>{});
111+
{ ((raw_name_of_enum<static_cast<T>(1 << Is)>() != "" ? result++ : result), ...); }(std::make_index_sequence<max>{});
136112
return result;
137113
}
138114

@@ -163,23 +139,23 @@ namespace magic::details
163139
constexpr auto start = enum_start<T>();
164140
constexpr auto max = enum_max<T>();
165141
constexpr auto length = max - start + 1;
166-
std::array<string_view, length> names{};
167-
split_initialize<T, length>([&]<std::size_t I>() { names[I] = name_of<static_cast<T>(start + I)>(); });
142+
std::array<std::string_view, length> names{};
143+
split_initialize<T, length>([&]<std::size_t I>() { names[I] = raw_name_of_enum<static_cast<T>(start + I)>(); });
168144
return names;
169145
}
170146
else
171147
{
172148
constexpr auto length = search_possible_bit_field_enum_length<T>();
173-
std::array<string_view, length> names{};
174-
constexpr auto has_zero = name_of<static_cast<T>(0)>() != "";
149+
std::array<std::string_view, length> names{};
150+
constexpr auto has_zero = raw_name_of_enum<static_cast<T>(0)>() != "";
175151
if constexpr (has_zero)
176152
{
177-
names[0] = name_of<static_cast<T>(0)>();
178-
split_initialize<T, length - 1>([&]<std::size_t I>() { names[I + 1] = name_of<static_cast<T>(1 << I)>(); });
153+
names[0] = raw_name_of_enum<static_cast<T>(0)>();
154+
split_initialize<T, length - 1>([&]<std::size_t I>() { names[I + 1] = raw_name_of_enum<static_cast<T>(1 << I)>(); });
179155
}
180156
else
181157
{
182-
split_initialize<T, length>([&]<std::size_t I>() { names[I] = name_of<static_cast<T>(1 << I)>(); });
158+
split_initialize<T, length>([&]<std::size_t I>() { names[I] = raw_name_of_enum<static_cast<T>(1 << I)>(); });
183159
}
184160
return names;
185161
}
@@ -196,13 +172,13 @@ namespace magic::details
196172
requires std::is_enum_v<T>
197173
struct Field
198174
{
199-
constexpr static string_view name() { return name_of<static_cast<T>(N)>(); }
175+
constexpr static std::string_view name() { return raw_name_of_enum<static_cast<T>(N)>(); }
200176

201177
using type = T;
202178

203179
constexpr static std::ptrdiff_t value() { return N; }
204180

205-
constexpr static string_view type_name() { return name_of<T>(); }
181+
constexpr static std::string_view type_name() { return raw_name_of_enum<T>(); }
206182
};
207183

208184
template <typename T>
@@ -220,7 +196,7 @@ namespace magic::details
220196
else
221197
{
222198
constexpr auto length = search_possible_bit_field_enum_length<T>();
223-
constexpr auto has_zero = name_of<static_cast<T>(0)>() != "";
199+
constexpr auto has_zero = raw_name_of_enum<static_cast<T>(0)>() != "";
224200
if constexpr (has_zero)
225201
{
226202
f(Field<T, 0>{});
@@ -248,11 +224,11 @@ namespace magic
248224

249225
template <typename T>
250226
requires std::is_enum_v<T>
251-
constexpr auto& name_of(T value)
227+
constexpr auto& raw_name_of_enum(T value)
252228
{
253229
constexpr auto start = enum_start<T>();
254230
return details::enum_names_storage<T>::names[static_cast<std::size_t>(value + start)];
255231
}
256232
} // namespace magic
257-
233+
#endif
258234
#endif // MAGIC_CPP_ENUM_H

0 commit comments

Comments
 (0)