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>)
115 template <
typename T>
118 and not is_same_v<remove_cvref_t<T>,
variant>
119 and not detail::is_in_place_index<remove_cvref_t<T>>
120 and not detail::is_in_place_type<remove_cvref_t<T>>
121 and is_constructible_v<detail::variant_alternative_selector_t<T, Ts...>, T>
125 :
variant(in_place_type<detail::variant_alternative_selector_t<T, Ts...>>,
etl::forward<T>(t))
129 template <size_t I,
typename... Args>
130 requires((I <
sizeof...(Ts))
and is_constructible_v<variant_alternative_t<I,
variant>, Args...>)
132 : _index(
static_cast<index_type>(I))
133 , _union(index_v<I>,
etl::forward<Args>(args)...)
137 template <
typename T,
typename... Args>
138 requires(is_constructible_v<T, Args...>
and mpl::count_v<remove_cvref_t<T>,
mpl::
list<Ts...>> == 1)
146 constexpr variant(
variant const& other)
noexcept((...
and etl::is_nothrow_copy_constructible_v<Ts>))
147 requires((...
and etl::is_copy_constructible_v<Ts>)
and !(...
and etl::is_trivially_copy_constructible_v<Ts>))
148 :
variant(other, copy_move_tag{})
154 constexpr variant(
variant&& other)
noexcept((...
and is_nothrow_move_constructible_v<Ts>))
155 requires((...
and is_move_constructible_v<Ts>)
and not(...
and is_trivially_move_constructible_v<Ts>))
166 (...
and detail::variant_copy_assignable<Ts>)
and not(...
and detail::variant_trivially_copy_assignable<Ts>)
179 (...
and detail::variant_move_assignable<Ts>)
and !(...
and detail::variant_trivially_move_assignable<Ts>)
182 assign(
etl::move(other));
186 template <
typename T>
188 not is_same_v<remove_cvref_t<T>,
variant>
189 and is_assignable_v<detail::variant_alternative_selector_t<T, Ts...>&, T>
190 and is_assignable_v<detail::variant_alternative_selector_t<T, Ts...>, T>
197 emplace<detail::variant_alternative_selector_t<T, Ts...>>(
etl::forward<T>(t));
202 requires(...
and is_trivially_destructible_v<Ts>)
213 return static_cast<size_t>(_index);
219 constexpr auto operator[](index_constant<I> index) & ->
auto&
221 static_assert(I <
sizeof...(Ts));
222 TETL_PRECONDITION(I == index());
223 return _union[index];
229 constexpr auto operator[](index_constant<I> index)
const& ->
auto const&
231 static_assert(I <
sizeof...(Ts));
232 TETL_PRECONDITION(I == index());
233 return _union[index];
239 constexpr auto operator[](index_constant<I> index) && ->
auto&&
241 static_assert(I <
sizeof...(Ts));
242 TETL_PRECONDITION(I == index());
243 return etl::move(_union)[index];
249 constexpr auto operator[](index_constant<I> index)
const&& ->
auto const&&
251 static_assert(I <
sizeof...(Ts));
252 TETL_PRECONDITION(I == index());
253 return etl::move(_union)[index];
256 template <
typename T,
typename... Args>
257 requires(is_constructible_v<T, Args...>
and mpl::count_v<T,
mpl::
list<Ts...>> == 1)
258 constexpr auto emplace(Args&&... args) ->
auto&
261 return replace(index_v<
mpl::index_of_v<T,
mpl::
list<Ts...>>>,
etl::forward<Args>(args)...);
264 template <size_t I,
typename... Args>
265 requires is_constructible_v<
mpl::at_t<I,
mpl::
list<Ts...>>, Args...>
266 constexpr auto emplace(Args&&... args) ->
auto&
269 return replace(index_v<I>,
etl::forward<Args>(args)...);
278 if (lhs.index() != rhs.index()) {
281 return etl::visit(detail::make_variant_compare_op(
etl::
equal_to()), lhs, rhs);
291 if (lhs.index() < rhs.index()) {
294 if (lhs.index() > rhs.index()) {
298 return etl::visit(detail::make_variant_compare_op(
etl::
less()), lhs, rhs);
308 if (lhs.index() < rhs.index()) {
311 if (lhs.index() > rhs.index()) {
315 return etl::visit(detail::make_variant_compare_op(
etl::
less_equal()), lhs, rhs);
325 if (lhs.index() > rhs.index()) {
328 if (lhs.index() < rhs.index()) {
332 return etl::visit(detail::make_variant_compare_op(
etl::
greater()), lhs, rhs);
342 if (lhs.index() > rhs.index()) {
345 if (lhs.index() < rhs.index()) {
353 struct copy_move_tag { };
355 template <
typename Other>
356 constexpr variant(Other&& other, [[maybe_unused]] copy_move_tag tag)
360 etl::visit_with_index([&](
auto param) {
361 replace(param.index,
etl::move(param).value());
362 },
etl::forward<Other>(other));
365 template <
typename Other>
366 constexpr auto assign(Other&& other) ->
void
368 etl::visit_with_index([&](
auto lhs,
auto rhs) {
369 if constexpr (lhs.index == rhs.index) {
370 lhs.value() =
etl::move(rhs.value());
373 replace(rhs.index,
etl::move(rhs.value()));
375 }, *
this,
etl::forward<Other>(other));
378 template <
typename... Args>
379 constexpr auto replace(
auto index, Args&&... args) ->
auto&
381 etl::construct_at(
etl::addressof(_union), index,
etl::forward<Args>(args)...);
382 _index =
static_cast<index_type>(index.value);
383 return (*
this)[index];
386 constexpr auto destroy() ->
void
388 etl::visit([](
auto& v) {
etl::destroy_at(
etl::addressof(v)); }, *
this);
398template <
typename T,
typename... Ts>
401 static_assert(
mpl::count_v<T,
mpl::
list<Ts...>> == 1);
402 return v.index() ==
mpl::index_of_v<T,
mpl::
list<Ts...>>;
408template <size_t I,
typename... Ts>
411 static_assert(I <
sizeof...(Ts));
412 TETL_PRECONDITION(I == v.index());
413 return v[index_v<I>];
419template <size_t I,
typename... Ts>
422 static_assert(I <
sizeof...(Ts));
423 TETL_PRECONDITION(I == v.index());
424 return v[index_v<I>];
430template <size_t I,
typename... Ts>
433 static_assert(I <
sizeof...(Ts));
434 TETL_PRECONDITION(I == v.index());
435 return etl::move(v)[index_v<I>];
441template <size_t I,
typename... Ts>
444 static_assert(I <
sizeof...(Ts));
445 TETL_PRECONDITION(I == v.index());
446 return etl::move(v)[index_v<I>];
453template <size_t I,
typename... Ts>
456 static_assert(I <
sizeof...(Ts));
457 if (pv ==
nullptr or pv->index() != I) {
460 return etl::addressof(
etl::unchecked_get<I>(*pv));
467template <size_t I,
typename... Ts>
469 -> add_pointer_t<variant_alternative_t<I,
variant<Ts...>>
const>
471 static_assert(I <
sizeof...(Ts));
472 if (pv ==
nullptr or pv->index() != I) {
475 return etl::addressof(
etl::unchecked_get<I>(*pv));
480template <
typename T,
typename... Ts>
483 return etl::get_if<
mpl::index_of_v<T,
mpl::
list<Ts...>>>(pv);
488template <
typename T,
typename... Ts>
489constexpr auto get_if(
variant<Ts...>
const* pv)
noexcept -> add_pointer_t<T
const>
491 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:266
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:454
constexpr variant(in_place_type_t< T >, Args &&... args)
Definition variant.hpp:139
friend constexpr auto operator==(variant const &lhs, variant const &rhs) -> bool
Equality operator.
Definition variant.hpp:276
friend constexpr auto operator<=(variant const &lhs, variant const &rhs) -> bool
Less-equal operator.
Definition variant.hpp:306
constexpr variant(in_place_index_t< I >, Args &&... args)
Definition variant.hpp:131
constexpr variant(T &&t) noexcept(is_nothrow_constructible_v< detail::variant_alternative_selector_t< T, Ts... >, T >)
Definition variant.hpp:124
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:192
constexpr auto operator[](index_constant< I > index) &-> auto &
Returns a reference to the object stored in the variant.
Definition variant.hpp:219
constexpr auto operator[](index_constant< I > index) &&-> auto &&
Returns a reference to the object stored in the variant.
Definition variant.hpp:239
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:211
constexpr auto operator[](index_constant< I > index) const &-> auto const &
Returns a reference to the object stored in the variant.
Definition variant.hpp:229
friend constexpr auto operator<(variant const &lhs, variant const &rhs) -> bool
Less-than operator.
Definition variant.hpp:289
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:399
constexpr auto operator[](index_constant< I > index) const &&-> auto const &&
Returns a reference to the object stored in the variant.
Definition variant.hpp:249
constexpr auto operator=(variant const &) -> variant &=default
friend constexpr auto operator>=(variant const &lhs, variant const &rhs) -> bool
Greater-equal operator.
Definition variant.hpp:340
constexpr ~variant()
Definition variant.hpp:205
friend constexpr auto operator>(variant const &lhs, variant const &rhs) -> bool
Greater-than operator.
Definition variant.hpp:323
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:468
constexpr auto emplace(Args &&... args) -> auto &
Definition variant.hpp:258
Definition variadic_union.hpp:19