22#define RFL_VARIANT_HPP_
33
44#include < array>
5- #include < bit>
65#include < cstdint>
76#include < limits>
87#include < optional>
1413#include " internal/nth_element_t.hpp"
1514#include " internal/variant/find_max_size.hpp"
1615#include " internal/variant/is_alternative_type.hpp"
17- #include " internal/variant/is_convertible_to.hpp"
1816#include " internal/variant/result_t.hpp"
1917
2018namespace rfl {
@@ -152,80 +150,40 @@ class Variant {
152150 }
153151
154152 template <class F >
155- result_t <F> visit (F& _f) {
153+ result_t <F> visit (F&& _f) {
156154 using ResultType = result_t <F>;
157155 if constexpr (std::is_same_v<ResultType, void >) {
158156 bool visited = false ;
159- do_visit_no_result (_f , &visited,
157+ do_visit_no_result (std::forward<F>(_f) , &visited,
160158 std::make_integer_sequence<IndexType, size_>());
161159 } else if constexpr (std::is_reference_v<ResultType>) {
162160 std::remove_reference_t <ResultType>* res = nullptr ;
163- do_visit_with_reference (_f , &res,
161+ do_visit_with_reference (std::forward<F>(_f) , &res,
164162 std::make_integer_sequence<IndexType, size_>());
165163 return *res;
166164 } else {
167165 auto res = std::optional<ResultType>();
168- do_visit_with_result (_f , &res,
166+ do_visit_with_result (std::forward<F>(_f) , &res,
169167 std::make_integer_sequence<IndexType, size_>());
170168 return std::move (*res);
171169 }
172170 }
173171
174172 template <class F >
175- result_t <F> visit (F& _f) const {
173+ result_t <F> visit (F&& _f) const {
176174 using ResultType = result_t <F>;
177175 if constexpr (std::is_same_v<ResultType, void >) {
178176 bool visited = false ;
179- do_visit_no_result (_f , &visited,
177+ do_visit_no_result (std::forward<F>(_f) , &visited,
180178 std::make_integer_sequence<IndexType, size_>());
181179 } else if constexpr (std::is_reference_v<ResultType>) {
182180 std::remove_reference_t <ResultType>* res = nullptr ;
183- do_visit_with_reference (_f , &res,
181+ do_visit_with_reference (std::forward<F>(_f) , &res,
184182 std::make_integer_sequence<IndexType, size_>());
185183 return *res;
186184 } else {
187185 auto res = std::optional<ResultType>();
188- do_visit_with_result (_f, &res,
189- std::make_integer_sequence<IndexType, size_>());
190- return std::move (*res);
191- }
192- }
193-
194- template <class F >
195- result_t <F> visit (const F& _f) {
196- using ResultType = std::remove_reference_t <result_t <F>>;
197- if constexpr (std::is_same_v<ResultType, void >) {
198- bool visited = false ;
199- do_visit_no_result (_f, &visited,
200- std::make_integer_sequence<IndexType, size_>());
201- } else if constexpr (std::is_reference_v<ResultType>) {
202- std::remove_reference_t <ResultType>* res = nullptr ;
203- do_visit_with_reference (_f, &res,
204- std::make_integer_sequence<IndexType, size_>());
205- return *res;
206- } else {
207- auto res = std::optional<ResultType>();
208- do_visit_with_result (_f, &res,
209- std::make_integer_sequence<IndexType, size_>());
210- return std::move (*res);
211- }
212- }
213-
214- template <class F >
215- result_t <F> visit (const F& _f) const {
216- using ResultType = result_t <F>;
217- if constexpr (std::is_same_v<ResultType, void >) {
218- bool visited = false ;
219- do_visit_no_result (_f, &visited,
220- std::make_integer_sequence<IndexType, size_>());
221- } else if constexpr (std::is_reference_v<ResultType>) {
222- std::remove_reference_t <ResultType>* res = nullptr ;
223- do_visit_with_reference (_f, &res,
224- std::make_integer_sequence<IndexType, size_>());
225- return *res;
226- } else {
227- auto res = std::optional<ResultType>();
228- do_visit_with_result (_f, &res,
186+ do_visit_with_result (std::forward<F>(_f), &res,
229187 std::make_integer_sequence<IndexType, size_>());
230188 return std::move (*res);
231189 }
@@ -330,7 +288,7 @@ class Variant {
330288 std::optional<ResultType>* _res,
331289 Index<_i>) {
332290 if (!*_res && index_ == _i) {
333- * _res = _f (get_alternative<_i>());
291+ _res-> emplace ( _f (get_alternative<_i>() ));
334292 }
335293 };
336294 (visit_one (_f, _res, Index<_is>{}), ...);
@@ -343,7 +301,7 @@ class Variant {
343301 std::optional<ResultType>* _res,
344302 Index<_i>) {
345303 if (!*_res && index_ == _i) {
346- * _res = _f (get_alternative<_i>());
304+ _res-> emplace ( _f (get_alternative<_i>() ));
347305 }
348306 };
349307 (visit_one (_f, _res, Index<_is>{}), ...);
@@ -356,7 +314,7 @@ class Variant {
356314 std::optional<ResultType>* _res,
357315 Index<_i>) {
358316 if (!*_res && index_ == _i) {
359- * _res = _f (get_alternative<_i>());
317+ _res-> emplace ( _f (get_alternative<_i>() ));
360318 }
361319 };
362320 (visit_one (_f, _res, Index<_is>{}), ...);
@@ -369,7 +327,7 @@ class Variant {
369327 std::optional<ResultType>* _res,
370328 Index<_i>) {
371329 if (!*_res && index_ == _i) {
372- * _res = _f (get_alternative<_i>());
330+ _res-> emplace ( _f (get_alternative<_i>() ));
373331 }
374332 };
375333 (visit_one (_f, _res, Index<_is>{}), ...);
@@ -460,6 +418,11 @@ class Variant {
460418 alignas (AlternativeTypes...) DataType data_;
461419};
462420
421+ template <typename V>
422+ concept VariantBased = requires (std::decay_t <V> v) {
423+ []<typename ... Args>(Variant<Args...> const &) {}(v);
424+ };
425+
463426template <class T , class ... Types>
464427constexpr T* get_if (Variant<Types...>* _v) noexcept {
465428 const auto get = [](auto & _v) -> T* {
0 commit comments