Skip to content

Commit 778cd54

Browse files
Use fold expressions inside the literals (#434)
1 parent f86cdb5 commit 778cd54

File tree

3 files changed

+36
-30
lines changed

3 files changed

+36
-30
lines changed

include/rfl/Literal.hpp

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Result.hpp"
1414
#include "Tuple.hpp"
1515
#include "internal/StringLiteral.hpp"
16+
#include "internal/find_index.hpp"
1617
#include "internal/no_duplicate_field_names.hpp"
1718

1819
namespace rfl {
@@ -95,31 +96,24 @@ class Literal {
9596

9697
/// Determines whether the literal contains any of the strings in the other
9798
/// literal at compile time.
98-
template <class OtherLiteralType, int _i = 0>
99+
template <class OtherLiteralType>
99100
static constexpr bool contains_any() {
100-
if constexpr (_i == num_fields_) {
101-
return false;
102-
} else {
103-
constexpr auto name = find_name_within_own_fields<_i>();
104-
return OtherLiteralType::template contains<name>() ||
105-
contains_any<OtherLiteralType, _i + 1>();
106-
}
101+
return []<int... _is>(const std::integer_sequence<int, _is...>&) {
102+
return (false || ... ||
103+
OtherLiteralType::template contains<
104+
find_name_within_own_fields<_is>()>());
105+
}(std::make_integer_sequence<int, num_fields_>());
107106
}
108107

109108
/// Determines whether the literal contains all of the strings in the other
110109
/// literal at compile time.
111-
template <class OtherLiteralType, int _i = 0, int _n_found = 0>
110+
template <class OtherLiteralType>
112111
static constexpr bool contains_all() {
113-
if constexpr (_i == num_fields_) {
114-
return _n_found == OtherLiteralType::num_fields_;
115-
} else {
116-
constexpr auto name = find_name_within_own_fields<_i>();
117-
if constexpr (OtherLiteralType::template contains<name>()) {
118-
return contains_all<OtherLiteralType, _i + 1, _n_found + 1>();
119-
} else {
120-
return contains_all<OtherLiteralType, _i + 1, _n_found>();
121-
}
122-
}
112+
return []<int... _is>(const std::integer_sequence<int, _is...>&) {
113+
return (true && ... &&
114+
OtherLiteralType::template contains<
115+
find_name_within_own_fields<_is>()>());
116+
}(std::make_integer_sequence<int, num_fields_>());
123117
}
124118

125119
/// Determines whether the literal has duplicate strings at compile time.
@@ -332,18 +326,9 @@ class Literal {
332326
}
333327

334328
/// Finds the value of a string literal at compile time.
335-
template <internal::StringLiteral _name, int _i = 0>
329+
template <internal::StringLiteral _name>
336330
static constexpr int find_value_of() {
337-
if constexpr (_i == num_fields_) {
338-
return -1;
339-
} else {
340-
using FieldType = tuple_element_t<_i, FieldsType>;
341-
if constexpr (FieldType::name_ == _name) {
342-
return _i;
343-
} else {
344-
return find_value_of<_name, _i + 1>();
345-
}
346-
}
331+
return internal::find_index_or_minus_one<_name, FieldsType>();
347332
}
348333

349334
/// Whether the literal contains this string.

include/rfl/internal/find_index.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ constexpr static int find_index() {
4545
return ix;
4646
}
4747

48+
/// Finds the index of the field signified by _field_name or -1.
49+
template <StringLiteral _field_name, class Fields>
50+
constexpr static int find_index_or_minus_one() {
51+
if constexpr (rfl::tuple_size_v<Fields> == 0) {
52+
return -1;
53+
} else {
54+
constexpr int ix = wrap_fields<_field_name, Fields>(
55+
std::make_integer_sequence<int, rfl::tuple_size_v<Fields>>());
56+
if constexpr (rfl::tuple_element_t<ix, Fields>::name_ == _field_name) {
57+
return ix;
58+
} else {
59+
return -1;
60+
}
61+
}
62+
}
63+
4864
} // namespace internal
4965
} // namespace rfl
5066

tests/json/test_literal.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ struct Person {
1919
};
2020

2121
TEST(json, test_literal) {
22+
static_assert(!FirstName::template contains_any<LastName>(),
23+
"Must be false.");
24+
static_assert(FirstName::template contains_any<FirstName>(), "Must be true.");
25+
static_assert(FirstName::template contains_all<FirstName>(), "Must be true.");
26+
2227
const auto bart = Person{.first_name = FirstName::make<"Bart">()};
2328

2429
write_and_read(bart,

0 commit comments

Comments
 (0)