12 #include "_detail/variant_helper.hpp" 40 template <
size_t I,
class T>
47 template <
class... TS>
55 # pragma region friend access 56 template <
size_t I,
class... ETS>
58 template <
size_t I,
class... ETS>
60 template <
size_t I,
class... ETS>
62 template <
class... ETS>
64 template <
class... ETS>
68 static const constexpr
size_t StorageSize = Detail::Max<
sizeof(TS)...>;
69 static const constexpr
size_t StorageAlignment = Detail::Max<
alignof(TS)...>;
78 void delete_if_valid() noexcept;
83 const constexpr
auto exactIndex = Detail::IndexOf<T, TS...>;
84 const constexpr
auto newIndex = exactIndex !=
variant_npos ? exactIndex : Detail::IndexOfAssignable<T, TS...>;
85 static_assert(newIndex !=
variant_npos,
"CVB: assigned type not compatible to alternatives list");
87 using NewT = Detail::TypeAt<newIndex, TS...>;
90 new(&data_) NewT(std::forward<T>(value));
101 new(&data_) Detail::TypeAt<0, TS...>{};
143 template <class T, typename std::enable_if<!std::is_same<T, variant &>::value,
int>::type = 0>
147 set(std::forward<T>(value));
161 template <class T, typename std::enable_if<!std::is_same<T, variant &>::value,
int>::type = 0>
164 set(std::forward<T>(value));
176 template <
size_t I,
class... ARGS>
186 template <
class T,
class... ARGS>
189 const constexpr
auto newIndex = Detail::IndexOf<T, TS...>;
190 static_assert(newIndex !=
variant_npos,
"CVB: assigned type not in alternatives list");
192 return emplace<newIndex>(std::forward<ARGS>(args)...);
198 size_t index() const noexcept {
return index_; }
215 #pragma region monostate 254 #pragma region variant_alternative 256 template <
size_t I,
class... TS>
259 using type = Detail::TypeAt<I, TS...>;
262 template <
size_t I,
class T>
265 template <
size_t I,
class T>
266 struct variant_alternative<I, const T> : variant_alternative<I, typename std::remove_reference<T>::type> {};
268 template <
size_t I,
class T>
269 struct variant_alternative<I, volatile T> : variant_alternative<I, typename std::remove_reference<T>::type> {};
271 template <
size_t I,
class T>
272 struct variant_alternative<I, const volatile T> : variant_alternative<I, typename std::remove_reference<T>::type> {};
277 template <
size_t I,
class T>
282 #pragma region variant_size 291 template <
class... TS>
301 struct variant_size<volatile T> : variant_size<typename std::remove_reference<T>::type> {};
304 struct variant_size<const volatile T> : variant_size<typename std::remove_reference<T>::type> {};
315 #pragma region get<I> 333 template <
size_t I,
class... TS>
336 static_assert(I <
sizeof...(TS),
"CVB: alternative index out of range");
347 template <
size_t I,
class... TS>
350 static_assert(I <
sizeof...(TS),
"CVB: alternative index out of range");
361 template <
size_t I,
class... TS>
364 static_assert(I <
sizeof...(TS),
"CVB: alternative index out of range");
373 #pragma region get<T> 391 template <
class T,
class... TS>
394 static const constexpr
size_t index = Detail::IndexOf<T, TS...>;
395 static_assert(index !=
variant_npos,
"CVB: type not in alternatives list");
397 return get<index>(var);
404 template <
class T,
class... TS>
407 static const constexpr
size_t index = Detail::IndexOf<T, TS...>;
408 static_assert(index !=
variant_npos,
"CVB: type not in alternatives list");
410 return get<index>(var);
417 template <
class T,
class... TS>
420 static const constexpr
size_t index = Detail::IndexOf<T, TS...>;
421 static_assert(index !=
variant_npos,
"CVB: type not in alternatives list");
423 return get<index>(std::move(var));
428 #pragma region get_if<I> 441 template <
size_t I,
class... TS>
444 if(!pvar || pvar->index() != I)
447 return &get<I>(*pvar);
454 template <
size_t I,
class... TS>
457 if(!pvar || pvar->index() != I)
460 return &get<I>(*pvar);
465 #pragma region get_if<I> 483 template <
class T,
class... TS>
486 static const constexpr
size_t index = Detail::IndexOf<T, TS...>;
487 static_assert(index !=
variant_npos,
"CVB: type not in alternatives list");
489 return get_if<index>(pvar);
496 template <
class T,
class... TS>
499 static const constexpr
size_t index = Detail::IndexOf<T, TS...>;
500 static_assert(index !=
variant_npos,
"CVB: type not in alternatives list");
502 return get_if<index>(pvar);
507 #pragma region holds_alternative 517 template <
class T,
class... TS>
520 static_assert(Detail::Contains<T, TS...>,
"CVB: alternative is not contained in variant.");
521 return var.index() == Detail::IndexOf<T, TS...>;
528 #pragma region VisitHelper 534 template <
class T,
size_t COUNT,
size_t I = 0>
537 template <
class VISITOR,
class VARIANT>
538 T operator()(VISITOR &&visitor, VARIANT &&var)
const 541 return visitor(get<I>(std::forward<VARIANT>(var)));
543 return VisitHelper1<T, COUNT, I + 1>{}(std::forward<VISITOR>(visitor), std::forward<VARIANT>(var));
547 template <
class T,
size_t COUNT>
548 struct VisitHelper1<T, COUNT, COUNT>
550 template <
class VISITOR,
class VARIANT>
551 T operator()(VISITOR &&, VARIANT &&)
const 553 throw bad_variant_access{};
572 template <
class VISITOR,
class VARIANT>
573 auto visit(VISITOR &&visitor, VARIANT &&var) -> decltype(visitor(get<0>(var)))
575 using RESULT = decltype(visitor(get<0>(var)));
576 using HELPER = Detail::VisitHelper1<RESULT, variant_alternatives_size_v<VARIANT>>;
578 return HELPER{}(std::forward<VISITOR>(visitor), std::forward<VARIANT>(var));
583 #pragma region comparison operators 595 template <
class... TS>
612 template <
class... TS>
615 return !(lhs == rhs);
631 template <
class... TS>
638 || (lhs.
index() == rhs.
index() && visit(Detail::VariantLess{&lhs.data_}, rhs))
650 template <
class... TS>
665 template <
class... TS>
680 template <
class... TS>
688 #pragma region variant copy 690 template <
class... TS>
694 visit(Detail::VariantCopier{&data_}, rhs);
697 template <
class... TS>
703 visit(Detail::VariantCopier{&data_}, rhs);
712 #pragma region variant move 714 template <
class... TS>
718 visit(Detail::VariantMover{&data_}, std::move(rhs));
719 rhs.delete_if_valid();
722 template <
class... TS>
728 visit(Detail::VariantMover{&data_}, std::move(rhs));
730 rhs.delete_if_valid();
738 #pragma region variant swap 740 template <
class... TS>
745 auto old = std::move(*
this);
746 *
this = std::move(other);
747 other = std::move(old);
752 #pragma region variant::delete_if_valid 755 template <
class... TS>
758 if(!valueless_by_exception())
760 visit(Detail::VariantDestructor{}, *
this);
767 #pragma region variant::emplace<I> 769 template <
class... TS>
770 template <
size_t I,
class... ARGS>
773 using NewT = Detail::TypeAt<I, TS...>;
776 auto result =
new(&data_) NewT(std::forward<ARGS>(args)...);
793 template <
class... TS>
This class is a replacement for C++17 std::variant.
Definition: variant.hpp:48
static const constexpr size_t variant_npos
Returned by variant::index() on invalid state.
Definition: variant.hpp:33
constexpr bool operator>=(monostate, monostate) noexcept
Definition: variant.hpp:242
variant() noexcept
Default ctor creating a variant with default value of the first alternative type.
Definition: variant.hpp:98
constexpr bool operator!=(monostate, monostate) noexcept
Definition: variant.hpp:250
bool operator >(const variant< TS... > &lhs, const variant< TS... > &rhs)
Greater-than operator for Shims::variant object.
Definition: variant.hpp:666
constexpr bool operator==(monostate, monostate) noexcept
Definition: variant.hpp:246
std::add_pointer< const T >::type get_if(const variant< TS... > *pvar) noexcept
Tries to get the value of the given Shims::variant pointer pvar as the alternative with type T.
Definition: variant.hpp:484
bool operator !=(const variant< TS... > &lhs, const variant< TS... > &rhs)
Inequality operator for Shims::variant objects.
Definition: variant.hpp:613
bad_variant_access()=default
Default ctor.
std::add_pointer< variant_alternative_t< I, variant< TS... > > >::type get_if(variant< TS... > *pvar) noexcept
Tries to get the value of the given Shims::variant pointer pvar as the alternative with index I.
Definition: variant.hpp:455
bool operator >=(const variant< TS... > &lhs, const variant< TS... > &rhs)
Greater-than or equal operator for Shims::variant object.
Definition: variant.hpp:681
variant_alternative_t< I, variant< TS... > > get(variant< TS... > &&var)
Gets the value of the given Shims::variant var as the alternative with index I.
Definition: variant.hpp:362
void swap(variant &other)
Swaps the content of this variant with the other one.
Definition: variant.hpp:741
~variant() noexcept
Destructor.
Definition: variant.hpp:105
std::add_pointer< T >::type get_if(variant< TS... > *pvar) noexcept
Tries to get the value of the given Shims::variant pointer pvar as the alternative with type T.
Definition: variant.hpp:497
T & get(variant< TS... > &var)
Gets the value of the given Shims::variant var as the alternative with type T.
Definition: variant.hpp:405
constexpr bool operator<=(monostate, monostate) noexcept
Definition: variant.hpp:238
constexpr bool operator<(monostate, monostate) noexcept
Definition: variant.hpp:230
Root namespace for the Image Manager interface.
Definition: version.hpp:11
const variant_alternative_t< I, variant< TS... > > & get(const variant< TS... > &var)
Gets the value of the given Shims::variant var as the alternative with index I.
Definition: variant.hpp:334
typename variant_alternative< I, T >::type variant_alternative_t
Helper type alias for Shims::variant_alternative.
Definition: variant.hpp:278
variant_alternative< I, variant< TS... > >::type & emplace(ARGS &&... args)
Emplaces an object as alternative at index I.
Definition: variant.hpp:771
variant(T &&value)
Ctor from an object of supported type T.
Definition: variant.hpp:144
bool holds_alternative(const variant< TS... > &var) noexcept
Gets whether the Shims::variant var holds an instance of type T.
Definition: variant.hpp:518
Error when accessing not set alternative.
Definition: variant.hpp:25
Get the number of alternatives in a variant.
Definition: variant.hpp:289
constexpr bool operator>(monostate, monostate) noexcept
Definition: variant.hpp:234
size_t index() const noexcept
Gets the zero-based index of the alternative held by this instance.
Definition: variant.hpp:198
T & emplace(ARGS &&... args)
Emplaces an object as a type T.
Definition: variant.hpp:187
T get(variant< TS... > &&var)
Gets the value of the given Shims::variant var as the alternative with type T.
Definition: variant.hpp:418
variant & operator=(const variant &rhs)
Copy operator.
Definition: variant.hpp:698
const T & get(const variant< TS... > &var)
Gets the value of the given Shims::variant var as the alternative with type T.
Definition: variant.hpp:392
auto visit(VISITOR &&visitor, VARIANT &&var) -> decltype(visitor(get< 0 >(var)))
Visits the given Shims::variant var. Cvb::Shims::visit can only visit one variant (not multiple like ...
Definition: variant.hpp:573
Compile-time index access to the type of the alternatives at index I.
Definition: variant.hpp:41
Unit type intended for use as a well-behaved empty alternative in Shims::variant.
Definition: variant.hpp:226
variant_alternative_t< I, variant< TS... > > & get(variant< TS... > &var)
Gets the value of the given Shims::variant var as the alternative with index I.
Definition: variant.hpp:348
bool valueless_by_exception() const noexcept
Returns false only if this instance holds a value.
Definition: variant.hpp:212