Skip to content

Commit 1e74d95

Browse files
committed
add some docs
1 parent 5fac89e commit 1e74d95

File tree

6 files changed

+134
-71
lines changed

6 files changed

+134
-71
lines changed

README.md

Lines changed: 122 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,77 @@
1-
# Magic Cpp
1+
![cover](docs/assets/cover.png)
22

3-
Header-only C++20 library provides static reflection for type, aggregate class and enum, no external dependencies, no registration, no macro, no code generation, just magic.
3+
magic-cpp is C++20 header-only library provides static reflection for type, struct and enum, no external dependencies, no registration, no macro, no code generation.
44

5-
## Documentation
5+
# Documentation
66
* [Reference](doc/reference.md)
77
* [Limitations](doc/limitations.md)
88
* [Integration](#Integration)
99

10-
## [Examples](example/)
11-
### type
10+
# [Examples](example/)
11+
## type
1212

13-
*just include `magic/type.h` to use these features*
13+
**just include `magic/type.h` to use the features below**
1414

15-
* full name of type
15+
- *retrieve the full name of a type*:
1616
```cpp
1717
struct Point{};
18+
1819
constexpr auto name = magic::full_name_of<Point>();
19-
static_assert(name == "Point");
20+
// name => "Point"
2021

2122
constexpr auto name2 = magic::full_name_of<std::vector<int>>();
22-
static_assert(name2 == "std::vector<int, std::allocator<int>>");
23+
// name2 => "std::vector<int>"
2324

2425
constexpr auto name3 = magic::full_name_of<std::size_t>();
25-
static_assert(name3 == "unsigned long long int");
26+
// name3 => "unsigned long long int"
2627
```
27-
* display name of type
28+
- *retrieve the display name of a type*
2829
```cpp
29-
// specialization for type to get better readable
30-
namespace magic
30+
// specialize for type to customize the display name
31+
template<>
32+
struct magic::type_info<std::size_t>
3133
{
32-
template<>
33-
struct type_info<std::size_t>
34-
{
35-
constexpr static auto value = "std::size_t";
36-
};
34+
constexpr static auto value = "std::size_t";
35+
};
3736

38-
template<>
39-
struct type_info<std::string>
40-
{
41-
constexpr static auto value = "std::string";
42-
};
43-
}
37+
template<>
38+
struct magic::type_info<std::string>
39+
{
40+
constexpr static auto value = "std::string";
41+
};
4442

4543
// use name_of to get the display name
4644
constexpr auto name = magic::name_of<std::size_t>();
47-
static_assert(name == "std::size_t");
45+
// name => "std::size_t"
4846

4947
constexpr auto name2 = magic::name_of<std::string>();
50-
static_assert(name2 == "std::string");
48+
// name => "std::string"
5149
```
5250

53-
* visualize type
51+
- *visualize type*
5452
```cpp
5553
// for some complex type, it is hard to understand for human
56-
// we can visualize it to a more readable form
54+
// we can visualize it as a tree to make it more readable
5755

5856
using T = int (*(*(*)(int*))[4])(int*); // hard to understand
5957
std::cout << magic::full_tree_of<T>() << std::endl;
6058
```
61-
Output:
59+
*Output:*
6260

63-
![ptr](docs/ptr.png)
61+
![ptr](docs/assets/sample_ptr.png)
6462

63+
----------------
6564
```cpp
6665
using T = std::map<int, std::string>;
6766
std::cout << magic::full_tree_of<T>() << std::endl;
6867
```
69-
Output:
70-
71-
![map](docs/map.png)
68+
*Output*:
69+
![map](docs/assets/sample_map.png)
7270

7371
you can also use `tree_of` to get a more compact form, more details see [type](docs/type.md).
7472

75-
### [aggregate class](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Definitions)
76-
*just include `magic/struct.h` to use these features*
73+
## [aggregate class](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Definitions)
74+
**just include `magic/struct.h` to use these features**
7775

7876
```cpp
7977
struct Complex
@@ -83,56 +81,119 @@ struct Complex
8381
}; // Complex is an aggregate class
8482
```
8583

86-
- Retrieve field count of an aggregate class
84+
- *retrieve field count of an aggregate class*
8785
```cpp
88-
static_assert(magic::field_count_of<Complex>() == 2);
86+
constexpr auto count = magic::field_count_of<Complex>();
87+
// count => 2
8988
```
90-
- Retrieve the field types for an aggregate class
89+
- *retrieve the field types for an aggregate class*
9190
```cpp
92-
using T = magic::field_types_of<Complex>;
93-
static_assert(std::same_as<T, std::tuple<std::string, std::vector<int>>>);
91+
using Types = magic::field_types_of<Complex>;
92+
// Types => std::tuple<std::string, std::vector<int>>
9493
```
95-
- Retrieve the field type at a given index for an aggregate class
94+
- *retrieve the field type at a given index for an aggregate class*
9695
```cpp
97-
static_assert(std::same_as<magic::field_type_of<Complex, 0>, std::string>);
98-
static_assert(std::same_as<magic::field_type_of<Complex, 1>, std::vector<int>>);
96+
using First = magic::field_type_of<Complex, 0>;
97+
// First => std::string
98+
99+
using Second = magic::field_type_of<Complex, 1>;
100+
// Second => std::vector<int>
99101
```
100-
- Retrieve the field names for an aggregate class
102+
- *retrieve the field names for an aggregate class*
101103
```cpp
102104
constexpr auto names = magic::field_names_of<Complex>();
103-
static_assert(names == std::array<std::string_view, 2>{"name", "vec"});
105+
// names => std::array{"name", "vec"}
104106
```
105107

106-
- Retrieve the field name at a given index for an aggregate class
108+
- *retrieve the field name at a given index for an aggregate class*
107109
```cpp
108-
static_assert(magic::field_name_of<Complex>(0) == "name");
109-
static_assert(magic::field_name_of<Complex>(1) == "vec");
110+
constexpr auto name1 = magic::field_name_of<Complex>(0);
111+
// name1 => "name"
112+
113+
constexpr auto name2 = magic::field_name_of<Complex>(1);
114+
// name2 => "vec"
110115
```
111116

112-
- Retrieve the field reference at a given index for an aggregate class
117+
- *retrieve the field reference at a given index for an aggregate class*
113118
```cpp
114119
Complex c{"hello", {1, 2, 3}};
115-
std::cout << magic::field_of<0>(c) << std::endl;
116-
// output: hello
117120

118-
std::cout << magic::field_of<1>(c)[1] << std::endl;
119-
// output: 2
121+
auto& value = magic::field_of<0>(c);
122+
// value => "hello"
123+
124+
auto& value2 = magic::field_of<1>(c);
125+
// value2 => std::vector{1, 2, 3}
120126
```
121127
122-
- Traverse all fields of an aggregate class
128+
- *traverse all fields of an aggregate class*
123129
```cpp
124-
Complex c{"hello", {1, 2, 3}};
125130
auto f = [](auto field)
126131
{
132+
constexpr auto index = field.index();
133+
constexpr auto name = field.name();
134+
using type = decltype(field)::type;
135+
if constexpr (name == "name")
136+
{
137+
std::cout << "index: " << index
138+
<< ", name: " << name
139+
<< ", value: " << field.value() << std::endl;
140+
}
141+
else if constexpr (name == "vec")
142+
{
143+
std::cout << "index: " << index
144+
<< ", name: " << name
145+
<< ", value: " << field.value()[0] << std::endl;
146+
}
147+
};
127148
149+
magic::foreach (complex, f);
150+
// out =>
151+
// index: 0, name: name, value: hello
152+
// index: 1, name: vec, value: 1
153+
```
154+
## enum
155+
**just include `magic/enum.h` to use these features**
156+
```cpp
157+
enum Color
158+
{
159+
RED,
160+
GREEN,
161+
BLUE
128162
};
129-
magic::foreach(c, f);
130163
```
131-
### enum
132-
- Retrieve the enum count
164+
- *retrieve the enum count*
165+
```cpp
166+
constexpr auto count = magic::enum_count_of<Color>();
167+
// count => 3
168+
```
169+
- *retrieve the enum names*
170+
```cpp
171+
constexpr auto& names = magic::enum_names_of<Color>();
172+
// names => std::array{"RED", "GREEN", "BLUE"}
173+
```
174+
- *retrieve the enum name*
175+
```cpp
176+
constexpr auto name = magic::name_of<Color::RED>();
177+
// name => "RED"
133178

134-
- Retrieve the enum names
179+
Color color = Color::GREEN;
180+
auto name2 = magic::name_of(color);
181+
// name => "GREEN"
182+
```
183+
- *retrieve the bit field enum value*
184+
```cpp
185+
186+
187+
```
188+
189+
- *traverse all enum values*
190+
```cpp
191+
192+
```
135193

136-
- Retrieve the enum nam
194+
# Limitations
137195

138-
- Retrieve the bit field enum value
196+
# Support
197+
- `gcc` > 12
198+
- `clang` > 15
199+
- `msvc` > 19.29

docs/assets/cover.png

126 KB
Loading

docs/assets/sample_map.png

578 KB
Loading

docs/assets/sample_ptr.png

315 KB
Loading

include/magic/enum.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,14 @@ namespace magic
245245
{
246246
return details::enum_names_storage<T>::names;
247247
}
248+
249+
template <typename T>
250+
requires std::is_enum_v<T>
251+
constexpr auto& name_of(T value)
252+
{
253+
constexpr auto start = enum_start<T>();
254+
return details::enum_names_storage<T>::names[static_cast<std::size_t>(value + start)];
255+
}
248256
} // namespace magic
249257

