Skip to content

Commit 40d64f2

Browse files
Added documentation
1 parent 18f0a95 commit 40d64f2

6 files changed

Lines changed: 193 additions & 1 deletion

File tree

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ reflect-cpp and sqlgen fill important gaps in C++ development. They reduce boile
5353

5454
### More in our [documentation](https://rfl.getml.com):
5555
- [Installation ↗](https://rfl.getml.com/install/#option-2-compilation-using-cmake)
56+
- [C++26 reflection ↗](https://rfl.getml.com/cpp26_reflection)
5657
- [Benchmarks ↗](https://rfl.getml.com/benchmarks)
5758
- [How to contribute ↗](https://rfl.getml.com/contributing)
5859
- [Compiling and running the tests ↗](https://rfl.getml.com/contributing/#compiling-and-running-the-tests)
@@ -676,6 +677,21 @@ The following compilers are supported for C++-20:
676677
The following compilers are supported for C++-26:
677678
- GCC 16.2 or higher
678679
680+
### Compiling with C++-26 reflection
681+
682+
To compile reflect-cpp using the standard C++ reflection facilities, pass the CMake option
683+
`REFLECTCPP_USE_CPP26_REFLECTION` together with the compiler flag that activates reflection
684+
support in your compiler (`-freflection` for GCC, `-freflection-latest` for Clang):
685+
686+
```bash
687+
cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
688+
cmake --build build -j 4
689+
```
690+
691+
With C++-26 reflection, fixed-size C arrays and inheritance are supported out of the box (no
692+
`-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE` flag needed), and there are no range restrictions for
693+
enums. Refer to the [documentation](https://rfl.getml.com/cpp26_reflection) for details.
694+
679695
### Using vcpkg
680696

681697
https://vcpkg.io/en/package/reflectcpp

docs/c_arrays_and_inheritance.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ inheritance altogether.
1212
Note that C arrays are not the same thing as `std::array`. `std::array` is always
1313
supported and is the recommended alternative.
1414

15+
!!! note "C++-26 reflection"
16+
17+
If you compile reflect-cpp with C++-26 reflection (see [C++26 reflection](cpp26_reflection.md)),
18+
then none of the restrictions in this section apply: fixed-size C arrays and inheritance are
19+
supported out of the box, no flag is required, and the fields may be spread out over
20+
multiple structs.
21+
1522
If you want support for these, you will have to pass the flag `-D REFLECT_CPP_C_ARRAYS_OR_INHERITANCE`
1623
during compilation.
1724

@@ -85,6 +92,10 @@ struct Derived : Base {
8592
};
8693
```
8794
95+
Note that this restriction does not apply when compiling with C++-26 reflection: with C++-26,
96+
the fields of the base class and the fields of the derived class are combined automatically,
97+
so the example above works as well.
98+
8899
The recommended alternative is to simply use `rfl::Flatten`, which
89100
has no such limitation:
90101

docs/cpp26_reflection.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# C++26 reflection
2+
3+
reflect-cpp can be compiled in two modes, which use two different reflection implementations:
4+
5+
* **C++-20/23 mode (the default):** reflection is implemented using metaprogramming
6+
techniques (structured bindings, aggregate-initialization analysis, and
7+
[enchantum](https://github.com/ZXShady/enchantum)). This works on a wide range of
8+
compilers, but it has some limitations and comes with a higher compile-time cost.
9+
* **C++-26 mode:** reflection uses the standard C++ reflection facilities
10+
(`<meta>`, [P2996](https://wg21.link/P2996)). This is more powerful, because members
11+
and enumerators are queried directly from the compiler instead of being inferred.
12+
13+
C++-26 mode is opt-in. It requires a compiler that supports the C++ reflection proposal
14+
and a compiler flag to activate it. The rest of this documentation applies to both modes,
15+
except where explicitly noted otherwise.
16+
17+
## Compiling with C++-26 reflection
18+
19+
The following compilers are supported for C++-26:
20+
21+
* GCC 16.2 or higher
22+
* Clang: experimental, only available in Clang builds that implement
23+
[P2996](https://wg21.link/P2996) (such as Bloomberg's
24+
[clang-p2996](https://github.com/bloomberg/clang-p2996) fork)
25+
26+
To compile reflect-cpp with C++-26 reflection, pass the CMake option
27+
`REFLECTCPP_USE_CPP26_REFLECTION` and the compiler flag that activates reflection
28+
support in your compiler:
29+
30+
* GCC: `-freflection`
31+
* Clang: `-freflection-latest`
32+
33+
For example, using cmake:
34+
35+
```bash
36+
cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
37+
cmake --build build -j 4
38+
```
39+
40+
The individual parts:
41+
42+
* `-DREFLECTCPP_USE_CPP26_REFLECTION=ON` switches reflect-cpp to the C++-26 reflection
43+
implementation and defines the macro `REFLECTCPP_USE_CPP26_REFLECTION`. If
44+
`CMAKE_CXX_STANDARD` is not set, it will be set to 26 automatically.
45+
* `-DCMAKE_CXX_STANDARD=26` sets the C++ standard to 26.
46+
* `-DCMAKE_CXX_FLAGS="-freflection"` activates the C++ reflection facilities in the
47+
compiler itself. Use `-freflection-latest` on Clang instead.
48+
49+
When compiling with C++-26 reflection, the option `REFLECTCPP_USE_STD_EXPECTED` is
50+
enabled by default as well, which means that `rfl::Result<T>` is an alias for
51+
`std::expected<T, rfl::Error>`. If you want to keep using the built-in `rfl::Result`
52+
type, pass `-DREFLECTCPP_USE_STD_EXPECTED=OFF`.
53+
54+
If you include the source files directly into your own build (see
55+
[Installation](install.md#option-4-include-source-files-into-your-own-build)), add the
56+
compile definition `-DREFLECTCPP_USE_CPP26_REFLECTION` and the appropriate compiler flag
57+
to all translation units that include reflect-cpp.
58+
59+
## What C++-26 reflection changes
60+
61+
### C arrays and inheritance are supported out of the box
62+
63+
In C++-20/23 mode, fixed-size C arrays and inheritance are only supported when you pass
64+
the flag `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE`, and inheritance only works when all of
65+
the fields are inside the same struct. Refer to
66+
[C arrays and inheritance](c_arrays_and_inheritance.md) for details.
67+
68+
In C++-26 mode, neither restriction applies:
69+
70+
* Fixed-size C arrays are regular fields as far as the compiler's reflection is concerned,
71+
so they work without any flag.
72+
* The fields of base classes are combined with the fields of the derived class, so the
73+
fields may be spread out over multiple structs.
74+
75+
For example, this is not supported in C++-20/23 mode, but works as-is in C++-26 mode:
76+
77+
```cpp
78+
struct Base {
79+
int x;
80+
};
81+
82+
struct Derived : Base {
83+
int y;
84+
};
85+
86+
const auto derived = Derived{1, 2};
87+
88+
rfl::json::write(derived);
89+
```
90+
91+
This results in the following JSON string:
92+
93+
```json
94+
{"x":1,"y":2}
95+
```
96+
97+
### No range restrictions for enums
98+
99+
In C++-20/23 mode, enum values must be in the range `[RFL_ENUM_RANGE_MIN,
100+
RFL_ENUM_RANGE_MAX]`, where the default range is `[-256, 256]`. Refer to
101+
[Enums](enums.md) for details.
102+
103+
In C++-26 mode, the enumerators are read directly from the compiler, so there is no
104+
restriction on the range of enum values, and `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX`
105+
are not needed.
106+
107+
### Lower compile-time cost
108+
109+
In C++-20/23 mode, reflect-cpp infers the fields of a struct by figuring out how the
110+
struct can be constructed. This requires a lot of compile-time work, especially in the
111+
presence of C arrays and inheritance. In C++-26 mode, the fields and enumerators are
112+
queried directly from the compiler's reflection information, which is considerably
113+
cheaper.
114+
115+
## Summary
116+
117+
| Feature | C++-20/23 | C++-26 |
118+
|---------|-----------|--------|
119+
| Supported compilers | GCC 11.4+, Clang 14.0+, MSVC 17.8+ | GCC 16.2+ (Clang: experimental) |
120+
| Compiler flag | *(none)* | `-freflection` (GCC), `-freflection-latest` (Clang) |
121+
| CMake option | *(none)* | `-DREFLECTCPP_USE_CPP26_REFLECTION=ON` |
122+
| Fixed-size C arrays | requires `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE` | supported out of the box |
123+
| Inheritance | requires `-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE`, fields must be in a single struct | supported out of the box, fields may be spread over multiple structs |
124+
| Enum value range | restricted to `[RFL_ENUM_RANGE_MIN, RFL_ENUM_RANGE_MAX]` (default `[-256, 256]`) | no restriction |
125+
| `rfl::Result` | built-in type (or `std::expected` via `-DREFLECTCPP_USE_STD_EXPECTED`) | `std::expected` by default |
126+
| Compile time | higher | lower |

docs/enums.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ However, some limitations apply:
4646
2. Enum values must be in the range `[RFL_ENUM_RANGE_MIN, RFL_ENUM_RANGE_MAX]`. If the range is not specified, the
4747
default range is `[-256, 256]`.
4848

49+
!!! note "C++-26 reflection"
50+
51+
This restriction only applies when compiling reflect-cpp with C++-20 or C++-23. When
52+
compiling with [C++-26 reflection](cpp26_reflection.md), the enumerators are read
53+
directly from the compiler, so there is no restriction on the range of enum values,
54+
and `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX` are not needed.
55+
4956
- You can specify a custom range for the all enum values by defining `RFL_ENUM_RANGE_MIN` and `RFL_ENUM_RANGE_MAX`
5057
before including the reflect-cpp header:
5158

docs/install.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,44 @@ hide:
55

66
# Installation
77

8-
The following compilers are supported:
8+
The following compilers are supported for C++-20:
99
- GCC 11.4 or higher
1010
- Clang 14.0 or higher
1111
- MSVC 17.8 (19.38) or higher
1212

13+
The following compilers are supported for C++-26:
14+
- GCC 16.2 or higher
15+
1316
You can include the source files into your build or compile it using cmake and vcpkg.
1417

18+
## Compiling with C++-26 reflection
19+
20+
By default, reflect-cpp uses a C++-20 compatible reflection implementation, which works
21+
across a wide range of compilers. If you want to use the standard C++ reflection
22+
facilities (`<meta>`, [P2996](https://wg21.link/P2996)), you can compile reflect-cpp in
23+
C++-26 mode instead. This is more powerful: fixed-size C arrays and inheritance are
24+
supported out of the box, and there are no range restrictions for enums. Refer to
25+
[C++26 reflection](cpp26_reflection.md) for details.
26+
27+
To enable C++-26 reflection, pass the CMake option `REFLECTCPP_USE_CPP26_REFLECTION` and
28+
the compiler flag that activates reflection support in your compiler:
29+
30+
* GCC: `-freflection`
31+
* Clang: `-freflection-latest` (experimental, only available in Clang builds that
32+
implement [P2996](https://wg21.link/P2996), such as Bloomberg's
33+
[clang-p2996](https://github.com/bloomberg/clang-p2996) fork)
34+
35+
For example, using cmake:
36+
37+
```bash
38+
cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
39+
cmake --build build -j 4
40+
```
41+
42+
If you include the source files into your own build (see Option 4 below), also add the
43+
compile definition `-DREFLECTCPP_USE_CPP26_REFLECTION` and the appropriate compiler flag
44+
to all translation units that include reflect-cpp.
45+
1546
## Option 1: Using vcpkg
1647

1748
Refer to [this port](https://vcpkg.link/ports/reflectcpp):

mkdocs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ nav:
112112
- Custom Format: supported_formats/supporting_your_own_format.md
113113
# - Reflective Programming: ./reflective_programming.md
114114
- Installation: install.md
115+
- C++26 reflection: cpp26_reflection.md
115116
- Documentation:
116117
- docs-readme.md
117118
- The basics:

0 commit comments

Comments
 (0)