Skip to content

Commit 1a183a1

Browse files
authored
glz::for_each_field (#1497)
* Add glz::for_each_field * Update README.md * Update reflect.hpp
1 parent f22d8ce commit 1a183a1

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

README.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ import libs = libglaze%lib{glaze}
237237

238238
# Explicit Metadata
239239

240-
If you want to specialize your reflection then you can optionally write the code below:
240+
If you want to specialize your reflection then you can **optionally** write the code below:
241241

242242
> This metadata is also necessary for non-aggregate initializable structs.
243243
@@ -322,7 +322,25 @@ static_assert(glz::reflect<my_struct>::keys[0] == "i"); // Access keys
322322

323323
> [!WARNING]
324324
>
325-
> The `glz::reflect` fields described above have been formalized and are unlikely to change. Other fields within the `glz::reflect` struct may evolve as we continue to formalize the spec. Therefore, breaking changes may occur for undocumented fields in the future.
325+
> The `glz::reflect` fields described above have been formalized and are unlikely to change. Other fields may evolve as we continue to formalize the spec.
326+
327+
## glz::for_each_field
328+
329+
```c++
330+
struct test_type {
331+
int32_t int1{};
332+
int64_t int2{};
333+
};
334+
335+
test_type var{42, 43};
336+
337+
glz::for_each_field(var, [](auto& field) {
338+
field += 1;
339+
});
340+
341+
expect(var.int1 == 43);
342+
expect(var.int2 == 44);
343+
```
326344
327345
# Custom Read/Write
328346

include/glaze/core/reflect.hpp

+27
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,33 @@ namespace glz
22012201
}
22022202
}
22032203

2204+
namespace glz
2205+
{
2206+
// The Callable comes second as ranges::for_each puts the callable at the end
2207+
2208+
template <class Callable, detail::reflectable T>
2209+
void for_each_field(T&& value, Callable&& callable)
2210+
{
2211+
constexpr auto N = reflect<T>::size;
2212+
if constexpr (N > 0) {
2213+
[&]<size_t... I>(std::index_sequence<I...>) constexpr {
2214+
(callable(get_member(value, get<I>(to_tuple(value)))), ...);
2215+
}(std::make_index_sequence<N>{});
2216+
}
2217+
}
2218+
2219+
template <class Callable, detail::glaze_object_t T>
2220+
void for_each_field(T&& value, Callable&& callable)
2221+
{
2222+
constexpr auto N = reflect<T>::size;
2223+
if constexpr (N > 0) {
2224+
[&]<size_t... I>(std::index_sequence<I...>) constexpr {
2225+
(callable(get_member(value, get<I>(reflect<T>::values))), ...);
2226+
}(std::make_index_sequence<N>{});
2227+
}
2228+
}
2229+
}
2230+
22042231
#ifdef _MSC_VER
22052232
// restore disabled warnings
22062233
#pragma warning(pop)

tests/reflection/reflection.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,55 @@
77

88
using namespace ut;
99

10+
struct test_type {
11+
int32_t int1{};
12+
int64_t int2{};
13+
};
14+
15+
suite reflect_test_type = [] {
16+
static_assert(glz::reflect<test_type>::size == 2);
17+
static_assert(glz::reflect<test_type>::keys[0] == "int1");
18+
19+
"for_each_field"_test = [] {
20+
test_type var{42, 43};
21+
22+
glz::for_each_field(var, [](auto& field) {
23+
field += 1;
24+
});
25+
26+
expect(var.int1 == 43);
27+
expect(var.int2 == 44);
28+
};
29+
};
30+
31+
struct test_type_meta {
32+
int32_t int1{};
33+
int64_t int2{};
34+
};
35+
36+
template <>
37+
struct glz::meta<test_type_meta>
38+
{
39+
using T = test_type_meta;
40+
static constexpr auto value = object(&T::int1, &T::int2);
41+
};
42+
43+
suite meta_reflect_test_type = [] {
44+
static_assert(glz::reflect<test_type_meta>::size == 2);
45+
static_assert(glz::reflect<test_type_meta>::keys[0] == "int1");
46+
47+
"for_each_field"_test = [] {
48+
test_type_meta var{42, 43};
49+
50+
glz::for_each_field(var, [](auto& field) {
51+
field += 1;
52+
});
53+
54+
expect(var.int1 == 43);
55+
expect(var.int2 == 44);
56+
};
57+
};
58+
1059
struct a_type
1160
{
1261
float fluff = 1.1f;

0 commit comments

Comments
 (0)