250258
#endif // MAGIC_CPP_ENUM_H

include/magic/struct.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ namespace magic::details
2727
template <typename T, std::size_t N>
2828
consteval std::size_t try_initialize_with_n()
2929
{
30-
return []<std::size_t... Is>(std::index_sequence<Is...>) {
31-
return requires { T{Any(Is)...}; } && !requires { T{Any(Is)..., Any(0)}; };
32-
}(std::make_index_sequence<N>{});
30+
return []<std::size_t... Is>(std::index_sequence<Is...>) { return requires { T{Any(Is)...}; }; }(std::make_index_sequence<N>{});
3331
}
3432

3533
template <typename T, std::size_t N1, std::size_t N2, std::size_t N3>
@@ -45,11 +43,7 @@ namespace magic::details
4543
template <typename T, std::size_t N = 0>
4644
consteval std::size_t total_count_of_fields()
4745
{
48-
if constexpr (N > sizeof(T) * 8 + 1)
49-
{
50-
static_assert(N <= sizeof(T) * 8 + 1, "Unexpected Error in total_count_of_fields");
51-
}
52-
else if constexpr (try_initialize_with_n<T, N>())
46+
if constexpr (try_initialize_with_n<T, N>() && !try_initialize_with_n<T, N + 1>())
5347
{
5448
return N;
5549
}
@@ -186,7 +180,7 @@ namespace magic::details
186180
constexpr auto field_types_of_impl(T object)
187181
{
188182
constexpr auto N = field_count_of<T>();
189-
// clang-format off
183+
// clang-format off
190184
#include "generate/struct_bind_of_field_types.code"
191185
// clang-format on
192186
}
@@ -196,7 +190,7 @@ namespace magic::details
196190
{
197191
using T = std::remove_cvref_t<decltype(object)>;
198192
constexpr auto N = field_count_of<T>();
199-
// clang-format off
193+
// clang-format off
200194
#include "generate/struct_bind_of_field_access.code"
201195
// clang-format on
202196
}

0 commit comments

Comments
 (0)