Skip to content

Commit b63c246

Browse files
Made sure that to_named_tuple (and, by extension, rfl::replace) works properly
1 parent 03f6f2e commit b63c246

File tree

9 files changed

+100
-18
lines changed

9 files changed

+100
-18
lines changed

include/rfl/Field.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
#include "internal/Array.hpp"
1313
#include "internal/StringLiteral.hpp"
1414
#include "internal/to_std_array.hpp"
15+
#include "internal/wrap_in_rfl_array_t.hpp"
1516

1617
namespace rfl {
1718

1819
/// Used to define a field in the NamedTuple.
1920
template <internal::StringLiteral _name, class T>
2021
struct Field {
2122
/// The underlying type.
22-
using Type = T;
23+
using Type = internal::wrap_in_rfl_array_t<T>;
2324

2425
/// The name of the field.
2526
using Name = rfl::Literal<_name>;
@@ -30,7 +31,7 @@ struct Field {
3031

3132
Field(Field<_name, T>&& _field) noexcept = default;
3233

33-
Field(const Field<_name, Type>& _field) = default;
34+
Field(const Field<_name, T>& _field) = default;
3435

3536
template <class U>
3637
Field(const Field<_name, U>& _field) : value_(_field.get()) {}

include/rfl/from_named_tuple.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace rfl {
1414

1515
/// Generates the struct T from a named tuple.
1616
template <class T, class NamedTupleType>
17-
T from_named_tuple(NamedTupleType&& _n) {
17+
auto from_named_tuple(NamedTupleType&& _n) {
1818
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
1919
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
2020
RequiredType>()) {
@@ -36,7 +36,7 @@ T from_named_tuple(NamedTupleType&& _n) {
3636

3737
/// Generates the struct T from a named tuple.
3838
template <class T, class NamedTupleType>
39-
T from_named_tuple(const NamedTupleType& _n) {
39+
auto from_named_tuple(const NamedTupleType& _n) {
4040
using RequiredType = std::remove_cvref_t<rfl::named_tuple_t<T>>;
4141
if constexpr (!std::is_same<std::remove_cvref_t<NamedTupleType>,
4242
RequiredType>()) {

include/rfl/internal/Array.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef RFL_INTERNAL_ARRAY_HPP_
22
#define RFL_INTERNAL_ARRAY_HPP_
33

4+
#include <array>
45
#include <type_traits>
56

67
#include "to_std_array.hpp"
@@ -17,6 +18,8 @@ struct Array {
1718
Array() = default;
1819
Array(const StdArrayType &_arr) : arr_(_arr) {}
1920
Array(StdArrayType &&_arr) : arr_(std::move(_arr)) {}
21+
Array(const T &_arr) : arr_(to_std_array(_arr)) {}
22+
Array(T &&_arr) : arr_(to_std_array(_arr)) {}
2023

2124
~Array() = default;
2225

include/rfl/internal/move_from_tuple.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ template <class T, class Pointers, class... Args>
6363
auto move_from_pointers(Pointers& _ptrs, Args&&... _args) {
6464
constexpr auto i = sizeof...(Args);
6565
if constexpr (i == std::tuple_size_v<std::remove_cvref_t<Pointers>>) {
66-
return T{std::move(_args)...};
66+
return std::remove_cvref_t<T>{std::move(_args)...};
6767
} else {
6868
using FieldType = std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
6969

@@ -116,7 +116,7 @@ auto flatten_c_arrays(const auto& _tup) {
116116
/// Creates a struct of type T from a tuple by moving the underlying
117117
/// fields.
118118
template <class T, class TupleType>
119-
T move_from_tuple(TupleType&& _t) {
119+
auto move_from_tuple(TupleType&& _t) {
120120
auto ptr_tuple = tup_to_ptr_tuple(_t);
121121

122122
using TargetTupleType = tuple_t<std::remove_cvref_t<T>>;

include/rfl/internal/move_to_field_tuple.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <type_traits>
66

77
#include "../field_names_t.hpp"
8+
#include "Array.hpp"
89
#include "bind_to_tuple.hpp"
910
#include "has_fields.hpp"
1011
#include "is_named_tuple.hpp"
@@ -22,7 +23,15 @@ auto move_to_field_tuple(OriginalStruct&& _t) {
2223
return bind_to_tuple(_t, [](auto& x) { return std::move(x); });
2324
} else {
2425
using FieldNames = field_names_t<T>;
25-
auto tup = bind_to_tuple(_t, [](auto& x) { return std::move(x); });
26+
const auto fct = []<class T>(T& _v) {
27+
using Type = std::remove_cvref_t<T>;
28+
if constexpr (std::is_array_v<Type>) {
29+
return Array<Type>(_v);
30+
} else {
31+
return std::move(_v);
32+
}
33+
};
34+
auto tup = bind_to_tuple(_t, fct);
2635
return wrap_in_fields<FieldNames>(std::move(tup));
2736
}
2837
}

include/rfl/internal/to_std_array.hpp

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,57 @@
11
#ifndef RFL_INTERNAL_TO_STD_ARRAY_HPP_
22
#define RFL_INTERNAL_TO_STD_ARRAY_HPP_
33

4-
#include <cstdint>
54
#include <array>
5+
#include <cstdint>
6+
#include <type_traits>
67

78
namespace rfl::internal {
89

910
template <class T>
10-
struct to_std_array {
11-
using type = T;
11+
struct StdArrayType {
12+
using Type = T;
1213
};
1314

14-
template <class T, std::size_t _n>
15-
struct to_std_array<T[_n]> {
16-
using type = std::array<typename to_std_array<std::remove_cvref_t<T>>::type, _n>;
15+
template <class T, size_t _n>
16+
struct StdArrayType<T[_n]> {
17+
using Type =
18+
std::array<typename StdArrayType<std::remove_cvref_t<T>>::Type, _n>;
19+
using ValueType = std::remove_cvref_t<T>;
20+
constexpr static size_t size = _n;
1721
};
1822

1923
template <class T>
20-
using to_std_array_t = to_std_array<T>::type;
24+
using to_std_array_t = StdArrayType<T>::Type;
2125

26+
template <class T>
27+
auto to_std_array(T&& _t) {
28+
using Type = std::remove_cvref_t<T>;
29+
if constexpr (std::is_array_v<Type>) {
30+
constexpr size_t n = StdArrayType<Type>::size;
31+
const auto fct = [&]<std::size_t... _i>(std::index_sequence<_i...>) {
32+
return to_std_array_t<Type>({to_std_array(
33+
std::forward<typename StdArrayType<Type>::ValueType>(_t[_i]))...});
34+
};
35+
return fct(std::make_index_sequence<n>());
36+
} else {
37+
return std::forward<T>(_t);
38+
}
2239
}
2340

41+
template <class T>
42+
auto to_std_array(const T& _t) {
43+
using Type = std::remove_cvref_t<T>;
44+
if constexpr (std::is_array_v<Type>) {
45+
constexpr size_t n = StdArrayType<Type>::size;
46+
const auto fct = [&]<std::size_t... _i>(std::index_sequence<_i...>) {
47+
return to_std_array_t<Type>({to_std_array(_t[_i])...});
48+
};
49+
return fct(std::make_index_sequence<n>());
50+
} else {
51+
return _t;
52+
}
53+
}
54+
55+
} // namespace rfl::internal
56+
2457
#endif

tests/json/test_c_array_class5.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "test_c_array_class5.hpp"
2+
3+
#include <array>
4+
#include <source_location>
5+
6+
#include "rfl.hpp"
7+
#include "rfl/json.hpp"
8+
#include "write_and_read.hpp"
9+
10+
namespace test_c_array_class5 {
11+
12+
struct Test5 {
13+
int a[3];
14+
int b[3];
15+
int c[2][2];
16+
};
17+
18+
void test() {
19+
std::cout << std::source_location::current().function_name() << std::endl;
20+
21+
Test5 t1 = {.a = {1, 2, 3}, .b = {4, 5, 6}, .c = {{7, 8}, {9, 10}}};
22+
23+
const auto t2 = rfl::replace(t1, rfl::make_field<"b", int[3]>({1, 2, 3}));
24+
25+
write_and_read(t2, R"({"a":[1,2,3],"b":[1,2,3],"c":[[7,8],[9,10]]})");
26+
}
27+
28+
} // namespace test_c_array_class5

tests/json/test_c_array_class5.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace test_c_array_class5 {
2+
3+
void test();
4+
5+
}

tests/json/tests.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "test_c_array_class2.hpp"
1313
#include "test_c_array_class3.hpp"
1414
#include "test_c_array_class4.hpp"
15+
#include "test_c_array_class5.hpp"
1516
#include "test_custom_class1.hpp"
1617
#include "test_custom_class2.hpp"
1718
#include "test_custom_class3.hpp"
@@ -116,6 +117,12 @@ int main() {
116117
test_custom_class3::test();
117118
test_custom_class4::test();
118119

120+
test_c_array_class1::test();
121+
test_c_array_class2::test();
122+
test_c_array_class3::test();
123+
test_c_array_class4::test();
124+
test_c_array_class5::test();
125+
119126
test_replace::test();
120127
test_replace2::test();
121128
test_replace_flatten::test();
@@ -139,9 +146,5 @@ int main() {
139146

140147
test_meta_fields::test();
141148

142-
test_c_array_class1::test();
143-
test_c_array_class2::test();
144-
test_c_array_class3::test();
145-
test_c_array_class4::test();
146149
return 0;
147150
}

0 commit comments

Comments
 (0)