21 #include <type_traits>
33 template <
typename T0,
typename T1,
typename SFINAE =
void>
53 new (&t0_) T0(other.t0_);
57 new (&t1_) T1(other.t1_);
72 new (&t0_) T0(std::move(other.t0_));
76 new (&t1_) T1(std::move(other.t1_));
115 template <
typename T0,
typename T1>
117 std::enable_if_t<std::is_trivially_destructible_v<T0> && std::is_trivially_destructible_v<T1>>> {
151 template <
typename T,
typename T0,
typename T1>
156 constexpr
static bool value = std::is_same_v<std::decay_t<T>, T0> || std::is_assignable_v<T0, T> ||
157 std::is_same_v<std::decay_t<T>, T1> || std::is_assignable_v<T1, T>;
168 template <
int I,
typename T0,
typename T1>
176 template <
typename T0,
typename T1>
189 template <
typename T0,
typename T1>
206 template <
typename T0,
typename T1>
237 template <typename T, typename SFINAE = std::enable_if_t<detail::is_variant_assignable<T, T0, T1>::value>>
240 if constexpr (std::is_same_v<std::decay_t<T>, T0> || std::is_assignable_v<T0, T>) {
242 new (&
storage_.t0_) T0(std::forward<T>(t));
243 }
else if constexpr (std::is_same_v<std::decay_t<T>, T1> || std::is_assignable_v<T1, T>) {
245 new (&
storage_.t1_) T1(std::forward<T>(t));
247 static_assert(
sizeof(T) < 0,
"Type not supported");
272 template <typename T, typename SFINAE = std::enable_if_t<detail::is_variant_assignable<T, T0, T1>::value>>
275 if constexpr (std::is_same_v<std::decay_t<T>, T0> || std::is_assignable_v<T0, T>) {
281 }
else if constexpr (std::is_same_v<std::decay_t<T>, T1> || std::is_assignable_v<T1, T>) {
288 static_assert(
sizeof(T) < 0,
"Type not supported");
306 if constexpr (I == 0) {
309 if constexpr (I == 1) {
318 if constexpr (I == 0) {
321 if constexpr (I == 1) {
337 template <
typename T,
typename T0,
typename T1>
340 if constexpr (std::is_same_v<T, T0>) {
342 }
else if constexpr (std::is_same_v<T, T1>) {
348 template <
typename T,
typename T0,
typename T1>
351 if constexpr (std::is_same_v<T, T0>) {
353 }
else if constexpr (std::is_same_v<T, T1>) {
364 template <
typename Visitor,
typename Variant>
365 constexpr decltype(
auto)
visit(Visitor visitor, Variant&& v)
367 if (v.index() == 0) {
368 return visitor(get<0>(v));
370 return visitor(get<1>(v));
380 template <
typename T,
typename T0,
typename T1>
383 if constexpr (std::is_same_v<T, T0>) {
384 return v.
index() == 0;
385 }
else if constexpr (std::is_same_v<T, T1>) {
386 return v.
index() == 1;
397 template <
typename T,
typename T0,
typename T1>
400 if constexpr (std::is_same_v<T, T0>) {
401 return (v->
index() == 0) ? &get<0>(*v) :
nullptr;
402 }
else if constexpr (std::is_same_v<T, T1>) {
403 return (v->
index() == 1) ? &get<1>(*v) :
nullptr;
409 template <
typename T,
typename T0,
typename T1>
412 if constexpr (std::is_same_v<T, T0>) {
413 return (v->
index() == 0) ? &get<0>(*v) :
nullptr;
414 }
else if constexpr (std::is_same_v<T, T1>) {
415 return (v->
index() == 1) ? &get<1>(*v) :
nullptr;
435 template <
typename T>
442 template <
typename T>
445 return visit([](
auto&& ptr) -> T& {
return *ptr; }, obj);
448 template <
typename T>
449 static const T& retrieve(
const MaybeOwningPointer<T>& obj)
451 return visit([](
auto&& ptr) ->
const T& {
return *ptr; }, obj);
Accelerator functionality.
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
T * get_if(variant< T0, T1 > *v)
Returns the member of requested type if it's active, otherwise nullptr.
bool holds_alternative(const variant< T0, T1 > &v)
Checks whether a variant's active member is of a certain type.
constexpr decltype(auto) visit(Visitor visitor, Variant &&v)
Applies a functor to the active variant element.
Determines if T can be assigned to a variant<T0, T1>
constexpr static bool value
If T can be assigned to the variant type.
T0 t0_
The storage for the first data type.
constexpr variant_storage()
Default constructor Default initializes the first member of the variant.
constexpr void clear()
No-op clear as both member types are trivially destructible.
T1 t1_
The storage for the second data type.
Storage abstraction to provide trivial destructor when both variant types are trivially destructible.
constexpr variant_storage(const variant_storage &other)
Copy constructor for nontrivial types Placement-new is required to correctly initialize the union.
constexpr variant_storage()
Default constructor Default initializes the first member of the variant.
constexpr variant_storage(variant_storage &&other)
Move constructor for nontrivial types Placement-new is required to correctly initialize the union.
~variant_storage()
Destroys the variant by calling the destructor of the active member.
constexpr void clear()
Resets the union by destroying the active member.
int index_
The index of the active member.
T0 type
The type of the first member.
T1 type
The type of the second member.
Obtains the type at index I of a variant<T0, T1>
A simple variant type that supports only two elements.
constexpr variant()=default
Default constructor - will default-initialize first member of the variant.
constexpr int index() const
Returns the index of the active variant member.
constexpr friend variant_alternative< I, T0, T1 >::type & get(variant &v)
Returns the variant member at the provided index.
constexpr variant(T &&t)
"Parameterized" constructor with which a value can be assigned
constexpr variant & operator=(variant &&)=default
Default assignment operator.
constexpr friend const variant_alternative< I, T0, T1 >::type & get(const variant &v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr variant & operator=(const variant &)=default
Default assignment operator.
constexpr variant(variant &&)=default
Default constructor.
detail::variant_storage< T0, T1 > storage_
Storage abstraction used to provide constexpr functionality when applicable.
constexpr variant & operator=(T &&t)
constexpr variant(const variant &)=default
Default constructor.