25#ifndef JOIN_CORE_VARIANT_HPP
26#define JOIN_CORE_VARIANT_HPP
60 using type = std::strong_ordering;
66 template <
typename... Ts>
67 using VariantOrdering = std::common_comparison_category_t<typename OrderingOf<Ts>::type...>;
72 template <
typename... Ts>
82 static void copy (std::size_t which,
const void* src,
void* dst)
84 static const CopyFunc table[] = {©Impl<Ts>...};
85 table[which](src, dst);
94 static void move (std::size_t which,
void* src,
void* dst)
96 static const MoveFunc table[] = {&moveImpl<Ts>...};
97 table[which](src, dst);
105 static void destroy (std::size_t which,
void* data)
107 static const DestroyFunc table[] = {&destroyImpl<Ts>...};
118 static bool equal (std::size_t which,
const void* a,
const void* b)
120 static const EqualFunc table[] = {&equalImpl<Ts>...};
121 return table[which](a, b);
131 template <
typename Ordering>
132 static Ordering
compare (std::size_t which,
const void* a,
const void* b)
134 static const CompareFunc<Ordering> table[] = {&compareImpl<Ordering, Ts>...};
135 return table[which](a, b);
140 using CopyFunc = void (*) (
const void*,
void*);
143 using MoveFunc = void (*) (
void*,
void*);
146 using DestroyFunc = void (*) (
void*);
149 using EqualFunc = bool (*) (
const void*,
const void*);
152 template <
typename Ordering>
153 using CompareFunc = Ordering (*) (
const void*,
const void*);
160 template <
typename T>
161 static void copyImpl (
const void* src,
void* dst)
163 new (dst) T (*
reinterpret_cast<const T*
> (src));
171 template <
typename T>
172 static void moveImpl (
void* src,
void* dst)
174 new (dst) T (std::move (*
reinterpret_cast<T*
> (src)));
181 template <
typename T>
182 static void destroyImpl (
void* data)
184 reinterpret_cast<T*
> (data)->~T ();
193 template <
typename T>
194 static bool equalImpl (
const void* a,
const void* b)
196 return *
reinterpret_cast<const T*
> (a) == *
reinterpret_cast<const T*
> (b);
205 template <
typename Ordering,
typename T>
206 static Ordering compareImpl (
const void* a,
const void* b)
208 if constexpr (std::is_null_pointer_v<T>)
210 return std::strong_ordering::equivalent;
214 return *
reinterpret_cast<const T*
> (a) <=> *
reinterpret_cast<const T*
> (b);
223 template <
typename... Ts>
227 static constexpr bool _trivial = (std::is_trivially_copyable_v<Ts> && ...);
230 static constexpr bool _defaultConstructible =
231 std::is_default_constructible_v<std::tuple_element_t<0, std::tuple<Ts...>>>;
234 static constexpr bool _copyConstructible = (std::is_copy_constructible_v<Ts> && ...);
237 static constexpr bool _moveConstructible = (std::is_move_constructible_v<Ts> && ...);
240 static constexpr bool _copyAssignable =
241 _copyConstructible && _moveConstructible && (std::is_copy_assignable_v<Ts> && ...);
244 static constexpr bool _moveAssignable = _moveConstructible && (std::is_move_assignable_v<Ts> && ...);
247 static_assert (0 <
sizeof...(Ts),
"Variant must have at least one alternative");
248 static_assert ((!std::is_void_v<Ts> && ...),
"Variant must have no void alternative");
249 static_assert ((!std::is_array_v<Ts> && ...),
"Variant must have no array alternative.");
250 static_assert ((!std::is_reference_v<Ts> && ...),
"Variant must have no reference alternative");
256 requires _defaultConstructible
266 requires (_trivial && _copyConstructible)
274 requires (!_trivial && _copyConstructible)
275 : _which (other._which)
285 requires (_trivial && _moveConstructible)
293 requires (!_trivial && _moveConstructible)
294 : _which (other._which)
303 template <
typename T,
typename Match =
match_t<T&&, Ts...>>
305 requires is_unique_v<Match, Ts...> && std::is_constructible_v<Match, T&&>
314 template <
typename T,
typename... Args>
315 constexpr explicit Variant (std::in_place_type_t<T>, Args&&... args)
316 requires is_unique_v<T, Ts...> && std::is_constructible_v<T, Args&&...>
325 template <
typename T,
typename Up,
typename... Args>
326 constexpr explicit Variant (std::in_place_type_t<T>, std::initializer_list<Up> il, Args&&... args)
327 requires is_unique_v<T, Ts...> && std::is_constructible_v<T, std::initializer_list<Up>&, Args&&...>
336 template <std::size_t I,
typename... Args>
337 constexpr explicit Variant (std::in_place_index_t<I>, Args&&... args)
338 requires std::is_constructible_v<std::tuple_element_t<I, std::tuple<Ts...>>, Args&&...>
341 new (storage ()) std::tuple_element_t<I, std::tuple<Ts...>> (std::forward<Args> (args)...);
348 template <std::size_t I,
typename Up,
typename... Args>
349 constexpr explicit Variant (std::in_place_index_t<I>, std::initializer_list<Up> il, Args&&... args)
350 requires std::is_constructible_v<std::tuple_element_t<I, std::tuple<Ts...>>, std::initializer_list<Up>&,
354 new (storage ()) std::tuple_element_t<I, std::tuple<Ts...>> (il, std::forward<Args> (args)...);
379 requires (_trivial && _copyAssignable)
388 requires (!_trivial && _copyAssignable)
401 requires (_trivial && _moveAssignable)
410 requires (!_trivial && _moveAssignable)
421 template <
typename T,
typename Match =
match_t<T&&, Ts...>>
423 requires is_unique_v<Match, Ts...> && std::is_constructible_v<Match, T&&>
433 template <
typename T>
434 constexpr bool is () const
444 template <std::
size_t I>
445 constexpr bool is () const
446 requires (I < sizeof...(Ts))
448 return (
index () == I);
455 template <
typename T,
typename... Args>
456 constexpr T&
set (Args&&... args)
457 requires is_unique_v<T, Ts...> && std::is_constructible_v<T, Args&&...>
466 template <
typename T,
typename Up,
typename... Args>
467 constexpr T&
set (std::initializer_list<Up> il, Args&&... args)
468 requires is_unique_v<T, Ts...> && std::is_constructible_v<T, std::initializer_list<Up>&, Args&&...>
477 template <std::size_t I,
typename... Args>
478 constexpr std::tuple_element_t<I, std::tuple<Ts...>>&
set (Args&&... args)
479 requires std::is_constructible_v<std::tuple_element_t<I, std::tuple<Ts...>>, Args&&...>
481 Variant tmp (std::in_place_index<I>, std::forward<Args> (args)...);
482 *
this = std::move (tmp);
490 template <std::size_t I,
class Up,
class... Args>
491 constexpr std::tuple_element_t<I, std::tuple<Ts...>>&
set (std::initializer_list<Up> il, Args&&... args)
492 requires std::is_constructible_v<std::tuple_element_t<I, std::tuple<Ts...>>, std::initializer_list<Up>&,
495 Variant tmp (std::in_place_index<I>, il, std::forward<Args> (args)...);
496 *
this = std::move (tmp);
504 template <
typename T>
510 throwException<std::bad_cast> ();
512 return *
reinterpret_cast<T*
> (storage ());
519 template <
typename T>
520 constexpr const T&
get () const
525 throwException<std::bad_cast> ();
527 return *
reinterpret_cast<const T*
> (storage ());
534 template <std::
size_t I>
535 constexpr std::tuple_element_t<I, std::tuple<Ts...>>&
get ()
536 requires (I <
sizeof...(Ts))
540 throwException<std::bad_cast> ();
542 return *
reinterpret_cast<std::tuple_element_t<I, std::tuple<Ts...
>>*> (storage ());
549 template <std::
size_t I>
550 constexpr const std::tuple_element_t<I, std::tuple<Ts...>>&
get () const
551 requires (I < sizeof...(Ts))
555 throwException<std::bad_cast> ();
557 return *
reinterpret_cast<const std::tuple_element_t<I, std::tuple<Ts...
>>*> (storage ());
564 template <
typename T>
572 return reinterpret_cast<T*
> (storage ());
579 template <
typename T>
587 return reinterpret_cast<const T*
> (storage ());
594 template <std::
size_t I>
595 constexpr std::tuple_element_t<I, std::tuple<Ts...>>*
getIf ()
596 requires (I <
sizeof...(Ts))
602 return reinterpret_cast<std::tuple_element_t<I, std::tuple<Ts...
>>*> (storage ());
609 template <std::
size_t I>
610 constexpr const std::tuple_element_t<I, std::tuple<Ts...>>*
getIf () const
611 requires (I < sizeof...(Ts))
617 return reinterpret_cast<const std::tuple_element_t<I, std::tuple<Ts...
>>*> (storage ());
624 constexpr std::size_t
index () const noexcept
626 if (_which >=
sizeof...(Ts))
628 __builtin_unreachable ();
639 if constexpr (_trivial)
641 std::swap (_data, other._data);
642 std::swap (_which, other._which);
646 alignas (Ts...)
unsigned char tmp[std::max ({
sizeof (Ts)...})];
653 std::swap (_which, other._which);
688 template <
typename... _Ts>
692 template <
typename... _Ts>
701 constexpr void* storage ()
703 return static_cast<void*
> (std::addressof (_data));
710 constexpr const void* storage ()
const
712 return static_cast<const void*
> (std::addressof (_data));
716 alignas (Ts...)
unsigned char _data[std::max ({
sizeof (Ts)...})];
728 template <
typename... Ts>
731 return lhs.
equal (rhs);
740 template <
typename... Ts>
751 template <
typename... Ts>
variant class.
Definition variant.hpp:225
constexpr T & set(std::initializer_list< Up > il, Args &&... args)
set the variable type of the object identified by type and assign it a value.
Definition variant.hpp:467
constexpr std::tuple_element_t< I, std::tuple< Ts... > > * getIf()
get the variable value address of the object type identified by index.
Definition variant.hpp:595
constexpr Variant(std::in_place_index_t< I >, Args &&... args)
constructs a variant with the alternative T specified by the index I.
Definition variant.hpp:337
constexpr const T & get() const
get the variable value of the object type identified by type.
Definition variant.hpp:520
constexpr bool is() const
check that the member type in use is the same than the one specified.
Definition variant.hpp:434
constexpr Variant()
default constructor.
Definition variant.hpp:255
constexpr Variant(Variant &&other)=default
move constructor.
constexpr const T * getIf() const
get the variable value address of the object type identified by type.
Definition variant.hpp:580
constexpr Variant(T &&t)
constructs a Variant holding the alternative selected by overload resolution.
Definition variant.hpp:304
constexpr std::tuple_element_t< I, std::tuple< Ts... > > & get()
get the variable value of the object type identified by index.
Definition variant.hpp:535
friend constexpr bool operator==(const Variant< _Ts... > &lhs, const Variant< _Ts... > &rhs)
constexpr const std::tuple_element_t< I, std::tuple< Ts... > > * getIf() const
get the variable value address of the object type identified by index.
Definition variant.hpp:610
constexpr Variant(std::in_place_type_t< T >, Args &&... args)
constructs a Variant with the specified alternative T.
Definition variant.hpp:315
constexpr std::size_t index() const noexcept
return the index of the alternative that is currently held by the variant.
Definition variant.hpp:624
constexpr T & set(Args &&... args)
set the variable type of the object identified by type and assign it a value.
Definition variant.hpp:456
friend constexpr details::VariantOrdering< _Ts... > operator<=>(const Variant< _Ts... > &lhs, const Variant< _Ts... > &rhs)
constexpr std::tuple_element_t< I, std::tuple< Ts... > > & set(Args &&... args)
set the variable type of the object identified by index and assign it a value.
Definition variant.hpp:478
constexpr Variant(const Variant &other)
copy constructor.
Definition variant.hpp:273
constexpr T & get()
get the variable value of the object type identified by type.
Definition variant.hpp:505
constexpr auto compare(const Variant &rhs) const
three-way compare.
Definition variant.hpp:677
~Variant()=default
destroy the Variant instance.
constexpr std::tuple_element_t< I, std::tuple< Ts... > > & set(std::initializer_list< Up > il, Args &&... args)
set the variable type of the object identified by index and assign it a value.
Definition variant.hpp:491
constexpr Variant & operator=(const Variant &other)=default
copy assignment.
void swap(Variant &other) noexcept
swap this variant with another.
Definition variant.hpp:637
constexpr Variant(std::in_place_index_t< I >, std::initializer_list< Up > il, Args &&... args)
constructs a variant with the alternative T specified by the index I.
Definition variant.hpp:349
constexpr Variant(const Variant &other)=default
copy constructor.
constexpr Variant(Variant &&other) noexcept
move constructor.
Definition variant.hpp:292
constexpr T * getIf()
get the variable value address of the object type identified by type.
Definition variant.hpp:565
constexpr const std::tuple_element_t< I, std::tuple< Ts... > > & get() const
get the variable value of the object type identified by index.
Definition variant.hpp:550
constexpr Variant(std::in_place_type_t< T >, std::initializer_list< Up > il, Args &&... args)
constructs a Variant with the specified alternative T.
Definition variant.hpp:326
constexpr bool equal(const Variant &rhs) const
check if equal.
Definition variant.hpp:663
constexpr bool is() const
check that the index in use is the same than the one specified.
Definition variant.hpp:445
std::common_comparison_category_t< typename OrderingOf< Ts >::type... > VariantOrdering
comparison category of a variant.
Definition variant.hpp:67
Definition acceptor.hpp:32
bool operator==(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
compare if endpoints are equal.
Definition endpoint.hpp:196
constexpr std::size_t find_index_v
get element position in a parameter pack according its type.
Definition traits.hpp:81
Type & swap(Type &val)
swaps byte orders.
Definition utils.hpp:86
constexpr bool is_unique_v
check if a type only appears one time in a parameter pack.
Definition traits.hpp:100
typename std::invoke_result_t< overload< Ts... >, T >::type match_t
find a type that match one of the alternatives of a parameter pack.
Definition traits.hpp:75
std::strong_ordering operator<=>(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
three-way compare endpoints.
Definition endpoint.hpp:208
std::strong_ordering type
Definition variant.hpp:60
comparison category of an alternative.
Definition variant.hpp:51
helper class for variant operations using jump tables for O(1) dispatch.
Definition variant.hpp:74
static void copy(std::size_t which, const void *src, void *dst)
copy one object to another.
Definition variant.hpp:82
static bool equal(std::size_t which, const void *a, const void *b)
compare if two objects of the same alternative are equal.
Definition variant.hpp:118
static void destroy(std::size_t which, void *data)
destroy the currently active object.
Definition variant.hpp:105
static Ordering compare(std::size_t which, const void *a, const void *b)
three-way compare two objects of the same alternative.
Definition variant.hpp:132
static void move(std::size_t which, void *src, void *dst)
move one object to another.
Definition variant.hpp:94