Skip to content

Commit 908ee22

Browse files
authored
Make rfl::num_fields public (#465)
1 parent e6c8fdf commit 908ee22

File tree

5 files changed

+67
-21
lines changed

5 files changed

+67
-21
lines changed

docs/custom_parser.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Custom parsers
22

3-
## `rfl::Reflector`
3+
## `rfl::Reflector`
44

5-
If you absolutely do not want to make any changes to your original classes whatsoever,
6-
You can create a Reflector template specialization for your type:
5+
If you absolutely do not want to (or are unable to) make any changes to your
6+
original classes whatsoever, you can create a Reflector template specialization
7+
for your type:
78

89
```cpp
910
namespace rfl {
@@ -13,7 +14,7 @@ struct Reflector<Person> {
1314
std::string first_name;
1415
std::string last_name;
1516
};
16-
17+
1718
static Person to(const ReflType& v) noexcept {
1819
return {v.first_name, v.last_name};
1920
}
@@ -25,7 +26,27 @@ struct Reflector<Person> {
2526
}
2627
```
2728
28-
It's also fine to define just the `from` method when the original class is
29+
One way to help make sure that your `ReflType` is kept up to date with your
30+
original class is to use the `rfl::num_fields<T>` utility to implement a compile-
31+
time assertion to verify that they have the same number of fields. The
32+
`rfl::num_fields<T>` utility can be used even in cases where the original
33+
class is too complex for `reflect-cpp`'s default reflection logic or
34+
`rfl::to_view()` to be able to handle.
35+
36+
```cpp
37+
namespace rfl {
38+
template <>
39+
struct Reflector<Person> {
40+
struct ReflType {
41+
std::string first_name;
42+
std::string last_name;
43+
};
44+
static_assert(rfl::num_fields<ReflType> == rfl::num_fields<Person>,
45+
"ReflType and actual type must have the same number of fields");
46+
// ...
47+
```
48+
49+
It's also fine to define just the `from` method when the original class is
2950
only written, or `to` when the original class is only read:
3051

3152
```cpp
@@ -46,7 +67,7 @@ struct Reflector<Person> {
4667
```
4768
4869
Note that the `ReflType` does not have to be a struct. For instance, if you have
49-
a custom type called `MyCustomType` that you want to be serialized as a string,
70+
a custom type called `MyCustomType` that you want to be serialized as a string,
5071
you can do the following:
5172
5273
```cpp
@@ -114,7 +135,7 @@ struct Person {
114135
};
115136
```
116137

117-
You can then write a helper struct:
138+
You can then write a helper struct:
118139

119140
```cpp
120141
struct PersonImpl {

docs/docs-readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828

2929
[Standard containers](standard_containers.md) - Describes how reflect-cpp treats containers in the standard library.
3030

31-
[C arrays and inheritance](c_arrays_and_inheritance.md) - Describes how reflect-cpp handles C arrays and inheritance.
31+
[C arrays and inheritance](c_arrays_and_inheritance.md) - Describes how reflect-cpp handles C arrays and inheritance.
3232

33-
[rfl::Bytestring](bytestring.md) - Describes how reflect-cpp handles binary strings for formats that support them.
33+
[rfl::Bytestring](bytestring.md) - Describes how reflect-cpp handles binary strings for formats that support them.
3434

35-
[rfl::Binary, rfl::Hex and rfl::Oct](number_systems.md)- For expressing numbers in different formats.
35+
[rfl::Binary, rfl::Hex and rfl::Oct](number_systems.md)- For expressing numbers in different formats.
3636

3737
## Validation
3838

@@ -58,7 +58,7 @@
5858

5959
[Custom classes](concepts/custom_classes.md) - For custom classes with private fields.
6060

61-
[Custom parsers for your classes](custom_parser.md) - For custom classes with private fields that you want to leave absolutely untouched.
61+
[Custom parsers for your classes](custom_parser.md) - For custom classes with private fields that you want (or need) to leave absolutely untouched.
6262

6363
## Useful helper functions and classes
6464

include/rfl/num_fields.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#ifndef RFL_NUM_FIELDS_HPP_
2+
#define RFL_NUM_FIELDS_HPP_
3+
4+
#include "internal/num_fields.hpp"
5+
6+
namespace rfl {
7+
8+
/// Returns the number of fields fields.
9+
template <class T>
10+
constexpr std::size_t num_fields = internal::num_fields<T>;
11+
12+
} // namespace rfl
13+
14+
#endif

tests/README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
reflect-cpp uses vcpkg for dependency management, including
44
gtest, which is required for the tests.
55

6-
```bash
7-
# bootstrap vcpkg if you haven't done so already
6+
```shell
7+
# bootstrap vcpkg if you haven't done so already
88
git submodule update --init
99
./vcpkg/bootstrap-vcpkg.sh # Linux, macOS
1010
./vcpkg/bootstrap-vcpkg.bat # Windows
@@ -15,29 +15,35 @@ git submodule update --init
1515

1616
To compile the tests, do the following:
1717

18-
```bash
18+
```shell
1919
cmake -S . -B build -DCMAKE_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_BUILD_TESTS=ON
2020
cmake --build build -j 4 # gcc, clang
2121
cmake --build build --config Release -j 4 # MSVC
2222
```
2323

2424
To run the tests, do the following:
2525

26-
```
26+
```shell
2727
./build/tests/json/reflect-cpp-json-tests
2828
```
2929

3030
## All serialization formats
3131

3232
To compile the tests with serialization formats other than JSON, do the following:
3333

34-
```bash
34+
```shell
3535
cmake -S . -B build -DCMAKE_CXX_STANDARD=20 -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_AVRO=ON -DREFLECTCPP_BSON=ON -DREFLECTCPP_CAPNPROTO=ON -DREFLECTCPP_CBOR=ON -DREFLECTCPP_FLEXBUFFERS=ON -DREFLECTCPP_MSGPACK=ON -DREFLECTCPP_XML=ON -DREFLECTCPP_TOML=ON -DREFLECTCPP_UBJSON=ON -DREFLECTCPP_YAML=ON -DCMAKE_BUILD_TYPE=Release
3636
cmake --build build -j 4 # gcc, clang
3737
cmake --build build --config Release -j 4 # MSVC
3838
```
3939

40-
To run the tests, do the following:
40+
You can run all of the tests via `ctest`, as in:
41+
42+
```shell
43+
ctest --test-dir build --output-on-failure
44+
```
45+
46+
Or you can run tests individually, as in:
4147

4248
```
4349
./build/tests/avro/reflect-cpp-avro-tests

tests/json_c_arrays_and_inheritance/test_inheritance2.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <iostream>
55
#include <rfl.hpp>
66

7-
#include "rfl/internal/num_fields.hpp"
7+
#include "rfl/num_fields.hpp"
88

99
namespace test_inheritance2 {
1010

@@ -31,23 +31,28 @@ struct EmptyDerived2 : EmptyBase1, EmptyBase2, BaseX {};
3131
TEST(json, test_inheritance2) {
3232
Derived1 derived1;
3333
const auto derived1_view = rfl::to_view(derived1);
34+
static_assert(rfl::num_fields<Derived1> == 2);
3435
static_assert(derived1_view.size() == 2);
3536

3637
Derived2 derived2;
3738
const auto derived2_view = rfl::to_view(derived2);
39+
static_assert(rfl::num_fields<Derived2> == 3);
3840
static_assert(derived2_view.size() == 3);
3941

40-
EmptyDerived1 empty_derived0;
42+
EmptyDerived0 empty_derived0;
4143
auto empty_derived0_view = rfl::to_view(empty_derived0);
44+
static_assert(rfl::num_fields<EmptyDerived0> == 2);
4245
static_assert(empty_derived0_view.size() == 2);
4346

4447
EmptyDerived1 empty_derived1;
4548
auto empty_derived1_view = rfl::to_view(empty_derived1);
49+
static_assert(rfl::num_fields<EmptyDerived1> == 2);
4650
static_assert(empty_derived1_view.size() == 2);
4751

48-
EmptyDerived1 empty_derived2;
52+
EmptyDerived2 empty_derived2;
4953
auto empty_derived2_view = rfl::to_view(empty_derived2);
50-
static_assert(empty_derived0_view.size() == 2);
54+
static_assert(rfl::num_fields<EmptyDerived1> == 2);
55+
static_assert(empty_derived2_view.size() == 2);
5156

5257
EXPECT_TRUE(true);
5358
}

0 commit comments

Comments
 (0)