4#ifndef TETL_VARIANT_VARIANT2_HPP
5#define TETL_VARIANT_VARIANT2_HPP
7#include <etl/_config/all.hpp>
9#include <etl/_contracts/check.hpp>
10#include <etl/_cstddef/size_t.hpp>
11#include <etl/_functional/equal_to.hpp>
12#include <etl/_functional/greater.hpp>
13#include <etl/_functional/greater_equal.hpp>
14#include <etl/_functional/less.hpp>
15#include <etl/_functional/less_equal.hpp>
16#include <etl/_memory/addressof.hpp>
17#include <etl/_memory/construct_at.hpp>
18#include <etl/_memory/destroy_at.hpp>
19#include <etl/_mpl/at.hpp>
20#include <etl/_mpl/count.hpp>
21#include <etl/_mpl/index_of.hpp>
22#include <etl/_type_traits/add_pointer.hpp>
23#include <etl/_type_traits/index_constant.hpp>
24#include <etl/_type_traits/is_assignable.hpp>
25#include <etl/_type_traits/is_constructible.hpp>
26#include <etl/_type_traits/is_copy_assignable.hpp>
27#include <etl/_type_traits/is_copy_constructible.hpp>
28#include <etl/_type_traits/is_default_constructible.hpp>
29#include <etl/_type_traits/is_move_assignable.hpp>
30#include <etl/_type_traits/is_move_constructible.hpp>
31#include <etl/_type_traits/is_nothrow_assignable.hpp>
32#include <etl/_type_traits/is_nothrow_constructible.hpp>
33#include <etl/_type_traits/is_nothrow_copy_assignable.hpp>
34#include <etl/_type_traits/is_nothrow_copy_constructible.hpp>
35#include <etl/_type_traits/is_nothrow_default_constructible.hpp>
36#include <etl/_type_traits/is_nothrow_move_assignable.hpp>
37#include <etl/_type_traits/is_nothrow_move_constructible.hpp>
38#include <etl/_type_traits/is_same.hpp>
39#include <etl/_type_traits/is_trivially_copy_assignable.hpp>
40#include <etl/_type_traits/is_trivially_copy_constructible.hpp>
41#include <etl/_type_traits/is_trivially_move_assignable.hpp>
42#include <etl/_type_traits/is_trivially_move_constructible.hpp>
43#include <etl/_type_traits/remove_cvref.hpp>
44#include <etl/_type_traits/smallest_size_t.hpp>
45#include <etl/_utility/forward.hpp>
46#include <etl/_utility/in_place_index.hpp>
47#include <etl/_utility/in_place_type.hpp>
48#include <etl/_utility/unreachable.hpp>
49#include <etl/_variant/variadic_union.hpp>
50#include <etl/_variant/variant_alternative.hpp>
51#include <etl/_variant/variant_alternative_selector.hpp>
52#include <etl/_variant/variant_fwd.hpp>
53#include <etl/_variant/variant_size.hpp>
54#include <etl/_variant/visit.hpp>
61concept variant_copy_assignable = is_copy_constructible_v<T>
and is_copy_assignable_v<T>;
64concept variant_trivially_copy_assignable = is_trivially_copy_constructible_v<T>
and is_trivially_copy_assignable_v<T>;
67concept variant_move_assignable = is_move_constructible_v<T>
and is_move_assignable_v<T>;
70concept variant_trivially_move_assignable = is_trivially_move_constructible_v<T>
and is_trivially_move_assignable_v<T>;
73inline constexpr auto is_in_place_index =
false;
76inline constexpr auto is_in_place_index<in_place_index_t<I>> =
true;
79inline constexpr auto is_in_place_type =
false;
82inline constexpr auto is_in_place_type<in_place_type_t<T>> =
true;
84constexpr auto make_variant_compare_op(
auto op)
86 return [op](
auto const& l,
auto const& r) ->
bool {
87 if constexpr (etl::is_same_v<
decltype(l),
decltype(r)>) {
98template <
typename... Ts>
102 static_assert((is_nothrow_move_constructible_v<Ts>
and ...));
104 using index_type = smallest_size_t<
sizeof...(Ts)>;
105 using first_type =
mpl::at_t<0,
mpl::
list<Ts...>>;
108 constexpr variant()
noexcept(is_nothrow_default_constructible_v<first_type>)
109 requires(is_default_constructible_v<first_type>)
114 template <
typename T>
117 and not is_same_v<remove_cvref_t<T>,
variant>
118 and not detail::is_in_place_index<remove_cvref_t<T>>
119 and not detail::is_in_place_type<remove_cvref_t<T>>
120 and is_constructible_v<detail::variant_alternative_selector_t<T, Ts...>, T>
123 :
variant(in_place_type<detail::variant_alternative_selector_t<T, Ts...>>,
etl::forward<T>(t))
127 template <size_t I,
typename... Args>
128 requires((I <
sizeof...(Ts))
and is_constructible_v<variant_alternative_t<I,
variant>, Args...>)
130 : _index(
static_cast<index_type>(I))
131 , _union(index_v<I>,
etl::forward<Args>(args)...)
135 template <
typename T,
typename... Args>
136 requires(is_constructible_v<T, Args...>
and mpl::count_v<remove_cvref_t<T>,
mpl::
list<Ts...>> == 1)
144 constexpr variant(
variant const& other)
noexcept((...
and etl::is_nothrow_copy_constructible_v<Ts>))
145 requires((...
and etl::is_copy_constructible_v<Ts>)
and not(...
and etl::is_trivially_copy_constructible_v<Ts>))
146 :
variant(other, copy_move_tag{})
152 constexpr variant(
variant&& other)
noexcept((...
and is_nothrow_move_constructible_v<Ts>))
153 requires((...
and is_move_constructible_v<Ts>)
and not(...
and is_trivially_move_constructible_v<Ts>))
164 (...
and detail::variant_copy_assignable<Ts>)
and not(...
and detail::variant_trivially_copy_assignable<Ts>)
177 (...
and detail::variant_move_assignable<Ts>)
and not(...
and detail::variant_trivially_move_assignable<Ts>)
180 assign(
etl::move(other));
184 template <
typename T>
186 not is_same_v<remove_cvref_t<T>,
variant>
187 and is_assignable_v<detail::variant_alternative_selector_t<T, Ts...>&, T>
188 and is_assignable_v<detail::variant_alternative_selector_t<T, Ts...>, T>
195 emplace<detail::variant_alternative_selector_t<T, Ts...>>(
etl::forward<T>(t));
200 requires(...
and is_trivially_destructible_v<Ts>)
211 return static_cast<size_t>(_index);
217 constexpr auto operator[](index_constant<I> index) & ->
auto&
219 static_assert(I <
sizeof...(Ts));
220 TETL_PRECONDITION(I == index());
221 return _union[index];
227 constexpr auto operator[](index_constant<I> index)
const& ->
auto const&
229 static_assert(I <
sizeof...(Ts));
230 TETL_PRECONDITION(I == index());
231 return _union[index];
237 constexpr auto operator[](index_constant<I> index) && ->
auto&&
239 static_assert(I <
sizeof...(Ts));
240 TETL_PRECONDITION(I == index());
241 return etl::move(_union)[index];
247 constexpr auto operator[](index_constant<I> index)
const&& ->
auto const&&
249 static_assert(I <
sizeof...(Ts));
250 TETL_PRECONDITION(I == index());
251 return etl::move(_union)[index];
254 template <
typename T,
typename... Args>
255 requires(is_constructible_v<T, Args...>
and mpl::count_v<T,
mpl::
list<Ts...>> == 1)
256 constexpr auto emplace(Args&&... args) ->
auto&
259 return replace(index_v<
mpl::index_of_v<T,
mpl::
list<Ts...>>>,
etl::forward<Args>(args)...);
262 template <size_t I,
typename... Args>
263 requires is_constructible_v<
mpl::at_t<I,
mpl::
list<Ts...>>, Args...>
264 constexpr auto emplace(Args&&... args) ->
auto&
267 return replace(index_v<I>,
etl::forward<Args>(args)...);
276 if (lhs.index() != rhs.index()) {
279 return etl::visit(detail::make_variant_compare_op(
etl::
equal_to()), lhs, rhs);
289 if (lhs.index() < rhs.index()) {
292 if (lhs.index() > rhs.index()) {
296 return etl::visit(detail::make_variant_compare_op(
etl::
less()), lhs, rhs);
306 if (lhs.index() < rhs.index()) {
309 if (lhs.index() > rhs.index()) {
313 return etl::visit(detail::make_variant_compare_op(
etl::
less_equal()), lhs, rhs);
323 if (lhs.index() > rhs.index()) {
326 if (lhs.index() < rhs.index()) {
330 return etl::visit(detail::make_variant_compare_op(
etl::
greater()), lhs, rhs);
340 if (lhs.index() > rhs.index()) {
343 if (lhs.index() < rhs.index()) {
351 struct copy_move_tag { };
353 template <
typename Other>
354 constexpr variant(Other&& other, [[maybe_unused]] copy_move_tag tag)
358 etl::visit_with_index([&](
auto param) {
359 replace(param.index,
etl::move(param).value());
360 },
etl::forward<Other>(other));
363 template <
typename Other>
364 constexpr auto assign(Other&& other) ->
void
366 etl::visit_with_index([&](
auto lhs,
auto rhs) {
367 if constexpr (lhs.index == rhs.index) {
368 lhs.value() =
etl::move(rhs.value());
371 replace(rhs.index,
etl::move(rhs.value()));
373 }, *
this,
etl::forward<Other>(other));
376 template <
typename... Args>
377 constexpr auto replace(
auto index, Args&&... args) ->
auto&
379 etl::construct_at(
etl::addressof(_union), index,
etl::forward<Args>(args)...);
380 _index =
static_cast<index_type>(index.value);
381 return (*
this)[index];
384 constexpr auto destroy() ->
void
386 etl::visit([](
auto& v) {
etl::destroy_at(
etl::addressof(v)); }, *
this);
396template <
typename T,
typename... Ts>
399 static_assert(
mpl::count_v<T,
mpl::
list<Ts...>> == 1);
400 return v.index() ==
mpl::index_of_v<T,
mpl::
list<Ts...>>;
406template <size_t I,
typename... Ts>
409 static_assert(I <
sizeof...(Ts));
410 TETL_PRECONDITION(I == v.index());
411 return v[index_v<I>];
417template <size_t I,
typename... Ts>
420 static_assert(I <
sizeof...(Ts));
421 TETL_PRECONDITION(I == v.index());
422 return v[index_v<I>];
428template <size_t I,
typename... Ts>
431 static_assert(I <
sizeof...(Ts));
432 TETL_PRECONDITION(I == v.index());
433 return etl::move(v)[index_v<I>];
439template <size_t I,
typename... Ts>
442 static_assert(I <
sizeof...(Ts));
443 TETL_PRECONDITION(I == v.index());
444 return etl::move(v)[index_v<I>];
451template <size_t I,
typename... Ts>
454 static_assert(I <
sizeof...(Ts));
455 if (pv ==
nullptr or pv->index() != I) {
458 return etl::addressof(
etl::unchecked_get<I>(*pv));
465template <size_t I,
typename... Ts>
467 -> add_pointer_t<variant_alternative_t<I,
variant<Ts...>>
const>
469 static_assert(I <
sizeof...(Ts));
470 if (pv ==
nullptr or pv->index() != I) {
473 return etl::addressof(
etl::unchecked_get<I>(*pv));
478template <
typename T,
typename... Ts>
481 return etl::get_if<
mpl::index_of_v<T,
mpl::
list<Ts...>>>(pv);
486template <
typename T,
typename... Ts>
487constexpr auto get_if(
variant<Ts...>
const* pv)
noexcept -> add_pointer_t<T
const>
489 return etl::get_if<
mpl::index_of_v<T,
mpl::
list<Ts...>>>(pv);
Definition adjacent_find.hpp:9
constexpr auto unchecked_get(variant< Ts... > const &&v) -> auto const &&
constexpr auto unchecked_get(variant< Ts... > &v) -> auto &
constexpr auto unchecked_get(variant< Ts... > &&v) -> auto &&
constexpr auto unchecked_get(variant< Ts... > const &v) -> auto const &
constexpr auto get_if(variant< Types... > *pv) noexcept -> add_pointer_t< T >
constexpr auto get_if(variant< Types... > const *pv) noexcept -> add_pointer_t< T const >
Function object for performing comparisons. Unless specialised, invokes operator== on type T....
Definition equal_to.hpp:15
Function object for performing comparisons. Unless specialised, invokes operator>= on type T....
Definition greater_equal.hpp:15
Function object for performing comparisons. Unless specialised, invokes operator> on type T....
Definition greater.hpp:15
Disambiguation tags that can be passed to the constructors of etl::optional, etl::variant,...
Definition in_place_index.hpp:20
Disambiguation tags that can be passed to the constructors of etl::optional, etl::variant,...
Definition in_place_type.hpp:20
Function object for performing comparisons. Unless specialised, invokes operator<= on type T....
Definition less_equal.hpp:15
Function object for performing comparisons. Unless specialised, invokes operator< on type T....
Definition less.hpp:15
Definition uninitialized_union.hpp:9
Definition variant.hpp:99
constexpr variant(variant const &)=default
constexpr auto emplace(Args &&... args) -> auto &
Definition variant.hpp:264
constexpr auto get_if(variant< Ts... > *pv) noexcept -> add_pointer_t< variant_alternative_t< I, variant< Ts... > > >
If pv is not a null pointer and pv->index() == I, returns a pointer to the value stored in the varian...
Definition variant.hpp:452
constexpr variant(in_place_type_t< T >, Args &&... args)
Definition variant.hpp:137
friend constexpr auto operator==(variant const &lhs, variant const &rhs) -> bool
Equality operator.
Definition variant.hpp:274
friend constexpr auto operator<=(variant const &lhs, variant const &rhs) -> bool
Less-equal operator.
Definition variant.hpp:304
constexpr variant(in_place_index_t< I >, Args &&... args)
Definition variant.hpp:129
constexpr variant(T &&t) noexcept(is_nothrow_constructible_v< detail::variant_alternative_selector_t< T, Ts... >, T >)
Definition variant.hpp:122
constexpr auto operator=(T &&t) noexcept((is_nothrow_assignable_v< detail::variant_alternative_selector_t< T, Ts... > &, T > and is_nothrow_constructible_v< detail::variant_alternative_selector_t< T, Ts... >, T >)) -> variant &
Definition variant.hpp:190
constexpr auto operator[](index_constant< I > index) &-> auto &
Returns a reference to the object stored in the variant.
Definition variant.hpp:217
constexpr auto operator[](index_constant< I > index) &&-> auto &&
Returns a reference to the object stored in the variant.
Definition variant.hpp:237
constexpr auto operator=(variant &&) -> variant &=default
constexpr auto index() const noexcept -> size_t
Returns the zero-based index of the alternative that is currently held by the variant.
Definition variant.hpp:209
constexpr auto operator[](index_constant< I > index) const &-> auto const &
Returns a reference to the object stored in the variant.
Definition variant.hpp:227
friend constexpr auto operator<(variant const &lhs, variant const &rhs) -> bool
Less-than operator.
Definition variant.hpp:287
constexpr auto holds_alternative(variant< Ts... > const &v) noexcept -> bool
Checks if the variant v holds the alternative T. The call is ill-formed if T does not appear exactly ...
Definition variant.hpp:397
constexpr auto operator[](index_constant< I > index) const &&-> auto const &&
Returns a reference to the object stored in the variant.
Definition variant.hpp:247
constexpr auto operator=(variant const &) -> variant &=default
friend constexpr auto operator>=(variant const &lhs, variant const &rhs) -> bool
Greater-equal operator.
Definition variant.hpp:338
constexpr ~variant()
Definition variant.hpp:203
friend constexpr auto operator>(variant const &lhs, variant const &rhs) -> bool
Greater-than operator.
Definition variant.hpp:321
constexpr variant(variant &&)=default
constexpr auto get_if(variant< Ts... > const *pv) noexcept -> add_pointer_t< variant_alternative_t< I, variant< Ts... > > const >
If pv is not a null pointer and pv->index() == I, returns a pointer to the value stored in the varian...
Definition variant.hpp:466
constexpr auto emplace(Args &&... args) -> auto &
Definition variant.hpp:256
Definition variadic_union.hpp:19