Skip to content

Commit 5683df5

Browse files
committed
add the lastest docs
1 parent 3a558e5 commit 5683df5

File tree

13 files changed

+545
-417
lines changed

13 files changed

+545
-417
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,3 @@ target_link_libraries(all_tests GTest::gtest_main)
3636
# 使用Google Test自动发现所有测试并将其添加到测试套件中
3737
include(GoogleTest)
3838
gtest_discover_tests(all_tests)
39-

README.md

Lines changed: 98 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,199 +1,144 @@
1-
![cover](docs/assets/cover.png)
1+
magic-cpp is a header-only C++ library. It aims to make it easier for you to use C++, including a series of functions such as visualizing type names, reflection of structs and enumerations, etc. It can help you get rid of the compiler's error messages which are difficult to read
22

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.
43

5-
# Documentation
6-
* [Reference](doc/reference.md)
7-
* [Limitations](doc/limitations.md)
8-
* [Integration](#Integration)
4+
- [Visualizing type](#visualizing-type)
5+
- [Basic usage](#basic-usage)
6+
- [Custom type name](#custom-type-name)
7+
- [Configurability](#configurability)
8+
- [Other features](#other-features)
99

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

13-
**just include `magic/type.h` to use the features below**
11+
# Visualizing type
12+
`#include <magic/visualize.h>`to use features below, `C++17` is minimum required
1413

15-
- *retrieve the full name of a type*:
14+
## Basic usage
15+
when using template programming, you often encounter the dilemma of type mismatch, especially when using libraries like `ranges`, templates are often deeply nested and difficult to read. Do not worry, `magic-cpp` can help you visualize the type, making it easier for human to understand the type. Consider the following example
1616
```cpp
17-
struct Point{};
18-
19-
constexpr auto name = magic::full_name_of<Point>();
20-
// name => "Point"
17+
using T = int (*(*(*)(int*))[4])(int*); // hard to understand
18+
std::cout << magic::visualize<T>() << std::endl;
19+
```
20+
Output:
2121

22-
constexpr auto name2 = magic::full_name_of<std::vector<int>>();
23-
// name2 => "std::vector<int>"
22+
![visualize](docs/assets/sample_ptr.png)
2423

25-
constexpr auto name3 = magic::full_name_of<std::size_t>();
26-
// name3 => "unsigned long long int"
27-
```
28-
- *retrieve the display name of a type*
24+
Or you may encounter this when writing code
2925
```cpp
30-
// specialize for type to customize the display name
31-
template<>
32-
struct magic::type_info<std::size_t>
33-
{
34-
constexpr static auto value = "std::size_t";
35-
};
26+
using T = std::function<int(const std::vector<int>&, std::tuple<int, int, int>)>; // hard to understand
27+
std::cout << magic::visualize<T>() << std::endl;
28+
```
29+
Output:
30+
31+
![visualize](docs/assets/std_function.png)
32+
33+
Almost all commonly used templates can be converted into such a tree representation, which is clear at a glance. Of course, the full expansion of some types is very long and not what you expected, for example, the output effect of `std::string` on `gcc` is like this
34+
35+
![visualize](docs/assets/full_std_string.png)
3636

37+
## Custom type name
38+
As you can see, there is a lot of information we don't want to see. It doesn't matter! Provide a custom type name through explicit specialization
39+
```cpp
3740
template<>
3841
struct magic::type_info<std::string>
3942
{
40-
constexpr static auto value = "std::string";
43+
inline static std::string name = "std::string";
4144
};
42-
43-
// use name_of to get the display name
44-
constexpr auto name = magic::name_of<std::size_t>();
45-
// name => "std::size_t"
46-
47-
constexpr auto name2 = magic::name_of<std::string>();
48-
// name => "std::string"
4945
```
46+
In this way, when encountering `std::string`, only the following will be displayed
5047

51-
- *visualize type*
52-
```cpp
53-
// for some complex type, it is hard to understand for human
54-
// we can visualize it as a tree to make it more readable
55-
56-
using T = int (*(*(*)(int*))[4])(int*); // hard to understand
57-
std::cout << magic::full_tree_of<T>() << std::endl;
58-
```
59-
*Output:*
48+
![visualize](docs/assets/std_string.png)
6049

61-
![ptr](docs/assets/sample_ptr.png)
50+
It's the custom name, isn't it convenient? I have pre-defined some commonly used type aliases such as `std::size_t`, `std::string`, `std::vector` in `customization.h`. If you need it, you can try to modify or add it yourself
6251

63-
----------------
52+
## Configurability
53+
Considering that some terminals do not support color, or do not support `utf` characters, the display will appear garbled, so we provide options to turn off these functions
6454
```cpp
65-
using T = std::map<int, std::string>;
66-
std::cout << magic::full_tree_of<T>() << std::endl;
55+
magic::VisualizeOption option;
56+
option.UTF8_SUPPORT = false; // do not use utf8 characters
57+
option.COLORFUL_SUPPORT = false; // turn off color support
58+
option.FULL_NAME = true; // use full name instead of custom alias
59+
std::cout << magic::visualize<std::string>(option) << std::endl;
6760
```
68-
*Output*:
69-
![map](docs/assets/sample_map.png)
61+
Output:
7062

71-
you can also use `tree_of` to get a more compact form, more details see [type](docs/type.md).
72-
73-
## [aggregate class](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Definitions)
74-
**just include `magic/struct.h` to use these features**
63+
![visualize](docs/assets/noutf_nocolor_full_std_string.png)
7564

65+
if you want to customize the color scheme, you can use the `HighlightConfig` structure
7666
```cpp
77-
struct Complex
67+
struct HighlightConfig
7868
{
79-
std::string name;
80-
std::vector<int> vec;
81-
}; // Complex is an aggregate class
82-
```
69+
std::uint32_t type; // type: int, double, ...
70+
std::uint32_t nttp; // non type template parameter: 1, 2, ...
71+
std::uint32_t tmpl; // template: std::vector, ...
72+
std::uint32_t builtin; // built-in compound type: ptr, ref...
73+
std::uint32_t modifier; // modifier: const, volatile, ...
74+
std::uint32_t tag; // tag: R: , M: , ...
75+
};
8376

84-
- *retrieve field count of an aggregate class*
85-
```cpp
86-
constexpr auto count = magic::field_count_of<Complex>();
87-
// count => 2
88-
```
89-
- *retrieve the field types for an aggregate class*
90-
```cpp
91-
using Types = magic::field_types_of<Complex>;
92-
// Types => std::tuple<std::string, std::vector<int>>
93-
```
94-
- *retrieve the field type at a given index for an aggregate class*
95-
```cpp
96-
using First = magic::field_type_of<Complex, 0>;
97-
// First => std::string
77+
// 默认采用的配色方案是 Dark
78+
constexpr static inline HighlightConfig Dark = {
79+
.type = 0xE5C07B, // yellow
80+
.nttp = 0xD19A66, // orange
81+
.tmpl = 0x0087CE, // blue
82+
.builtin = 0xC678DD, // purple
83+
.modifier = 0x98C379, // green
84+
.tag = 0x5C6370, // gray
85+
};
9886

99-
using Second = magic::field_type_of<Complex, 1>;
100-
// Second => std::vector<int>
87+
// there is also a built-in Light style color scheme
10188
```
102-
- *retrieve the field names for an aggregate class*
89+
You can also customize the color scheme yourself, and then pass it to the `visualize` function
10390
```cpp
104-
constexpr auto names = magic::field_names_of<Complex>();
105-
// names => std::array{"name", "vec"}
91+
magic::VisualizeOption option; // default option
92+
std::cout << magic::visualize<std::string>(option, magic::Light) << std::endl;
10693
```
94+
## Other features
95+
Besides visualizing types, we also support some other operations
10796

108-
- *retrieve the field name at a given index for an aggregate class*
97+
retrieving a type's `display_name`
10998
```cpp
110-
constexpr auto name1 = magic::field_name_of<Complex>(0);
111-
// name1 => "name"
11299

113-
constexpr auto name2 = magic::field_name_of<Complex>(1);
114-
// name2 => "vec"
115-
```
116-
117-
- *retrieve the field reference at a given index for an aggregate class*
118-
```cpp
119-
Complex c{"hello", {1, 2, 3}};
120-
121-
auto& value = magic::field_of<0>(c);
122-
// value => "hello"
123100

124-
auto& value2 = magic::field_of<1>(c);
125-
// value2 => std::vector{1, 2, 3}
126101
```
127102

128-
- *traverse all fields of an aggregate class*
103+
retrieving `raw_name` in compile time
129104
```cpp
130-
auto f = [](auto field)
105+
template<typename T>
106+
struct Point
131107
{
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-
}
108+
T start;
109+
T end;
147110
};
148111

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
162-
};
163-
```
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"
112+
// retrieving a type's raw_name
113+
constexpr auto name = magic::raw_name_of<Point<int>>();
114+
// name => "Point<int>"
178115

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
116+
// retrieving a non-type template parameter's raw_name
117+
constexpr auto name2 = magic::raw_name_of<1>();
118+
// name2 => "1"
185119

120+
// retrieving a template's raw_name
121+
constexpr auto name3 = magic::raw_name_of_template<Point<int>>();
122+
// name3 => "Point"
186123

187-
```
124+
// retrieving a member's raw_name, C++20 or higher is required
125+
Point point;
126+
constexpr auto name4 = magic::raw_name_of_member<&point.start>();
127+
// name4 => "start"
188128

189-
- *traverse all enum values*
190-
```cpp
129+
constexpr auto name5 = magic::raw_name_of_member<&point.end>();
130+
// name5 => "end"
191131

192-
```
193132

194-
# Limitations
133+
enum class Color
134+
{
135+
RED,
136+
GREEN,
137+
BLUE,
138+
};
195139

196-
# Support
197-
- `gcc` > 12
198-
- `clang` > 15
199-
- `msvc` > 19.29
140+
// retrieving an enumeration's raw_name
141+
constexpr auto name6 = magic::raw_name_of<Color::RED>();
142+
// name6 => "RED"
143+
```
144+
Please note that the content obtained by these methods may be different on different compilers, please do not use them to build the core part of the code.

0 commit comments

Comments
 (0)