Skip to content

Commit a0fe397

Browse files
Better rvalue handling for NamedTuple and Result (#446)
1 parent ec6ab3b commit a0fe397

File tree

2 files changed

+138
-86
lines changed

2 files changed

+138
-86
lines changed

include/rfl/NamedTuple.hpp

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -85,27 +85,29 @@ class NamedTuple {
8585
/// Move constructor.
8686
template <class... OtherFieldTypes>
8787
NamedTuple(NamedTuple<OtherFieldTypes...>&& _other)
88-
: NamedTuple(retrieve_fields(_other.fields(), seq_)) {}
88+
: NamedTuple(retrieve_fields(
89+
std::forward<NamedTuple<OtherFieldTypes...>>(_other).fields(),
90+
seq_)) {}
8991

9092
~NamedTuple() = default;
9193

9294
/// Returns a new named tuple with additional fields.
9395
template <internal::StringLiteral _name, class FType, class... Tail>
94-
auto add(Field<_name, FType>&& _head, Tail&&... _tail) {
96+
auto add(Field<_name, FType>&& _head, Tail&&... _tail) && {
9597
using Head = Field<_name, FType>;
9698
if constexpr (sizeof...(Tail) > 0) {
9799
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
98-
make_fields(seq_, std::forward<Head>(_head)))
100+
std::move(*this).make_fields(seq_, std::forward<Head>(_head)))
99101
.add(std::forward<Tail>(_tail)...);
100102
} else {
101103
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
102-
make_fields(seq_, std::forward<Head>(_head)));
104+
std::move(*this).make_fields(seq_, std::forward<Head>(_head)));
103105
}
104106
}
105107

106108
/// Returns a new named tuple with additional fields.
107109
template <internal::StringLiteral _name, class FType, class... Tail>
108-
auto add(Field<_name, FType> _head, const Tail&... _tail) const {
110+
auto add(Field<_name, FType> _head, const Tail&... _tail) const& {
109111
using Head = Field<_name, FType>;
110112
if constexpr (sizeof...(Tail) > 0) {
111113
return NamedTuple<FieldTypes..., std::remove_cvref_t<Head>>(
@@ -120,19 +122,21 @@ class NamedTuple {
120122
/// Template specialization for rfl::Tuple, so we can pass fields from other
121123
/// named tuples.
122124
template <class... TupContent, class... Tail>
123-
auto add(rfl::Tuple<TupContent...>&& _tuple, Tail&&... _tail) {
125+
auto add(rfl::Tuple<TupContent...>&& _tuple, Tail&&... _tail) && {
124126
if constexpr (sizeof...(Tail) > 0) {
125-
return add_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple))
127+
return std::move(*this)
128+
.add_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple))
126129
.add(std::forward<Tail>(_tail)...);
127130
} else {
128-
return add_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple));
131+
return std::move(*this).add_tuple(
132+
std::forward<rfl::Tuple<TupContent...>>(_tuple));
129133
}
130134
}
131135

132136
/// Template specialization for rfl::Tuple, so we can pass fields from other
133137
/// named tuples.
134138
template <class... TupContent, class... Tail>
135-
auto add(rfl::Tuple<TupContent...> _tuple, const Tail&... _tail) const {
139+
auto add(rfl::Tuple<TupContent...> _tuple, const Tail&... _tail) const& {
136140
if constexpr (sizeof...(Tail) > 0) {
137141
return add_tuple(std::move(_tuple)).add(_tail...);
138142
} else {
@@ -143,36 +147,39 @@ class NamedTuple {
143147
/// Template specialization for NamedTuple, so we can pass fields from other
144148
/// named tuples.
145149
template <class... TupContent, class... Tail>
146-
auto add(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
147-
return add(std::forward<rfl::Tuple<TupContent...>>(_named_tuple.fields()),
148-
std::forward<Tail>(_tail)...);
150+
auto add(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) && {
151+
return std::move(*this).add(
152+
std::forward<rfl::Tuple<TupContent...>>(
153+
std::forward<NamedTuple<TupContent...>>(_named_tuple).fields()),
154+
std::forward<Tail>(_tail)...);
149155
}
150156

151157
/// Template specialization for NamedTuple, so we can pass fields from other
152158
/// named tuples.
153159
template <class... TupContent, class... Tail>
154-
auto add(NamedTuple<TupContent...> _named_tuple, const Tail&... _tail) const {
160+
auto add(NamedTuple<TupContent...> _named_tuple,
161+
const Tail&... _tail) const& {
155162
return add(_named_tuple.fields(), _tail...);
156163
}
157164

158165
/// Creates a new named tuple by applying the supplied function to
159166
/// field. The function is expected to return a named tuple itself.
160167
template <typename F>
161-
auto and_then(const F& _f) {
168+
auto and_then(const F& _f) && {
162169
const auto transform_field = [&_f](auto... _fields) {
163170
return rfl::tuple_cat(_f(std::move(_fields)).fields()...);
164171
};
165172
const auto to_nt = []<class... NewFields>(rfl::Tuple<NewFields...>&& _tup) {
166173
return NamedTuple<NewFields...>(_tup);
167174
};
168-
auto new_fields = rfl::apply(transform_field, std::move(fields()));
175+
auto new_fields = rfl::apply(transform_field, std::move(*this).fields());
169176
return to_nt(std::move(new_fields));
170177
}
171178

172179
/// Creates a new named tuple by applying the supplied function to
173180
/// field. The function is expected to return a named tuple itself.
174181
template <typename F>
175-
auto and_then(const F& _f) const {
182+
auto and_then(const F& _f) const& {
176183
const auto transform_field = [&_f](auto... _fields) {
177184
return rfl::tuple_cat(_f(std::move(_fields)).fields()...);
178185
};
@@ -193,10 +200,10 @@ class NamedTuple {
193200
}
194201

195202
/// Returns a tuple containing the fields.
196-
Fields fields() { return make_fields(seq_); }
203+
Fields fields() && { return std::move(*this).make_fields(seq_); }
197204

198205
/// Returns a tuple containing the fields.
199-
Fields fields() const { return make_fields(seq_); }
206+
Fields fields() const& { return make_fields(seq_); }
200207

201208
/// Gets a field by index.
202209
template <int _index>
@@ -276,13 +283,15 @@ class NamedTuple {
276283
/// Replaces one or several fields, returning a new version
277284
/// with the non-replaced fields left unchanged.
278285
template <internal::StringLiteral _name, class FType, class... OtherRFields>
279-
auto replace(Field<_name, FType>&& _field, OtherRFields&&... _other_fields) {
286+
auto replace(Field<_name, FType>&& _field,
287+
OtherRFields&&... _other_fields) && {
280288
using RField = Field<_name, FType>;
281289
constexpr auto num_other_fields = sizeof...(OtherRFields);
282290
if constexpr (num_other_fields == 0) {
283-
return replace_value<RField>(_field.value_);
291+
return std::move(*this).template replace_value<RField>(_field.value_);
284292
} else {
285-
return replace_value<RField>(_field.value_)
293+
return std::move(*this)
294+
.template replace_value<RField>(_field.value_)
286295
.replace(std::forward<OtherRFields>(_other_fields)...);
287296
}
288297
}
@@ -291,7 +300,7 @@ class NamedTuple {
291300
/// with the non-replaced fields left unchanged.
292301
template <internal::StringLiteral _name, class FType, class... OtherRFields>
293302
auto replace(Field<_name, FType> _field,
294-
const OtherRFields&... _other_fields) const {
303+
const OtherRFields&... _other_fields) const& {
295304
using RField = Field<_name, FType>;
296305
constexpr auto num_other_fields = sizeof...(OtherRFields);
297306
if constexpr (num_other_fields == 0) {
@@ -305,19 +314,21 @@ class NamedTuple {
305314
/// Template specialization for rfl::Tuple, so we can pass fields from other
306315
/// named tuples.
307316
template <class... TupContent, class... Tail>
308-
auto replace(rfl::Tuple<TupContent...>&& _tuple, Tail&&... _tail) {
317+
auto replace(rfl::Tuple<TupContent...>&& _tuple, Tail&&... _tail) && {
309318
if constexpr (sizeof...(Tail) > 0) {
310-
return replace_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple))
319+
return std::move(*this)
320+
.replace_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple))
311321
.replace(std::forward<Tail>(_tail)...);
312322
} else {
313-
return replace_tuple(std::forward<rfl::Tuple<TupContent...>>(_tuple));
323+
return std::move(*this).replace_tuple(
324+
std::forward<rfl::Tuple<TupContent...>>(_tuple));
314325
}
315326
}
316327

317328
/// Template specialization for rfl::Tuple, so we can pass fields from other
318329
/// named tuples.
319330
template <class... TupContent, class... Tail>
320-
auto replace(rfl::Tuple<TupContent...> _tuple, const Tail&... _tail) const {
331+
auto replace(rfl::Tuple<TupContent...> _tuple, const Tail&... _tail) const& {
321332
if constexpr (sizeof...(Tail) > 0) {
322333
return replace_tuple(std::move(_tuple)).replace(_tail...);
323334
} else {
@@ -328,8 +339,8 @@ class NamedTuple {
328339
/// Template specialization for NamedTuple, so we can pass fields from other
329340
/// named tuples.
330341
template <class... TupContent, class... Tail>
331-
auto replace(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) {
332-
return replace(
342+
auto replace(NamedTuple<TupContent...>&& _named_tuple, Tail&&... _tail) && {
343+
return std::move(*this).replace(
333344
std::forward<NamedTuple<TupContent...>>(_named_tuple).fields(),
334345
std::forward<Tail>(_tail)...);
335346
}
@@ -338,7 +349,7 @@ class NamedTuple {
338349
/// named tuples.
339350
template <class... TupContent, class... Tail>
340351
auto replace(NamedTuple<TupContent...> _named_tuple,
341-
const Tail&... _tail) const {
352+
const Tail&... _tail) const& {
342353
return replace(_named_tuple.fields(), _tail...);
343354
}
344355

@@ -348,21 +359,21 @@ class NamedTuple {
348359
/// Creates a new named tuple by applying the supplied function to every
349360
/// field.
350361
template <typename F>
351-
auto transform(const F& _f) {
362+
auto transform(const F& _f) && {
352363
const auto transform_field = [&_f](auto... fields) {
353364
return rfl::make_tuple(_f(std::move(fields))...);
354365
};
355366
const auto to_nt = []<class... NewFields>(rfl::Tuple<NewFields...>&& _tup) {
356367
return NamedTuple<NewFields...>(_tup);
357368
};
358-
auto new_fields = rfl::apply(transform_field, std::move(fields()));
369+
auto new_fields = rfl::apply(transform_field, std::move(*this).fields());
359370
return to_nt(std::move(new_fields));
360371
}
361372

362373
/// Creates a new named tuple by applying the supplied function to every
363374
/// field.
364375
template <typename F>
365-
auto transform(const F& _f) const {
376+
auto transform(const F& _f) const& {
366377
const auto transform_field = [&_f](auto... fields) {
367378
return rfl::make_tuple(_f(std::move(fields))...);
368379
};
@@ -383,17 +394,17 @@ class NamedTuple {
383394
/// Adds the elements of a tuple to a newly created named tuple,
384395
/// and other elements to a newly created named tuple.
385396
template <class... TupContent>
386-
constexpr auto add_tuple(rfl::Tuple<TupContent...>&& _tuple) {
397+
constexpr auto add_tuple(rfl::Tuple<TupContent...>&& _tuple) && {
387398
const auto a = [this](auto&&... _fields) {
388-
return this->add(std::forward<TupContent>(_fields)...);
399+
return std::move(*this).add(std::forward<TupContent>(_fields)...);
389400
};
390401
return rfl::apply(a, std::forward<rfl::Tuple<TupContent...>>(_tuple));
391402
}
392403

393404
/// Adds the elements of a tuple to a newly created named tuple,
394405
/// and other elements to a newly created named tuple.
395406
template <class... TupContent>
396-
constexpr auto add_tuple(rfl::Tuple<TupContent...>&& _tuple) const {
407+
constexpr auto add_tuple(rfl::Tuple<TupContent...>&& _tuple) const& {
397408
const auto a = [this](auto&&... _fields) {
398409
return this->add(std::forward<TupContent>(_fields)...);
399410
};
@@ -435,11 +446,10 @@ class NamedTuple {
435446
/// Generates the fields.
436447
template <int... _is, class... AdditionalArgs>
437448
auto make_fields(std::integer_sequence<int, _is...>,
438-
AdditionalArgs&&... _args) {
449+
AdditionalArgs&&... _args) && {
439450
const auto wrap = [this]<int _i>(Index<_i>) {
440451
using FieldType = internal::nth_element_t<_i, FieldTypes...>;
441-
using T = std::remove_cvref_t<typename FieldType::Type>;
442-
return FieldType(std::forward<T>(rfl::get<_i>(values_)));
452+
return FieldType(std::move(rfl::get<_i>(values_)));
443453
};
444454
return rfl::make_tuple(wrap(Index<_is>{})...,
445455
std::forward<AdditionalArgs>(_args)...);
@@ -448,7 +458,7 @@ class NamedTuple {
448458
/// Generates the fields.
449459
template <int... _is, class... AdditionalArgs>
450460
auto make_fields(std::integer_sequence<int, _is...>,
451-
AdditionalArgs... _args) const {
461+
AdditionalArgs... _args) const& {
452462
const auto wrap = [this]<int _i>(Index<_i>) {
453463
using FieldType = internal::nth_element_t<_i, FieldTypes...>;
454464
return FieldType(rfl::get<_i>(values_));
@@ -474,16 +484,16 @@ class NamedTuple {
474484

475485
/// Replaced the field signified by the field type.
476486
template <class Field, class T>
477-
NamedTuple<FieldTypes...> replace_value(T&& _val) {
487+
NamedTuple<FieldTypes...> replace_value(T&& _val) && {
478488
using FieldType = std::remove_cvref_t<Field>;
479489
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
480-
return make_replaced<index>(std::forward<Values>(values_),
481-
std::forward<T>(_val), seq_);
490+
return make_replaced<index>(std::move(values_), std::forward<T>(_val),
491+
seq_);
482492
}
483493

484494
/// Replaced the field signified by the field type.
485495
template <class Field, class T>
486-
NamedTuple<FieldTypes...> replace_value(T&& _val) const {
496+
NamedTuple<FieldTypes...> replace_value(T&& _val) const& {
487497
using FieldType = std::remove_cvref_t<Field>;
488498
constexpr auto index = internal::find_index<FieldType::name_, Fields>();
489499
auto values = values_;
@@ -493,17 +503,17 @@ class NamedTuple {
493503
/// Adds the elements of a tuple to a newly created named tuple,
494504
/// and other elements to a newly created named tuple.
495505
template <class... TupContent>
496-
auto replace_tuple(rfl::Tuple<TupContent...>&& _tuple) {
506+
auto replace_tuple(rfl::Tuple<TupContent...>&& _tuple) && {
497507
const auto r = [this](auto&&... _fields) {
498-
return this->replace(std::forward<TupContent>(_fields)...);
508+
return std::move(*this).replace(std::forward<TupContent>(_fields)...);
499509
};
500510
return rfl::apply(r, std::forward<rfl::Tuple<TupContent...>>(_tuple));
501511
}
502512

503513
/// Adds the elements of a tuple to a newly created named tuple,
504514
/// and other elements to a newly created named tuple.
505515
template <class... TupContent>
506-
auto replace_tuple(rfl::Tuple<TupContent...>&& _tuple) const {
516+
auto replace_tuple(rfl::Tuple<TupContent...>&& _tuple) const& {
507517
const auto r = [this](auto&&... _fields) {
508518
return this->replace(std::forward<TupContent>(_fields)...);
509519
};

0 commit comments

Comments
 (0)