1aed8d94eSDimitry Andric// -*- C++ -*- 2aed8d94eSDimitry Andric//===------------------------------ variant -------------------------------===// 3aed8d94eSDimitry Andric// 4aed8d94eSDimitry Andric// The LLVM Compiler Infrastructure 5aed8d94eSDimitry Andric// 6aed8d94eSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 7aed8d94eSDimitry Andric// Source Licenses. See LICENSE.TXT for details. 8aed8d94eSDimitry Andric// 9aed8d94eSDimitry Andric//===----------------------------------------------------------------------===// 10aed8d94eSDimitry Andric 11aed8d94eSDimitry Andric#ifndef _LIBCPP_VARIANT 12aed8d94eSDimitry Andric#define _LIBCPP_VARIANT 13aed8d94eSDimitry Andric 14aed8d94eSDimitry Andric/* 15aed8d94eSDimitry Andric variant synopsis 16aed8d94eSDimitry Andric 17aed8d94eSDimitry Andricnamespace std { 18aed8d94eSDimitry Andric 19aed8d94eSDimitry Andric // 20.7.2, class template variant 20aed8d94eSDimitry Andric template <class... Types> 21aed8d94eSDimitry Andric class variant { 22aed8d94eSDimitry Andric public: 23aed8d94eSDimitry Andric 24aed8d94eSDimitry Andric // 20.7.2.1, constructors 25aed8d94eSDimitry Andric constexpr variant() noexcept(see below); 26*b5893f02SDimitry Andric variant(const variant&); // constexpr in C++20 27*b5893f02SDimitry Andric variant(variant&&) noexcept(see below); // constexpr in C++20 28aed8d94eSDimitry Andric 29aed8d94eSDimitry Andric template <class T> constexpr variant(T&&) noexcept(see below); 30aed8d94eSDimitry Andric 31aed8d94eSDimitry Andric template <class T, class... Args> 32aed8d94eSDimitry Andric constexpr explicit variant(in_place_type_t<T>, Args&&...); 33aed8d94eSDimitry Andric 34aed8d94eSDimitry Andric template <class T, class U, class... Args> 35aed8d94eSDimitry Andric constexpr explicit variant( 36aed8d94eSDimitry Andric in_place_type_t<T>, initializer_list<U>, Args&&...); 37aed8d94eSDimitry Andric 38aed8d94eSDimitry Andric template <size_t I, class... Args> 39aed8d94eSDimitry Andric constexpr explicit variant(in_place_index_t<I>, Args&&...); 40aed8d94eSDimitry Andric 41aed8d94eSDimitry Andric template <size_t I, class U, class... Args> 42aed8d94eSDimitry Andric constexpr explicit variant( 43aed8d94eSDimitry Andric in_place_index_t<I>, initializer_list<U>, Args&&...); 44aed8d94eSDimitry Andric 45aed8d94eSDimitry Andric // 20.7.2.2, destructor 46aed8d94eSDimitry Andric ~variant(); 47aed8d94eSDimitry Andric 48aed8d94eSDimitry Andric // 20.7.2.3, assignment 49*b5893f02SDimitry Andric variant& operator=(const variant&); // constexpr in C++20 50*b5893f02SDimitry Andric variant& operator=(variant&&) noexcept(see below); // constexpr in C++20 51aed8d94eSDimitry Andric 52aed8d94eSDimitry Andric template <class T> variant& operator=(T&&) noexcept(see below); 53aed8d94eSDimitry Andric 54aed8d94eSDimitry Andric // 20.7.2.4, modifiers 55aed8d94eSDimitry Andric template <class T, class... Args> 56540d2a8bSDimitry Andric T& emplace(Args&&...); 57aed8d94eSDimitry Andric 58aed8d94eSDimitry Andric template <class T, class U, class... Args> 59540d2a8bSDimitry Andric T& emplace(initializer_list<U>, Args&&...); 60aed8d94eSDimitry Andric 61aed8d94eSDimitry Andric template <size_t I, class... Args> 62540d2a8bSDimitry Andric variant_alternative_t<I, variant>& emplace(Args&&...); 63aed8d94eSDimitry Andric 64aed8d94eSDimitry Andric template <size_t I, class U, class... Args> 65540d2a8bSDimitry Andric variant_alternative_t<I, variant>& emplace(initializer_list<U>, Args&&...); 66aed8d94eSDimitry Andric 67aed8d94eSDimitry Andric // 20.7.2.5, value status 68aed8d94eSDimitry Andric constexpr bool valueless_by_exception() const noexcept; 69aed8d94eSDimitry Andric constexpr size_t index() const noexcept; 70aed8d94eSDimitry Andric 71aed8d94eSDimitry Andric // 20.7.2.6, swap 72aed8d94eSDimitry Andric void swap(variant&) noexcept(see below); 73aed8d94eSDimitry Andric }; 74aed8d94eSDimitry Andric 75aed8d94eSDimitry Andric // 20.7.3, variant helper classes 76aed8d94eSDimitry Andric template <class T> struct variant_size; // undefined 77aed8d94eSDimitry Andric 78aed8d94eSDimitry Andric template <class T> 7930785c0eSDimitry Andric inline constexpr size_t variant_size_v = variant_size<T>::value; 80aed8d94eSDimitry Andric 81aed8d94eSDimitry Andric template <class T> struct variant_size<const T>; 82aed8d94eSDimitry Andric template <class T> struct variant_size<volatile T>; 83aed8d94eSDimitry Andric template <class T> struct variant_size<const volatile T>; 84aed8d94eSDimitry Andric 85aed8d94eSDimitry Andric template <class... Types> 86aed8d94eSDimitry Andric struct variant_size<variant<Types...>>; 87aed8d94eSDimitry Andric 88aed8d94eSDimitry Andric template <size_t I, class T> struct variant_alternative; // undefined 89aed8d94eSDimitry Andric 90aed8d94eSDimitry Andric template <size_t I, class T> 91aed8d94eSDimitry Andric using variant_alternative_t = typename variant_alternative<I, T>::type; 92aed8d94eSDimitry Andric 93aed8d94eSDimitry Andric template <size_t I, class T> struct variant_alternative<I, const T>; 94aed8d94eSDimitry Andric template <size_t I, class T> struct variant_alternative<I, volatile T>; 95aed8d94eSDimitry Andric template <size_t I, class T> struct variant_alternative<I, const volatile T>; 96aed8d94eSDimitry Andric 97aed8d94eSDimitry Andric template <size_t I, class... Types> 98aed8d94eSDimitry Andric struct variant_alternative<I, variant<Types...>>; 99aed8d94eSDimitry Andric 10030785c0eSDimitry Andric inline constexpr size_t variant_npos = -1; 101aed8d94eSDimitry Andric 102aed8d94eSDimitry Andric // 20.7.4, value access 103aed8d94eSDimitry Andric template <class T, class... Types> 104aed8d94eSDimitry Andric constexpr bool holds_alternative(const variant<Types...>&) noexcept; 105aed8d94eSDimitry Andric 106aed8d94eSDimitry Andric template <size_t I, class... Types> 107aed8d94eSDimitry Andric constexpr variant_alternative_t<I, variant<Types...>>& 108aed8d94eSDimitry Andric get(variant<Types...>&); 109aed8d94eSDimitry Andric 110aed8d94eSDimitry Andric template <size_t I, class... Types> 111aed8d94eSDimitry Andric constexpr variant_alternative_t<I, variant<Types...>>&& 112aed8d94eSDimitry Andric get(variant<Types...>&&); 113aed8d94eSDimitry Andric 114aed8d94eSDimitry Andric template <size_t I, class... Types> 115aed8d94eSDimitry Andric constexpr variant_alternative_t<I, variant<Types...>> const& 116aed8d94eSDimitry Andric get(const variant<Types...>&); 117aed8d94eSDimitry Andric 118aed8d94eSDimitry Andric template <size_t I, class... Types> 119aed8d94eSDimitry Andric constexpr variant_alternative_t<I, variant<Types...>> const&& 120aed8d94eSDimitry Andric get(const variant<Types...>&&); 121aed8d94eSDimitry Andric 122aed8d94eSDimitry Andric template <class T, class... Types> 123aed8d94eSDimitry Andric constexpr T& get(variant<Types...>&); 124aed8d94eSDimitry Andric 125aed8d94eSDimitry Andric template <class T, class... Types> 126aed8d94eSDimitry Andric constexpr T&& get(variant<Types...>&&); 127aed8d94eSDimitry Andric 128aed8d94eSDimitry Andric template <class T, class... Types> 129aed8d94eSDimitry Andric constexpr const T& get(const variant<Types...>&); 130aed8d94eSDimitry Andric 131aed8d94eSDimitry Andric template <class T, class... Types> 132aed8d94eSDimitry Andric constexpr const T&& get(const variant<Types...>&&); 133aed8d94eSDimitry Andric 134aed8d94eSDimitry Andric template <size_t I, class... Types> 135aed8d94eSDimitry Andric constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> 136aed8d94eSDimitry Andric get_if(variant<Types...>*) noexcept; 137aed8d94eSDimitry Andric 138aed8d94eSDimitry Andric template <size_t I, class... Types> 139aed8d94eSDimitry Andric constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> 140aed8d94eSDimitry Andric get_if(const variant<Types...>*) noexcept; 141aed8d94eSDimitry Andric 142aed8d94eSDimitry Andric template <class T, class... Types> 143aed8d94eSDimitry Andric constexpr add_pointer_t<T> 144aed8d94eSDimitry Andric get_if(variant<Types...>*) noexcept; 145aed8d94eSDimitry Andric 146aed8d94eSDimitry Andric template <class T, class... Types> 147aed8d94eSDimitry Andric constexpr add_pointer_t<const T> 148aed8d94eSDimitry Andric get_if(const variant<Types...>*) noexcept; 149aed8d94eSDimitry Andric 150aed8d94eSDimitry Andric // 20.7.5, relational operators 151aed8d94eSDimitry Andric template <class... Types> 152aed8d94eSDimitry Andric constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); 153aed8d94eSDimitry Andric 154aed8d94eSDimitry Andric template <class... Types> 155aed8d94eSDimitry Andric constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); 156aed8d94eSDimitry Andric 157aed8d94eSDimitry Andric template <class... Types> 158aed8d94eSDimitry Andric constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); 159aed8d94eSDimitry Andric 160aed8d94eSDimitry Andric template <class... Types> 161aed8d94eSDimitry Andric constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); 162aed8d94eSDimitry Andric 163aed8d94eSDimitry Andric template <class... Types> 164aed8d94eSDimitry Andric constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); 165aed8d94eSDimitry Andric 166aed8d94eSDimitry Andric template <class... Types> 167aed8d94eSDimitry Andric constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); 168aed8d94eSDimitry Andric 169aed8d94eSDimitry Andric // 20.7.6, visitation 170aed8d94eSDimitry Andric template <class Visitor, class... Variants> 171aed8d94eSDimitry Andric constexpr see below visit(Visitor&&, Variants&&...); 172aed8d94eSDimitry Andric 173aed8d94eSDimitry Andric // 20.7.7, class monostate 174aed8d94eSDimitry Andric struct monostate; 175aed8d94eSDimitry Andric 176aed8d94eSDimitry Andric // 20.7.8, monostate relational operators 177aed8d94eSDimitry Andric constexpr bool operator<(monostate, monostate) noexcept; 178aed8d94eSDimitry Andric constexpr bool operator>(monostate, monostate) noexcept; 179aed8d94eSDimitry Andric constexpr bool operator<=(monostate, monostate) noexcept; 180aed8d94eSDimitry Andric constexpr bool operator>=(monostate, monostate) noexcept; 181aed8d94eSDimitry Andric constexpr bool operator==(monostate, monostate) noexcept; 182aed8d94eSDimitry Andric constexpr bool operator!=(monostate, monostate) noexcept; 183aed8d94eSDimitry Andric 184aed8d94eSDimitry Andric // 20.7.9, specialized algorithms 185aed8d94eSDimitry Andric template <class... Types> 186aed8d94eSDimitry Andric void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); 187aed8d94eSDimitry Andric 188aed8d94eSDimitry Andric // 20.7.10, class bad_variant_access 189aed8d94eSDimitry Andric class bad_variant_access; 190aed8d94eSDimitry Andric 191aed8d94eSDimitry Andric // 20.7.11, hash support 192aed8d94eSDimitry Andric template <class T> struct hash; 193aed8d94eSDimitry Andric template <class... Types> struct hash<variant<Types...>>; 194aed8d94eSDimitry Andric template <> struct hash<monostate>; 195aed8d94eSDimitry Andric 196aed8d94eSDimitry Andric} // namespace std 197aed8d94eSDimitry Andric 198aed8d94eSDimitry Andric*/ 199aed8d94eSDimitry Andric 200aed8d94eSDimitry Andric#include <__config> 201aed8d94eSDimitry Andric#include <__tuple> 202aed8d94eSDimitry Andric#include <array> 203aed8d94eSDimitry Andric#include <exception> 204aed8d94eSDimitry Andric#include <functional> 205aed8d94eSDimitry Andric#include <initializer_list> 206aed8d94eSDimitry Andric#include <new> 207aed8d94eSDimitry Andric#include <tuple> 208aed8d94eSDimitry Andric#include <type_traits> 209aed8d94eSDimitry Andric#include <utility> 210b2c7081bSDimitry Andric#include <limits> 211*b5893f02SDimitry Andric#include <version> 212aed8d94eSDimitry Andric 213aed8d94eSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 214aed8d94eSDimitry Andric#pragma GCC system_header 215aed8d94eSDimitry Andric#endif 216aed8d94eSDimitry Andric 217b2c7081bSDimitry Andric_LIBCPP_PUSH_MACROS 218b2c7081bSDimitry Andric#include <__undef_macros> 219b2c7081bSDimitry Andric 220aed8d94eSDimitry Andricnamespace std { // explicitly not using versioning namespace 221aed8d94eSDimitry Andric 222*b5893f02SDimitry Andricclass _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception { 223aed8d94eSDimitry Andricpublic: 224aed8d94eSDimitry Andric virtual const char* what() const _NOEXCEPT; 225aed8d94eSDimitry Andric}; 226aed8d94eSDimitry Andric 227aed8d94eSDimitry Andric} // namespace std 228aed8d94eSDimitry Andric 229aed8d94eSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 230aed8d94eSDimitry Andric 231aed8d94eSDimitry Andric#if _LIBCPP_STD_VER > 14 232aed8d94eSDimitry Andric 233aed8d94eSDimitry Andric_LIBCPP_NORETURN 234aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 235*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 236aed8d94eSDimitry Andricvoid __throw_bad_variant_access() { 237aed8d94eSDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 238aed8d94eSDimitry Andric throw bad_variant_access(); 239aed8d94eSDimitry Andric#else 240aed8d94eSDimitry Andric _VSTD::abort(); 241aed8d94eSDimitry Andric#endif 242aed8d94eSDimitry Andric} 243aed8d94eSDimitry Andric 244aed8d94eSDimitry Andrictemplate <class... _Types> 245aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS variant; 246aed8d94eSDimitry Andric 247aed8d94eSDimitry Andrictemplate <class _Tp> 248aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size; 249aed8d94eSDimitry Andric 250aed8d94eSDimitry Andrictemplate <class _Tp> 25130785c0eSDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t variant_size_v = variant_size<_Tp>::value; 252aed8d94eSDimitry Andric 253aed8d94eSDimitry Andrictemplate <class _Tp> 254aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {}; 255aed8d94eSDimitry Andric 256aed8d94eSDimitry Andrictemplate <class _Tp> 257aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {}; 258aed8d94eSDimitry Andric 259aed8d94eSDimitry Andrictemplate <class _Tp> 260aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> 261aed8d94eSDimitry Andric : variant_size<_Tp> {}; 262aed8d94eSDimitry Andric 263aed8d94eSDimitry Andrictemplate <class... _Types> 264aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>> 265aed8d94eSDimitry Andric : integral_constant<size_t, sizeof...(_Types)> {}; 266aed8d94eSDimitry Andric 267aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp> 268aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative; 269aed8d94eSDimitry Andric 270aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp> 271aed8d94eSDimitry Andricusing variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type; 272aed8d94eSDimitry Andric 273aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp> 274aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp> 275aed8d94eSDimitry Andric : add_const<variant_alternative_t<_Ip, _Tp>> {}; 276aed8d94eSDimitry Andric 277aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp> 278aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, volatile _Tp> 279aed8d94eSDimitry Andric : add_volatile<variant_alternative_t<_Ip, _Tp>> {}; 280aed8d94eSDimitry Andric 281aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Tp> 282aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> 283aed8d94eSDimitry Andric : add_cv<variant_alternative_t<_Ip, _Tp>> {}; 284aed8d94eSDimitry Andric 285aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 286aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> { 28724d58133SDimitry Andric static_assert(_Ip < sizeof...(_Types), "Index out of bounds in std::variant_alternative<>"); 288aed8d94eSDimitry Andric using type = __type_pack_element<_Ip, _Types...>; 289aed8d94eSDimitry Andric}; 290aed8d94eSDimitry Andric 29130785c0eSDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t variant_npos = static_cast<size_t>(-1); 292b2c7081bSDimitry Andric 293b2c7081bSDimitry Andricconstexpr int __choose_index_type(unsigned int __num_elem) { 294b2c7081bSDimitry Andric if (__num_elem < std::numeric_limits<unsigned char>::max()) 295b2c7081bSDimitry Andric return 0; 296b2c7081bSDimitry Andric if (__num_elem < std::numeric_limits<unsigned short>::max()) 297b2c7081bSDimitry Andric return 1; 298b2c7081bSDimitry Andric return 2; 299b2c7081bSDimitry Andric} 300b2c7081bSDimitry Andric 301b2c7081bSDimitry Andrictemplate <size_t _NumAlts> 302b2c7081bSDimitry Andricusing __variant_index_t = 303b2c7081bSDimitry Andric#ifndef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION 304b2c7081bSDimitry Andric unsigned int; 305b2c7081bSDimitry Andric#else 306b2c7081bSDimitry Andric std::tuple_element_t< 307b2c7081bSDimitry Andric __choose_index_type(_NumAlts), 308b2c7081bSDimitry Andric std::tuple<unsigned char, unsigned short, unsigned int> 309b2c7081bSDimitry Andric >; 310b2c7081bSDimitry Andric#endif 311b2c7081bSDimitry Andric 312b2c7081bSDimitry Andrictemplate <class _IndexType> 313b2c7081bSDimitry Andricconstexpr _IndexType __variant_npos = static_cast<_IndexType>(-1); 314aed8d94eSDimitry Andric 315aed8d94eSDimitry Andricnamespace __find_detail { 316aed8d94eSDimitry Andric 317aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 318aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 319aed8d94eSDimitry Andricconstexpr size_t __find_index() { 320aed8d94eSDimitry Andric constexpr bool __matches[] = {is_same_v<_Tp, _Types>...}; 321aed8d94eSDimitry Andric size_t __result = __not_found; 322aed8d94eSDimitry Andric for (size_t __i = 0; __i < sizeof...(_Types); ++__i) { 323aed8d94eSDimitry Andric if (__matches[__i]) { 324aed8d94eSDimitry Andric if (__result != __not_found) { 325aed8d94eSDimitry Andric return __ambiguous; 326aed8d94eSDimitry Andric } 327aed8d94eSDimitry Andric __result = __i; 328aed8d94eSDimitry Andric } 329aed8d94eSDimitry Andric } 330aed8d94eSDimitry Andric return __result; 331aed8d94eSDimitry Andric} 332aed8d94eSDimitry Andric 333aed8d94eSDimitry Andrictemplate <size_t _Index> 334aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl 335aed8d94eSDimitry Andric : integral_constant<size_t, _Index> {}; 336aed8d94eSDimitry Andric 337aed8d94eSDimitry Andrictemplate <> 338aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl<__not_found> {}; 339aed8d94eSDimitry Andric 340aed8d94eSDimitry Andrictemplate <> 341aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae_impl<__ambiguous> {}; 342aed8d94eSDimitry Andric 343aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 344aed8d94eSDimitry Andricstruct __find_unambiguous_index_sfinae 345aed8d94eSDimitry Andric : __find_unambiguous_index_sfinae_impl<__find_index<_Tp, _Types...>()> {}; 346aed8d94eSDimitry Andric 347aed8d94eSDimitry Andric} // namespace __find_detail 348aed8d94eSDimitry Andric 349aed8d94eSDimitry Andricnamespace __variant_detail { 350aed8d94eSDimitry Andric 351aed8d94eSDimitry Andricstruct __valueless_t {}; 352aed8d94eSDimitry Andric 353aed8d94eSDimitry Andricenum class _Trait { _TriviallyAvailable, _Available, _Unavailable }; 354aed8d94eSDimitry Andric 355aed8d94eSDimitry Andrictemplate <typename _Tp, 356aed8d94eSDimitry Andric template <typename> class _IsTriviallyAvailable, 357aed8d94eSDimitry Andric template <typename> class _IsAvailable> 358aed8d94eSDimitry Andricconstexpr _Trait __trait = 359aed8d94eSDimitry Andric _IsTriviallyAvailable<_Tp>::value 360aed8d94eSDimitry Andric ? _Trait::_TriviallyAvailable 361aed8d94eSDimitry Andric : _IsAvailable<_Tp>::value ? _Trait::_Available : _Trait::_Unavailable; 362aed8d94eSDimitry Andric 363aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 364aed8d94eSDimitry Andricconstexpr _Trait __common_trait(initializer_list<_Trait> __traits) { 365aed8d94eSDimitry Andric _Trait __result = _Trait::_TriviallyAvailable; 366aed8d94eSDimitry Andric for (_Trait __t : __traits) { 367aed8d94eSDimitry Andric if (static_cast<int>(__t) > static_cast<int>(__result)) { 368aed8d94eSDimitry Andric __result = __t; 369aed8d94eSDimitry Andric } 370aed8d94eSDimitry Andric } 371aed8d94eSDimitry Andric return __result; 372aed8d94eSDimitry Andric} 373aed8d94eSDimitry Andric 374aed8d94eSDimitry Andrictemplate <typename... _Types> 375aed8d94eSDimitry Andricstruct __traits { 376aed8d94eSDimitry Andric static constexpr _Trait __copy_constructible_trait = 377aed8d94eSDimitry Andric __common_trait({__trait<_Types, 378aed8d94eSDimitry Andric is_trivially_copy_constructible, 379aed8d94eSDimitry Andric is_copy_constructible>...}); 380aed8d94eSDimitry Andric 381aed8d94eSDimitry Andric static constexpr _Trait __move_constructible_trait = 382aed8d94eSDimitry Andric __common_trait({__trait<_Types, 383aed8d94eSDimitry Andric is_trivially_move_constructible, 384aed8d94eSDimitry Andric is_move_constructible>...}); 385aed8d94eSDimitry Andric 386aed8d94eSDimitry Andric static constexpr _Trait __copy_assignable_trait = __common_trait( 387aed8d94eSDimitry Andric {__copy_constructible_trait, 388aed8d94eSDimitry Andric __trait<_Types, is_trivially_copy_assignable, is_copy_assignable>...}); 389aed8d94eSDimitry Andric 390aed8d94eSDimitry Andric static constexpr _Trait __move_assignable_trait = __common_trait( 391aed8d94eSDimitry Andric {__move_constructible_trait, 392aed8d94eSDimitry Andric __trait<_Types, is_trivially_move_assignable, is_move_assignable>...}); 393aed8d94eSDimitry Andric 394aed8d94eSDimitry Andric static constexpr _Trait __destructible_trait = __common_trait( 395aed8d94eSDimitry Andric {__trait<_Types, is_trivially_destructible, is_destructible>...}); 396aed8d94eSDimitry Andric}; 397aed8d94eSDimitry Andric 398aed8d94eSDimitry Andricnamespace __access { 399aed8d94eSDimitry Andric 400aed8d94eSDimitry Andricstruct __union { 401aed8d94eSDimitry Andric template <class _Vp> 402aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 403aed8d94eSDimitry Andric static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<0>) { 404aed8d94eSDimitry Andric return _VSTD::forward<_Vp>(__v).__head; 405aed8d94eSDimitry Andric } 406aed8d94eSDimitry Andric 407aed8d94eSDimitry Andric template <class _Vp, size_t _Ip> 408aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 409aed8d94eSDimitry Andric static constexpr auto&& __get_alt(_Vp&& __v, in_place_index_t<_Ip>) { 410aed8d94eSDimitry Andric return __get_alt(_VSTD::forward<_Vp>(__v).__tail, in_place_index<_Ip - 1>); 411aed8d94eSDimitry Andric } 412aed8d94eSDimitry Andric}; 413aed8d94eSDimitry Andric 414aed8d94eSDimitry Andricstruct __base { 415aed8d94eSDimitry Andric template <size_t _Ip, class _Vp> 416aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 417aed8d94eSDimitry Andric static constexpr auto&& __get_alt(_Vp&& __v) { 418aed8d94eSDimitry Andric return __union::__get_alt(_VSTD::forward<_Vp>(__v).__data, 419aed8d94eSDimitry Andric in_place_index<_Ip>); 420aed8d94eSDimitry Andric } 421aed8d94eSDimitry Andric}; 422aed8d94eSDimitry Andric 423aed8d94eSDimitry Andricstruct __variant { 424aed8d94eSDimitry Andric template <size_t _Ip, class _Vp> 425aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 426aed8d94eSDimitry Andric static constexpr auto&& __get_alt(_Vp&& __v) { 427aed8d94eSDimitry Andric return __base::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v).__impl); 428aed8d94eSDimitry Andric } 429aed8d94eSDimitry Andric}; 430aed8d94eSDimitry Andric 431aed8d94eSDimitry Andric} // namespace __access 432aed8d94eSDimitry Andric 433aed8d94eSDimitry Andricnamespace __visitation { 434aed8d94eSDimitry Andric 435aed8d94eSDimitry Andricstruct __base { 436aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 437aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 438aed8d94eSDimitry Andric static constexpr decltype(auto) 439aed8d94eSDimitry Andric __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { 440aed8d94eSDimitry Andric constexpr auto __fdiagonal = 441aed8d94eSDimitry Andric __make_fdiagonal<_Visitor&&, 442aed8d94eSDimitry Andric decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); 443aed8d94eSDimitry Andric return __fdiagonal[__index](_VSTD::forward<_Visitor>(__visitor), 444aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs).__as_base()...); 445aed8d94eSDimitry Andric } 446aed8d94eSDimitry Andric 447aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 448aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 449aed8d94eSDimitry Andric static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor, 450aed8d94eSDimitry Andric _Vs&&... __vs) { 451aed8d94eSDimitry Andric constexpr auto __fmatrix = 452aed8d94eSDimitry Andric __make_fmatrix<_Visitor&&, 453aed8d94eSDimitry Andric decltype(_VSTD::forward<_Vs>(__vs).__as_base())...>(); 4545517e702SDimitry Andric return __at(__fmatrix, __vs.index()...)( 4555517e702SDimitry Andric _VSTD::forward<_Visitor>(__visitor), 456aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs).__as_base()...); 457aed8d94eSDimitry Andric } 458aed8d94eSDimitry Andric 459aed8d94eSDimitry Andricprivate: 460aed8d94eSDimitry Andric template <class _Tp> 461aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4625517e702SDimitry Andric static constexpr const _Tp& __at(const _Tp& __elem) { return __elem; } 463aed8d94eSDimitry Andric 4645517e702SDimitry Andric template <class _Tp, size_t _Np, typename... _Indices> 465aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 466aed8d94eSDimitry Andric static constexpr auto&& __at(const array<_Tp, _Np>& __elems, 4675517e702SDimitry Andric size_t __index, _Indices... __indices) { 4685517e702SDimitry Andric return __at(__elems[__index], __indices...); 469aed8d94eSDimitry Andric } 470aed8d94eSDimitry Andric 471aed8d94eSDimitry Andric template <class _Fp, class... _Fs> 472aed8d94eSDimitry Andric static constexpr void __std_visit_visitor_return_type_check() { 473aed8d94eSDimitry Andric static_assert( 474aed8d94eSDimitry Andric __all<is_same_v<_Fp, _Fs>...>::value, 475aed8d94eSDimitry Andric "`std::visit` requires the visitor to have a single return type."); 476aed8d94eSDimitry Andric } 477aed8d94eSDimitry Andric 478aed8d94eSDimitry Andric template <class... _Fs> 479aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 480aed8d94eSDimitry Andric static constexpr auto __make_farray(_Fs&&... __fs) { 4814ba319b5SDimitry Andric __std_visit_visitor_return_type_check<__uncvref_t<_Fs>...>(); 4824ba319b5SDimitry Andric using __result = array<common_type_t<__uncvref_t<_Fs>...>, sizeof...(_Fs)>; 483aed8d94eSDimitry Andric return __result{{_VSTD::forward<_Fs>(__fs)...}}; 484aed8d94eSDimitry Andric } 485aed8d94eSDimitry Andric 486540d2a8bSDimitry Andric template <std::size_t... _Is> 487aed8d94eSDimitry Andric struct __dispatcher { 488540d2a8bSDimitry Andric template <class _Fp, class... _Vs> 489540d2a8bSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 490aed8d94eSDimitry Andric static constexpr decltype(auto) __dispatch(_Fp __f, _Vs... __vs) { 491aed8d94eSDimitry Andric return __invoke_constexpr( 492aed8d94eSDimitry Andric static_cast<_Fp>(__f), 493aed8d94eSDimitry Andric __access::__base::__get_alt<_Is>(static_cast<_Vs>(__vs))...); 494aed8d94eSDimitry Andric } 495aed8d94eSDimitry Andric }; 496540d2a8bSDimitry Andric 497540d2a8bSDimitry Andric template <class _Fp, class... _Vs, size_t... _Is> 498540d2a8bSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 499540d2a8bSDimitry Andric static constexpr auto __make_dispatch(index_sequence<_Is...>) { 500540d2a8bSDimitry Andric return __dispatcher<_Is...>::template __dispatch<_Fp, _Vs...>; 501aed8d94eSDimitry Andric } 502aed8d94eSDimitry Andric 503aed8d94eSDimitry Andric template <size_t _Ip, class _Fp, class... _Vs> 504aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 505aed8d94eSDimitry Andric static constexpr auto __make_fdiagonal_impl() { 506aed8d94eSDimitry Andric return __make_dispatch<_Fp, _Vs...>( 507aed8d94eSDimitry Andric index_sequence<(__identity<_Vs>{}, _Ip)...>{}); 508aed8d94eSDimitry Andric } 509aed8d94eSDimitry Andric 510aed8d94eSDimitry Andric template <class _Fp, class... _Vs, size_t... _Is> 511aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 512aed8d94eSDimitry Andric static constexpr auto __make_fdiagonal_impl(index_sequence<_Is...>) { 513aed8d94eSDimitry Andric return __base::__make_farray(__make_fdiagonal_impl<_Is, _Fp, _Vs...>()...); 514aed8d94eSDimitry Andric } 515aed8d94eSDimitry Andric 516aed8d94eSDimitry Andric template <class _Fp, class _Vp, class... _Vs> 517aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 518aed8d94eSDimitry Andric static constexpr auto __make_fdiagonal() { 5194ba319b5SDimitry Andric constexpr size_t _Np = __uncvref_t<_Vp>::__size(); 5204ba319b5SDimitry Andric static_assert(__all<(_Np == __uncvref_t<_Vs>::__size())...>::value); 521aed8d94eSDimitry Andric return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<_Np>{}); 522aed8d94eSDimitry Andric } 523aed8d94eSDimitry Andric 524aed8d94eSDimitry Andric template <class _Fp, class... _Vs, size_t... _Is> 525aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 526aed8d94eSDimitry Andric static constexpr auto __make_fmatrix_impl(index_sequence<_Is...> __is) { 527aed8d94eSDimitry Andric return __make_dispatch<_Fp, _Vs...>(__is); 528aed8d94eSDimitry Andric } 529aed8d94eSDimitry Andric 530aed8d94eSDimitry Andric template <class _Fp, class... _Vs, size_t... _Is, size_t... _Js, class... _Ls> 531aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 532aed8d94eSDimitry Andric static constexpr auto __make_fmatrix_impl(index_sequence<_Is...>, 533aed8d94eSDimitry Andric index_sequence<_Js...>, 534aed8d94eSDimitry Andric _Ls... __ls) { 535aed8d94eSDimitry Andric return __base::__make_farray(__make_fmatrix_impl<_Fp, _Vs...>( 536aed8d94eSDimitry Andric index_sequence<_Is..., _Js>{}, __ls...)...); 537aed8d94eSDimitry Andric } 538aed8d94eSDimitry Andric 539aed8d94eSDimitry Andric template <class _Fp, class... _Vs> 540aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 541aed8d94eSDimitry Andric static constexpr auto __make_fmatrix() { 542aed8d94eSDimitry Andric return __make_fmatrix_impl<_Fp, _Vs...>( 5434ba319b5SDimitry Andric index_sequence<>{}, make_index_sequence<__uncvref_t<_Vs>::__size()>{}...); 544aed8d94eSDimitry Andric } 545aed8d94eSDimitry Andric}; 546aed8d94eSDimitry Andric 547aed8d94eSDimitry Andricstruct __variant { 548aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 549aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 550aed8d94eSDimitry Andric static constexpr decltype(auto) 551aed8d94eSDimitry Andric __visit_alt_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { 552aed8d94eSDimitry Andric return __base::__visit_alt_at(__index, 553aed8d94eSDimitry Andric _VSTD::forward<_Visitor>(__visitor), 554aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs).__impl...); 555aed8d94eSDimitry Andric } 556aed8d94eSDimitry Andric 557aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 558aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 559aed8d94eSDimitry Andric static constexpr decltype(auto) __visit_alt(_Visitor&& __visitor, 560aed8d94eSDimitry Andric _Vs&&... __vs) { 561aed8d94eSDimitry Andric return __base::__visit_alt(_VSTD::forward<_Visitor>(__visitor), 562aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs).__impl...); 563aed8d94eSDimitry Andric } 564aed8d94eSDimitry Andric 565aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 566aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 567aed8d94eSDimitry Andric static constexpr decltype(auto) 568aed8d94eSDimitry Andric __visit_value_at(size_t __index, _Visitor&& __visitor, _Vs&&... __vs) { 569aed8d94eSDimitry Andric return __visit_alt_at( 570aed8d94eSDimitry Andric __index, 571aed8d94eSDimitry Andric __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)), 572aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs)...); 573aed8d94eSDimitry Andric } 574aed8d94eSDimitry Andric 575aed8d94eSDimitry Andric template <class _Visitor, class... _Vs> 576aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 577aed8d94eSDimitry Andric static constexpr decltype(auto) __visit_value(_Visitor&& __visitor, 578aed8d94eSDimitry Andric _Vs&&... __vs) { 579aed8d94eSDimitry Andric return __visit_alt( 580aed8d94eSDimitry Andric __make_value_visitor(_VSTD::forward<_Visitor>(__visitor)), 581aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs)...); 582aed8d94eSDimitry Andric } 583aed8d94eSDimitry Andric 584aed8d94eSDimitry Andricprivate: 585aed8d94eSDimitry Andric template <class _Visitor, class... _Values> 586aed8d94eSDimitry Andric static constexpr void __std_visit_exhaustive_visitor_check() { 587b2c7081bSDimitry Andric static_assert(is_invocable_v<_Visitor, _Values...>, 588aed8d94eSDimitry Andric "`std::visit` requires the visitor to be exhaustive."); 589aed8d94eSDimitry Andric } 590aed8d94eSDimitry Andric 591aed8d94eSDimitry Andric template <class _Visitor> 592aed8d94eSDimitry Andric struct __value_visitor { 593aed8d94eSDimitry Andric template <class... _Alts> 594aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 595aed8d94eSDimitry Andric constexpr decltype(auto) operator()(_Alts&&... __alts) const { 596aed8d94eSDimitry Andric __std_visit_exhaustive_visitor_check< 597aed8d94eSDimitry Andric _Visitor, 5985ca5951eSDimitry Andric decltype((_VSTD::forward<_Alts>(__alts).__value))...>(); 599aed8d94eSDimitry Andric return __invoke_constexpr(_VSTD::forward<_Visitor>(__visitor), 600aed8d94eSDimitry Andric _VSTD::forward<_Alts>(__alts).__value...); 601aed8d94eSDimitry Andric } 602aed8d94eSDimitry Andric _Visitor&& __visitor; 603aed8d94eSDimitry Andric }; 604aed8d94eSDimitry Andric 605aed8d94eSDimitry Andric template <class _Visitor> 606aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 607aed8d94eSDimitry Andric static constexpr auto __make_value_visitor(_Visitor&& __visitor) { 608aed8d94eSDimitry Andric return __value_visitor<_Visitor>{_VSTD::forward<_Visitor>(__visitor)}; 609aed8d94eSDimitry Andric } 610aed8d94eSDimitry Andric}; 611aed8d94eSDimitry Andric 612aed8d94eSDimitry Andric} // namespace __visitation 613aed8d94eSDimitry Andric 614aed8d94eSDimitry Andrictemplate <size_t _Index, class _Tp> 615aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __alt { 616aed8d94eSDimitry Andric using __value_type = _Tp; 617aed8d94eSDimitry Andric 618aed8d94eSDimitry Andric template <class... _Args> 619aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 620aed8d94eSDimitry Andric explicit constexpr __alt(in_place_t, _Args&&... __args) 621aed8d94eSDimitry Andric : __value(_VSTD::forward<_Args>(__args)...) {} 622aed8d94eSDimitry Andric 623aed8d94eSDimitry Andric __value_type __value; 624aed8d94eSDimitry Andric}; 625aed8d94eSDimitry Andric 626aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, size_t _Index, class... _Types> 627aed8d94eSDimitry Andricunion _LIBCPP_TEMPLATE_VIS __union; 628aed8d94eSDimitry Andric 629aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, size_t _Index> 630aed8d94eSDimitry Andricunion _LIBCPP_TEMPLATE_VIS __union<_DestructibleTrait, _Index> {}; 631aed8d94eSDimitry Andric 632aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_UNION(destructible_trait, destructor) \ 633aed8d94eSDimitry Andric template <size_t _Index, class _Tp, class... _Types> \ 634aed8d94eSDimitry Andric union _LIBCPP_TEMPLATE_VIS __union<destructible_trait, \ 635aed8d94eSDimitry Andric _Index, \ 636aed8d94eSDimitry Andric _Tp, \ 637aed8d94eSDimitry Andric _Types...> { \ 638aed8d94eSDimitry Andric public: \ 639aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY \ 640aed8d94eSDimitry Andric explicit constexpr __union(__valueless_t) noexcept : __dummy{} {} \ 641aed8d94eSDimitry Andric \ 642aed8d94eSDimitry Andric template <class... _Args> \ 643aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY \ 644aed8d94eSDimitry Andric explicit constexpr __union(in_place_index_t<0>, _Args&&... __args) \ 645aed8d94eSDimitry Andric : __head(in_place, _VSTD::forward<_Args>(__args)...) {} \ 646aed8d94eSDimitry Andric \ 647aed8d94eSDimitry Andric template <size_t _Ip, class... _Args> \ 648aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY \ 649aed8d94eSDimitry Andric explicit constexpr __union(in_place_index_t<_Ip>, _Args&&... __args) \ 650aed8d94eSDimitry Andric : __tail(in_place_index<_Ip - 1>, _VSTD::forward<_Args>(__args)...) {} \ 651aed8d94eSDimitry Andric \ 652aed8d94eSDimitry Andric __union(const __union&) = default; \ 653aed8d94eSDimitry Andric __union(__union&&) = default; \ 654aed8d94eSDimitry Andric \ 655aed8d94eSDimitry Andric destructor \ 656aed8d94eSDimitry Andric \ 657aed8d94eSDimitry Andric __union& operator=(const __union&) = default; \ 658aed8d94eSDimitry Andric __union& operator=(__union&&) = default; \ 659aed8d94eSDimitry Andric \ 660aed8d94eSDimitry Andric private: \ 661aed8d94eSDimitry Andric char __dummy; \ 662aed8d94eSDimitry Andric __alt<_Index, _Tp> __head; \ 663aed8d94eSDimitry Andric __union<destructible_trait, _Index + 1, _Types...> __tail; \ 664aed8d94eSDimitry Andric \ 665aed8d94eSDimitry Andric friend struct __access::__union; \ 666aed8d94eSDimitry Andric } 667aed8d94eSDimitry Andric 668aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_TriviallyAvailable, ~__union() = default;); 669aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_Available, ~__union() {}); 670aed8d94eSDimitry Andric_LIBCPP_VARIANT_UNION(_Trait::_Unavailable, ~__union() = delete;); 671aed8d94eSDimitry Andric 672aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_UNION 673aed8d94eSDimitry Andric 674aed8d94eSDimitry Andrictemplate <_Trait _DestructibleTrait, class... _Types> 675aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __base { 676aed8d94eSDimitry Andricpublic: 677b2c7081bSDimitry Andric using __index_t = __variant_index_t<sizeof...(_Types)>; 678b2c7081bSDimitry Andric 679aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 680aed8d94eSDimitry Andric explicit constexpr __base(__valueless_t tag) noexcept 681b2c7081bSDimitry Andric : __data(tag), __index(__variant_npos<__index_t>) {} 682aed8d94eSDimitry Andric 683aed8d94eSDimitry Andric template <size_t _Ip, class... _Args> 684aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 685aed8d94eSDimitry Andric explicit constexpr __base(in_place_index_t<_Ip>, _Args&&... __args) 686aed8d94eSDimitry Andric : 687aed8d94eSDimitry Andric __data(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...), 688aed8d94eSDimitry Andric __index(_Ip) {} 689aed8d94eSDimitry Andric 690aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 691aed8d94eSDimitry Andric constexpr bool valueless_by_exception() const noexcept { 692aed8d94eSDimitry Andric return index() == variant_npos; 693aed8d94eSDimitry Andric } 694aed8d94eSDimitry Andric 695aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 696aed8d94eSDimitry Andric constexpr size_t index() const noexcept { 697b2c7081bSDimitry Andric return __index == __variant_npos<__index_t> ? variant_npos : __index; 698aed8d94eSDimitry Andric } 699aed8d94eSDimitry Andric 700aed8d94eSDimitry Andricprotected: 701aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 702aed8d94eSDimitry Andric constexpr auto&& __as_base() & { return *this; } 703aed8d94eSDimitry Andric 704aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 705aed8d94eSDimitry Andric constexpr auto&& __as_base() && { return _VSTD::move(*this); } 706aed8d94eSDimitry Andric 707aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 708aed8d94eSDimitry Andric constexpr auto&& __as_base() const & { return *this; } 709aed8d94eSDimitry Andric 710aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 711aed8d94eSDimitry Andric constexpr auto&& __as_base() const && { return _VSTD::move(*this); } 712aed8d94eSDimitry Andric 713aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 714aed8d94eSDimitry Andric static constexpr size_t __size() { return sizeof...(_Types); } 715aed8d94eSDimitry Andric 716aed8d94eSDimitry Andric __union<_DestructibleTrait, 0, _Types...> __data; 717b2c7081bSDimitry Andric __index_t __index; 718aed8d94eSDimitry Andric 719aed8d94eSDimitry Andric friend struct __access::__base; 720aed8d94eSDimitry Andric friend struct __visitation::__base; 721aed8d94eSDimitry Andric}; 722aed8d94eSDimitry Andric 723aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__destructible_trait> 724aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __destructor; 725aed8d94eSDimitry Andric 726aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_DESTRUCTOR(destructible_trait, destructor, destroy) \ 727aed8d94eSDimitry Andric template <class... _Types> \ 728aed8d94eSDimitry Andric class _LIBCPP_TEMPLATE_VIS __destructor<__traits<_Types...>, \ 729aed8d94eSDimitry Andric destructible_trait> \ 730aed8d94eSDimitry Andric : public __base<destructible_trait, _Types...> { \ 731aed8d94eSDimitry Andric using __base_type = __base<destructible_trait, _Types...>; \ 732b2c7081bSDimitry Andric using __index_t = typename __base_type::__index_t; \ 733aed8d94eSDimitry Andric \ 734aed8d94eSDimitry Andric public: \ 735aed8d94eSDimitry Andric using __base_type::__base_type; \ 736aed8d94eSDimitry Andric using __base_type::operator=; \ 737aed8d94eSDimitry Andric \ 738aed8d94eSDimitry Andric __destructor(const __destructor&) = default; \ 739aed8d94eSDimitry Andric __destructor(__destructor&&) = default; \ 740aed8d94eSDimitry Andric destructor \ 741aed8d94eSDimitry Andric __destructor& operator=(const __destructor&) = default; \ 742aed8d94eSDimitry Andric __destructor& operator=(__destructor&&) = default; \ 743aed8d94eSDimitry Andric \ 744aed8d94eSDimitry Andric protected: \ 745aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY \ 746aed8d94eSDimitry Andric destroy \ 747aed8d94eSDimitry Andric } 748aed8d94eSDimitry Andric 749aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR( 750aed8d94eSDimitry Andric _Trait::_TriviallyAvailable, 751aed8d94eSDimitry Andric ~__destructor() = default;, 752b2c7081bSDimitry Andric void __destroy() noexcept { this->__index = __variant_npos<__index_t>; }); 753aed8d94eSDimitry Andric 754aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR( 755aed8d94eSDimitry Andric _Trait::_Available, 756aed8d94eSDimitry Andric ~__destructor() { __destroy(); }, 757aed8d94eSDimitry Andric void __destroy() noexcept { 758aed8d94eSDimitry Andric if (!this->valueless_by_exception()) { 759aed8d94eSDimitry Andric __visitation::__base::__visit_alt( 760aed8d94eSDimitry Andric [](auto& __alt) noexcept { 7614ba319b5SDimitry Andric using __alt_type = __uncvref_t<decltype(__alt)>; 762aed8d94eSDimitry Andric __alt.~__alt_type(); 763aed8d94eSDimitry Andric }, 764aed8d94eSDimitry Andric *this); 765aed8d94eSDimitry Andric } 766b2c7081bSDimitry Andric this->__index = __variant_npos<__index_t>; 767aed8d94eSDimitry Andric }); 768aed8d94eSDimitry Andric 769aed8d94eSDimitry Andric_LIBCPP_VARIANT_DESTRUCTOR( 770aed8d94eSDimitry Andric _Trait::_Unavailable, 771aed8d94eSDimitry Andric ~__destructor() = delete;, 772aed8d94eSDimitry Andric void __destroy() noexcept = delete;); 773aed8d94eSDimitry Andric 774aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_DESTRUCTOR 775aed8d94eSDimitry Andric 776aed8d94eSDimitry Andrictemplate <class _Traits> 777aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __constructor : public __destructor<_Traits> { 778aed8d94eSDimitry Andric using __base_type = __destructor<_Traits>; 779aed8d94eSDimitry Andric 780aed8d94eSDimitry Andricpublic: 781aed8d94eSDimitry Andric using __base_type::__base_type; 782aed8d94eSDimitry Andric using __base_type::operator=; 783aed8d94eSDimitry Andric 784aed8d94eSDimitry Andricprotected: 785aed8d94eSDimitry Andric template <size_t _Ip, class _Tp, class... _Args> 786aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 787540d2a8bSDimitry Andric static _Tp& __construct_alt(__alt<_Ip, _Tp>& __a, _Args&&... __args) { 788540d2a8bSDimitry Andric ::new ((void*)_VSTD::addressof(__a)) 789aed8d94eSDimitry Andric __alt<_Ip, _Tp>(in_place, _VSTD::forward<_Args>(__args)...); 790540d2a8bSDimitry Andric return __a.__value; 791aed8d94eSDimitry Andric } 792aed8d94eSDimitry Andric 793aed8d94eSDimitry Andric template <class _Rhs> 794aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 795aed8d94eSDimitry Andric static void __generic_construct(__constructor& __lhs, _Rhs&& __rhs) { 796aed8d94eSDimitry Andric __lhs.__destroy(); 797aed8d94eSDimitry Andric if (!__rhs.valueless_by_exception()) { 798aed8d94eSDimitry Andric __visitation::__base::__visit_alt_at( 799aed8d94eSDimitry Andric __rhs.index(), 800aed8d94eSDimitry Andric [](auto& __lhs_alt, auto&& __rhs_alt) { 801aed8d94eSDimitry Andric __construct_alt( 802aed8d94eSDimitry Andric __lhs_alt, 803aed8d94eSDimitry Andric _VSTD::forward<decltype(__rhs_alt)>(__rhs_alt).__value); 804aed8d94eSDimitry Andric }, 805aed8d94eSDimitry Andric __lhs, _VSTD::forward<_Rhs>(__rhs)); 806aed8d94eSDimitry Andric __lhs.__index = __rhs.index(); 807aed8d94eSDimitry Andric } 808aed8d94eSDimitry Andric } 809aed8d94eSDimitry Andric}; 810aed8d94eSDimitry Andric 811aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__move_constructible_trait> 812aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __move_constructor; 813aed8d94eSDimitry Andric 814aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, \ 815aed8d94eSDimitry Andric move_constructor) \ 816aed8d94eSDimitry Andric template <class... _Types> \ 817aed8d94eSDimitry Andric class _LIBCPP_TEMPLATE_VIS __move_constructor<__traits<_Types...>, \ 818aed8d94eSDimitry Andric move_constructible_trait> \ 819aed8d94eSDimitry Andric : public __constructor<__traits<_Types...>> { \ 820aed8d94eSDimitry Andric using __base_type = __constructor<__traits<_Types...>>; \ 821aed8d94eSDimitry Andric \ 822aed8d94eSDimitry Andric public: \ 823aed8d94eSDimitry Andric using __base_type::__base_type; \ 824aed8d94eSDimitry Andric using __base_type::operator=; \ 825aed8d94eSDimitry Andric \ 826aed8d94eSDimitry Andric __move_constructor(const __move_constructor&) = default; \ 827aed8d94eSDimitry Andric move_constructor \ 828aed8d94eSDimitry Andric ~__move_constructor() = default; \ 829aed8d94eSDimitry Andric __move_constructor& operator=(const __move_constructor&) = default; \ 830aed8d94eSDimitry Andric __move_constructor& operator=(__move_constructor&&) = default; \ 831aed8d94eSDimitry Andric } 832aed8d94eSDimitry Andric 833aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR( 834aed8d94eSDimitry Andric _Trait::_TriviallyAvailable, 835aed8d94eSDimitry Andric __move_constructor(__move_constructor&& __that) = default;); 836aed8d94eSDimitry Andric 837aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR( 838aed8d94eSDimitry Andric _Trait::_Available, 839aed8d94eSDimitry Andric __move_constructor(__move_constructor&& __that) noexcept( 840aed8d94eSDimitry Andric __all<is_nothrow_move_constructible_v<_Types>...>::value) 841aed8d94eSDimitry Andric : __move_constructor(__valueless_t{}) { 842aed8d94eSDimitry Andric this->__generic_construct(*this, _VSTD::move(__that)); 843aed8d94eSDimitry Andric }); 844aed8d94eSDimitry Andric 845aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_CONSTRUCTOR( 846aed8d94eSDimitry Andric _Trait::_Unavailable, 847aed8d94eSDimitry Andric __move_constructor(__move_constructor&&) = delete;); 848aed8d94eSDimitry Andric 849aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_MOVE_CONSTRUCTOR 850aed8d94eSDimitry Andric 851aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__copy_constructible_trait> 852aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __copy_constructor; 853aed8d94eSDimitry Andric 854aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, \ 855aed8d94eSDimitry Andric copy_constructor) \ 856aed8d94eSDimitry Andric template <class... _Types> \ 857aed8d94eSDimitry Andric class _LIBCPP_TEMPLATE_VIS __copy_constructor<__traits<_Types...>, \ 858aed8d94eSDimitry Andric copy_constructible_trait> \ 859aed8d94eSDimitry Andric : public __move_constructor<__traits<_Types...>> { \ 860aed8d94eSDimitry Andric using __base_type = __move_constructor<__traits<_Types...>>; \ 861aed8d94eSDimitry Andric \ 862aed8d94eSDimitry Andric public: \ 863aed8d94eSDimitry Andric using __base_type::__base_type; \ 864aed8d94eSDimitry Andric using __base_type::operator=; \ 865aed8d94eSDimitry Andric \ 866aed8d94eSDimitry Andric copy_constructor \ 867aed8d94eSDimitry Andric __copy_constructor(__copy_constructor&&) = default; \ 868aed8d94eSDimitry Andric ~__copy_constructor() = default; \ 869aed8d94eSDimitry Andric __copy_constructor& operator=(const __copy_constructor&) = default; \ 870aed8d94eSDimitry Andric __copy_constructor& operator=(__copy_constructor&&) = default; \ 871aed8d94eSDimitry Andric } 872aed8d94eSDimitry Andric 873aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR( 874aed8d94eSDimitry Andric _Trait::_TriviallyAvailable, 875aed8d94eSDimitry Andric __copy_constructor(const __copy_constructor& __that) = default;); 876aed8d94eSDimitry Andric 877aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR( 878aed8d94eSDimitry Andric _Trait::_Available, 879aed8d94eSDimitry Andric __copy_constructor(const __copy_constructor& __that) 880aed8d94eSDimitry Andric : __copy_constructor(__valueless_t{}) { 881aed8d94eSDimitry Andric this->__generic_construct(*this, __that); 882aed8d94eSDimitry Andric }); 883aed8d94eSDimitry Andric 884aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_CONSTRUCTOR( 885aed8d94eSDimitry Andric _Trait::_Unavailable, 886aed8d94eSDimitry Andric __copy_constructor(const __copy_constructor&) = delete;); 887aed8d94eSDimitry Andric 888aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_COPY_CONSTRUCTOR 889aed8d94eSDimitry Andric 890aed8d94eSDimitry Andrictemplate <class _Traits> 891aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __assignment : public __copy_constructor<_Traits> { 892aed8d94eSDimitry Andric using __base_type = __copy_constructor<_Traits>; 893aed8d94eSDimitry Andric 894aed8d94eSDimitry Andricpublic: 895aed8d94eSDimitry Andric using __base_type::__base_type; 896aed8d94eSDimitry Andric using __base_type::operator=; 897aed8d94eSDimitry Andric 898aed8d94eSDimitry Andric template <size_t _Ip, class... _Args> 899aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 900540d2a8bSDimitry Andric auto& __emplace(_Args&&... __args) { 901aed8d94eSDimitry Andric this->__destroy(); 902540d2a8bSDimitry Andric auto& __res = this->__construct_alt(__access::__base::__get_alt<_Ip>(*this), 903aed8d94eSDimitry Andric _VSTD::forward<_Args>(__args)...); 904aed8d94eSDimitry Andric this->__index = _Ip; 905540d2a8bSDimitry Andric return __res; 906aed8d94eSDimitry Andric } 907aed8d94eSDimitry Andric 908aed8d94eSDimitry Andricprotected: 909db17bf38SDimitry Andric template <size_t _Ip, class _Tp, class _Arg> 910aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 911db17bf38SDimitry Andric void __assign_alt(__alt<_Ip, _Tp>& __a, _Arg&& __arg) { 912aed8d94eSDimitry Andric if (this->index() == _Ip) { 913aed8d94eSDimitry Andric __a.__value = _VSTD::forward<_Arg>(__arg); 914aed8d94eSDimitry Andric } else { 915aed8d94eSDimitry Andric struct { 916aed8d94eSDimitry Andric void operator()(true_type) const { 917db17bf38SDimitry Andric __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg)); 918aed8d94eSDimitry Andric } 919aed8d94eSDimitry Andric void operator()(false_type) const { 920db17bf38SDimitry Andric __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg))); 921aed8d94eSDimitry Andric } 922aed8d94eSDimitry Andric __assignment* __this; 923aed8d94eSDimitry Andric _Arg&& __arg; 924aed8d94eSDimitry Andric } __impl{this, _VSTD::forward<_Arg>(__arg)}; 925db17bf38SDimitry Andric __impl(bool_constant<is_nothrow_constructible_v<_Tp, _Arg> || 926db17bf38SDimitry Andric !is_nothrow_move_constructible_v<_Tp>>{}); 927aed8d94eSDimitry Andric } 928aed8d94eSDimitry Andric } 929aed8d94eSDimitry Andric 930aed8d94eSDimitry Andric template <class _That> 931aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 932aed8d94eSDimitry Andric void __generic_assign(_That&& __that) { 933aed8d94eSDimitry Andric if (this->valueless_by_exception() && __that.valueless_by_exception()) { 934aed8d94eSDimitry Andric // do nothing. 935aed8d94eSDimitry Andric } else if (__that.valueless_by_exception()) { 936aed8d94eSDimitry Andric this->__destroy(); 937aed8d94eSDimitry Andric } else { 938aed8d94eSDimitry Andric __visitation::__base::__visit_alt_at( 939aed8d94eSDimitry Andric __that.index(), 940aed8d94eSDimitry Andric [this](auto& __this_alt, auto&& __that_alt) { 941aed8d94eSDimitry Andric this->__assign_alt( 942aed8d94eSDimitry Andric __this_alt, 943db17bf38SDimitry Andric _VSTD::forward<decltype(__that_alt)>(__that_alt).__value); 944aed8d94eSDimitry Andric }, 945aed8d94eSDimitry Andric *this, _VSTD::forward<_That>(__that)); 946aed8d94eSDimitry Andric } 947aed8d94eSDimitry Andric } 948aed8d94eSDimitry Andric}; 949aed8d94eSDimitry Andric 950aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__move_assignable_trait> 951aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __move_assignment; 952aed8d94eSDimitry Andric 953aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, \ 954aed8d94eSDimitry Andric move_assignment) \ 955aed8d94eSDimitry Andric template <class... _Types> \ 956aed8d94eSDimitry Andric class _LIBCPP_TEMPLATE_VIS __move_assignment<__traits<_Types...>, \ 957aed8d94eSDimitry Andric move_assignable_trait> \ 958aed8d94eSDimitry Andric : public __assignment<__traits<_Types...>> { \ 959aed8d94eSDimitry Andric using __base_type = __assignment<__traits<_Types...>>; \ 960aed8d94eSDimitry Andric \ 961aed8d94eSDimitry Andric public: \ 962aed8d94eSDimitry Andric using __base_type::__base_type; \ 963aed8d94eSDimitry Andric using __base_type::operator=; \ 964aed8d94eSDimitry Andric \ 965aed8d94eSDimitry Andric __move_assignment(const __move_assignment&) = default; \ 966aed8d94eSDimitry Andric __move_assignment(__move_assignment&&) = default; \ 967aed8d94eSDimitry Andric ~__move_assignment() = default; \ 968aed8d94eSDimitry Andric __move_assignment& operator=(const __move_assignment&) = default; \ 969aed8d94eSDimitry Andric move_assignment \ 970aed8d94eSDimitry Andric } 971aed8d94eSDimitry Andric 972aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT( 973aed8d94eSDimitry Andric _Trait::_TriviallyAvailable, 974aed8d94eSDimitry Andric __move_assignment& operator=(__move_assignment&& __that) = default;); 975aed8d94eSDimitry Andric 976aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT( 977aed8d94eSDimitry Andric _Trait::_Available, 978aed8d94eSDimitry Andric __move_assignment& operator=(__move_assignment&& __that) noexcept( 979aed8d94eSDimitry Andric __all<(is_nothrow_move_constructible_v<_Types> && 980aed8d94eSDimitry Andric is_nothrow_move_assignable_v<_Types>)...>::value) { 981aed8d94eSDimitry Andric this->__generic_assign(_VSTD::move(__that)); 982aed8d94eSDimitry Andric return *this; 983aed8d94eSDimitry Andric }); 984aed8d94eSDimitry Andric 985aed8d94eSDimitry Andric_LIBCPP_VARIANT_MOVE_ASSIGNMENT( 986aed8d94eSDimitry Andric _Trait::_Unavailable, 987aed8d94eSDimitry Andric __move_assignment& operator=(__move_assignment&&) = delete;); 988aed8d94eSDimitry Andric 989aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_MOVE_ASSIGNMENT 990aed8d94eSDimitry Andric 991aed8d94eSDimitry Andrictemplate <class _Traits, _Trait = _Traits::__copy_assignable_trait> 992aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __copy_assignment; 993aed8d94eSDimitry Andric 994aed8d94eSDimitry Andric#define _LIBCPP_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, \ 995aed8d94eSDimitry Andric copy_assignment) \ 996aed8d94eSDimitry Andric template <class... _Types> \ 997aed8d94eSDimitry Andric class _LIBCPP_TEMPLATE_VIS __copy_assignment<__traits<_Types...>, \ 998aed8d94eSDimitry Andric copy_assignable_trait> \ 999aed8d94eSDimitry Andric : public __move_assignment<__traits<_Types...>> { \ 1000aed8d94eSDimitry Andric using __base_type = __move_assignment<__traits<_Types...>>; \ 1001aed8d94eSDimitry Andric \ 1002aed8d94eSDimitry Andric public: \ 1003aed8d94eSDimitry Andric using __base_type::__base_type; \ 1004aed8d94eSDimitry Andric using __base_type::operator=; \ 1005aed8d94eSDimitry Andric \ 1006aed8d94eSDimitry Andric __copy_assignment(const __copy_assignment&) = default; \ 1007aed8d94eSDimitry Andric __copy_assignment(__copy_assignment&&) = default; \ 1008aed8d94eSDimitry Andric ~__copy_assignment() = default; \ 1009aed8d94eSDimitry Andric copy_assignment \ 1010aed8d94eSDimitry Andric __copy_assignment& operator=(__copy_assignment&&) = default; \ 1011aed8d94eSDimitry Andric } 1012aed8d94eSDimitry Andric 1013aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT( 1014aed8d94eSDimitry Andric _Trait::_TriviallyAvailable, 1015aed8d94eSDimitry Andric __copy_assignment& operator=(const __copy_assignment& __that) = default;); 1016aed8d94eSDimitry Andric 1017aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT( 1018aed8d94eSDimitry Andric _Trait::_Available, 1019aed8d94eSDimitry Andric __copy_assignment& operator=(const __copy_assignment& __that) { 1020aed8d94eSDimitry Andric this->__generic_assign(__that); 1021aed8d94eSDimitry Andric return *this; 1022aed8d94eSDimitry Andric }); 1023aed8d94eSDimitry Andric 1024aed8d94eSDimitry Andric_LIBCPP_VARIANT_COPY_ASSIGNMENT( 1025aed8d94eSDimitry Andric _Trait::_Unavailable, 1026aed8d94eSDimitry Andric __copy_assignment& operator=(const __copy_assignment&) = delete;); 1027aed8d94eSDimitry Andric 1028aed8d94eSDimitry Andric#undef _LIBCPP_VARIANT_COPY_ASSIGNMENT 1029aed8d94eSDimitry Andric 1030aed8d94eSDimitry Andrictemplate <class... _Types> 1031aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS __impl 1032aed8d94eSDimitry Andric : public __copy_assignment<__traits<_Types...>> { 1033aed8d94eSDimitry Andric using __base_type = __copy_assignment<__traits<_Types...>>; 1034aed8d94eSDimitry Andric 1035aed8d94eSDimitry Andricpublic: 1036aed8d94eSDimitry Andric using __base_type::__base_type; 1037aed8d94eSDimitry Andric using __base_type::operator=; 1038aed8d94eSDimitry Andric 1039aed8d94eSDimitry Andric template <size_t _Ip, class _Arg> 1040aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1041aed8d94eSDimitry Andric void __assign(_Arg&& __arg) { 1042aed8d94eSDimitry Andric this->__assign_alt(__access::__base::__get_alt<_Ip>(*this), 1043db17bf38SDimitry Andric _VSTD::forward<_Arg>(__arg)); 1044aed8d94eSDimitry Andric } 1045aed8d94eSDimitry Andric 1046aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1047aed8d94eSDimitry Andric void __swap(__impl& __that) { 1048aed8d94eSDimitry Andric if (this->valueless_by_exception() && __that.valueless_by_exception()) { 1049aed8d94eSDimitry Andric // do nothing. 1050aed8d94eSDimitry Andric } else if (this->index() == __that.index()) { 1051aed8d94eSDimitry Andric __visitation::__base::__visit_alt_at( 1052aed8d94eSDimitry Andric this->index(), 1053aed8d94eSDimitry Andric [](auto& __this_alt, auto& __that_alt) { 1054aed8d94eSDimitry Andric using _VSTD::swap; 1055aed8d94eSDimitry Andric swap(__this_alt.__value, __that_alt.__value); 1056aed8d94eSDimitry Andric }, 1057aed8d94eSDimitry Andric *this, 1058aed8d94eSDimitry Andric __that); 1059aed8d94eSDimitry Andric } else { 1060aed8d94eSDimitry Andric __impl* __lhs = this; 1061aed8d94eSDimitry Andric __impl* __rhs = _VSTD::addressof(__that); 1062aed8d94eSDimitry Andric if (__lhs->__move_nothrow() && !__rhs->__move_nothrow()) { 1063aed8d94eSDimitry Andric _VSTD::swap(__lhs, __rhs); 1064aed8d94eSDimitry Andric } 1065aed8d94eSDimitry Andric __impl __tmp(_VSTD::move(*__rhs)); 1066aed8d94eSDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 1067aed8d94eSDimitry Andric // EXTENSION: When the move construction of `__lhs` into `__rhs` throws 1068aed8d94eSDimitry Andric // and `__tmp` is nothrow move constructible then we move `__tmp` back 1069*b5893f02SDimitry Andric // into `__rhs` and provide the strong exception safety guarantee. 1070aed8d94eSDimitry Andric try { 1071aed8d94eSDimitry Andric this->__generic_construct(*__rhs, _VSTD::move(*__lhs)); 1072aed8d94eSDimitry Andric } catch (...) { 1073aed8d94eSDimitry Andric if (__tmp.__move_nothrow()) { 1074aed8d94eSDimitry Andric this->__generic_construct(*__rhs, _VSTD::move(__tmp)); 1075aed8d94eSDimitry Andric } 1076aed8d94eSDimitry Andric throw; 1077aed8d94eSDimitry Andric } 1078aed8d94eSDimitry Andric#else 1079aed8d94eSDimitry Andric this->__generic_construct(*__rhs, _VSTD::move(*__lhs)); 1080aed8d94eSDimitry Andric#endif 1081aed8d94eSDimitry Andric this->__generic_construct(*__lhs, _VSTD::move(__tmp)); 1082aed8d94eSDimitry Andric } 1083aed8d94eSDimitry Andric } 1084aed8d94eSDimitry Andric 1085aed8d94eSDimitry Andricprivate: 1086aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1087aed8d94eSDimitry Andric bool __move_nothrow() const { 1088aed8d94eSDimitry Andric constexpr bool __results[] = {is_nothrow_move_constructible_v<_Types>...}; 1089aed8d94eSDimitry Andric return this->valueless_by_exception() || __results[this->index()]; 1090aed8d94eSDimitry Andric } 1091aed8d94eSDimitry Andric}; 1092aed8d94eSDimitry Andric 1093aed8d94eSDimitry Andrictemplate <class... _Types> 1094aed8d94eSDimitry Andricstruct __overload; 1095aed8d94eSDimitry Andric 1096aed8d94eSDimitry Andrictemplate <> 1097aed8d94eSDimitry Andricstruct __overload<> { void operator()() const; }; 1098aed8d94eSDimitry Andric 1099aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1100aed8d94eSDimitry Andricstruct __overload<_Tp, _Types...> : __overload<_Types...> { 1101aed8d94eSDimitry Andric using __overload<_Types...>::operator(); 1102aed8d94eSDimitry Andric __identity<_Tp> operator()(_Tp) const; 1103aed8d94eSDimitry Andric}; 1104aed8d94eSDimitry Andric 1105aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1106aed8d94eSDimitry Andricusing __best_match_t = typename result_of_t<__overload<_Types...>(_Tp&&)>::type; 1107aed8d94eSDimitry Andric 1108aed8d94eSDimitry Andric} // __variant_detail 1109aed8d94eSDimitry Andric 1110aed8d94eSDimitry Andrictemplate <class... _Types> 1111aed8d94eSDimitry Andricclass _LIBCPP_TEMPLATE_VIS variant 1112aed8d94eSDimitry Andric : private __sfinae_ctor_base< 1113aed8d94eSDimitry Andric __all<is_copy_constructible_v<_Types>...>::value, 1114aed8d94eSDimitry Andric __all<is_move_constructible_v<_Types>...>::value>, 1115aed8d94eSDimitry Andric private __sfinae_assign_base< 1116aed8d94eSDimitry Andric __all<(is_copy_constructible_v<_Types> && 1117aed8d94eSDimitry Andric is_copy_assignable_v<_Types>)...>::value, 1118aed8d94eSDimitry Andric __all<(is_move_constructible_v<_Types> && 1119aed8d94eSDimitry Andric is_move_assignable_v<_Types>)...>::value> { 1120aed8d94eSDimitry Andric static_assert(0 < sizeof...(_Types), 1121aed8d94eSDimitry Andric "variant must consist of at least one alternative."); 1122aed8d94eSDimitry Andric 1123aed8d94eSDimitry Andric static_assert(__all<!is_array_v<_Types>...>::value, 1124aed8d94eSDimitry Andric "variant can not have an array type as an alternative."); 1125aed8d94eSDimitry Andric 1126aed8d94eSDimitry Andric static_assert(__all<!is_reference_v<_Types>...>::value, 1127aed8d94eSDimitry Andric "variant can not have a reference type as an alternative."); 1128aed8d94eSDimitry Andric 1129aed8d94eSDimitry Andric static_assert(__all<!is_void_v<_Types>...>::value, 1130aed8d94eSDimitry Andric "variant can not have a void type as an alternative."); 1131aed8d94eSDimitry Andric 1132aed8d94eSDimitry Andric using __first_type = variant_alternative_t<0, variant>; 1133aed8d94eSDimitry Andric 1134aed8d94eSDimitry Andricpublic: 1135aed8d94eSDimitry Andric template <bool _Dummy = true, 1136aed8d94eSDimitry Andric enable_if_t<__dependent_type<is_default_constructible<__first_type>, 1137aed8d94eSDimitry Andric _Dummy>::value, 1138aed8d94eSDimitry Andric int> = 0> 1139aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1140aed8d94eSDimitry Andric constexpr variant() noexcept(is_nothrow_default_constructible_v<__first_type>) 1141aed8d94eSDimitry Andric : __impl(in_place_index<0>) {} 1142aed8d94eSDimitry Andric 1143aed8d94eSDimitry Andric variant(const variant&) = default; 1144aed8d94eSDimitry Andric variant(variant&&) = default; 1145aed8d94eSDimitry Andric 1146aed8d94eSDimitry Andric template < 1147aed8d94eSDimitry Andric class _Arg, 11484ba319b5SDimitry Andric enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0, 11494ba319b5SDimitry Andric enable_if_t<!__is_inplace_type<__uncvref_t<_Arg>>::value, int> = 0, 11504ba319b5SDimitry Andric enable_if_t<!__is_inplace_index<__uncvref_t<_Arg>>::value, int> = 0, 1151aed8d94eSDimitry Andric class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>, 1152aed8d94eSDimitry Andric size_t _Ip = 1153aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1154aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0> 1155aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1156aed8d94eSDimitry Andric constexpr variant(_Arg&& __arg) noexcept( 1157aed8d94eSDimitry Andric is_nothrow_constructible_v<_Tp, _Arg>) 1158aed8d94eSDimitry Andric : __impl(in_place_index<_Ip>, _VSTD::forward<_Arg>(__arg)) {} 1159aed8d94eSDimitry Andric 1160aed8d94eSDimitry Andric template <size_t _Ip, class... _Args, 11615517e702SDimitry Andric class = enable_if_t<(_Ip < sizeof...(_Types)), int>, 1162aed8d94eSDimitry Andric class _Tp = variant_alternative_t<_Ip, variant<_Types...>>, 1163aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0> 1164aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1165aed8d94eSDimitry Andric explicit constexpr variant( 1166aed8d94eSDimitry Andric in_place_index_t<_Ip>, 1167aed8d94eSDimitry Andric _Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 1168aed8d94eSDimitry Andric : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {} 1169aed8d94eSDimitry Andric 1170aed8d94eSDimitry Andric template < 1171aed8d94eSDimitry Andric size_t _Ip, 1172aed8d94eSDimitry Andric class _Up, 1173aed8d94eSDimitry Andric class... _Args, 1174aed8d94eSDimitry Andric enable_if_t<(_Ip < sizeof...(_Types)), int> = 0, 1175aed8d94eSDimitry Andric class _Tp = variant_alternative_t<_Ip, variant<_Types...>>, 1176aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1177aed8d94eSDimitry Andric int> = 0> 1178aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1179aed8d94eSDimitry Andric explicit constexpr variant( 1180aed8d94eSDimitry Andric in_place_index_t<_Ip>, 1181aed8d94eSDimitry Andric initializer_list<_Up> __il, 1182aed8d94eSDimitry Andric _Args&&... __args) noexcept( 1183aed8d94eSDimitry Andric is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) 1184aed8d94eSDimitry Andric : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {} 1185aed8d94eSDimitry Andric 1186aed8d94eSDimitry Andric template < 1187aed8d94eSDimitry Andric class _Tp, 1188aed8d94eSDimitry Andric class... _Args, 1189aed8d94eSDimitry Andric size_t _Ip = 1190aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1191aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0> 1192aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1193aed8d94eSDimitry Andric explicit constexpr variant(in_place_type_t<_Tp>, _Args&&... __args) noexcept( 1194aed8d94eSDimitry Andric is_nothrow_constructible_v<_Tp, _Args...>) 1195aed8d94eSDimitry Andric : __impl(in_place_index<_Ip>, _VSTD::forward<_Args>(__args)...) {} 1196aed8d94eSDimitry Andric 1197aed8d94eSDimitry Andric template < 1198aed8d94eSDimitry Andric class _Tp, 1199aed8d94eSDimitry Andric class _Up, 1200aed8d94eSDimitry Andric class... _Args, 1201aed8d94eSDimitry Andric size_t _Ip = 1202aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1203aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1204aed8d94eSDimitry Andric int> = 0> 1205aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1206aed8d94eSDimitry Andric explicit constexpr variant( 1207aed8d94eSDimitry Andric in_place_type_t<_Tp>, 1208aed8d94eSDimitry Andric initializer_list<_Up> __il, 1209aed8d94eSDimitry Andric _Args&&... __args) noexcept( 1210aed8d94eSDimitry Andric is_nothrow_constructible_v<_Tp, initializer_list< _Up>&, _Args...>) 1211aed8d94eSDimitry Andric : __impl(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {} 1212aed8d94eSDimitry Andric 1213aed8d94eSDimitry Andric ~variant() = default; 1214aed8d94eSDimitry Andric 1215aed8d94eSDimitry Andric variant& operator=(const variant&) = default; 1216aed8d94eSDimitry Andric variant& operator=(variant&&) = default; 1217aed8d94eSDimitry Andric 1218aed8d94eSDimitry Andric template < 1219aed8d94eSDimitry Andric class _Arg, 12204ba319b5SDimitry Andric enable_if_t<!is_same_v<__uncvref_t<_Arg>, variant>, int> = 0, 1221aed8d94eSDimitry Andric class _Tp = __variant_detail::__best_match_t<_Arg, _Types...>, 1222aed8d94eSDimitry Andric size_t _Ip = 1223aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1224aed8d94eSDimitry Andric enable_if_t<is_assignable_v<_Tp&, _Arg> && is_constructible_v<_Tp, _Arg>, 1225aed8d94eSDimitry Andric int> = 0> 1226aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1227aed8d94eSDimitry Andric variant& operator=(_Arg&& __arg) noexcept( 1228aed8d94eSDimitry Andric is_nothrow_assignable_v<_Tp&, _Arg> && 1229aed8d94eSDimitry Andric is_nothrow_constructible_v<_Tp, _Arg>) { 1230aed8d94eSDimitry Andric __impl.template __assign<_Ip>(_VSTD::forward<_Arg>(__arg)); 1231aed8d94eSDimitry Andric return *this; 1232aed8d94eSDimitry Andric } 1233aed8d94eSDimitry Andric 1234aed8d94eSDimitry Andric template < 1235aed8d94eSDimitry Andric size_t _Ip, 1236aed8d94eSDimitry Andric class... _Args, 1237aed8d94eSDimitry Andric enable_if_t<(_Ip < sizeof...(_Types)), int> = 0, 1238aed8d94eSDimitry Andric class _Tp = variant_alternative_t<_Ip, variant<_Types...>>, 1239aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0> 1240aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1241540d2a8bSDimitry Andric _Tp& emplace(_Args&&... __args) { 1242540d2a8bSDimitry Andric return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...); 1243aed8d94eSDimitry Andric } 1244aed8d94eSDimitry Andric 1245aed8d94eSDimitry Andric template < 1246aed8d94eSDimitry Andric size_t _Ip, 1247aed8d94eSDimitry Andric class _Up, 1248aed8d94eSDimitry Andric class... _Args, 1249aed8d94eSDimitry Andric enable_if_t<(_Ip < sizeof...(_Types)), int> = 0, 1250aed8d94eSDimitry Andric class _Tp = variant_alternative_t<_Ip, variant<_Types...>>, 1251aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1252aed8d94eSDimitry Andric int> = 0> 1253aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1254540d2a8bSDimitry Andric _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) { 1255540d2a8bSDimitry Andric return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...); 1256aed8d94eSDimitry Andric } 1257aed8d94eSDimitry Andric 1258aed8d94eSDimitry Andric template < 1259aed8d94eSDimitry Andric class _Tp, 1260aed8d94eSDimitry Andric class... _Args, 1261aed8d94eSDimitry Andric size_t _Ip = 1262aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1263aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0> 1264aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1265540d2a8bSDimitry Andric _Tp& emplace(_Args&&... __args) { 1266540d2a8bSDimitry Andric return __impl.template __emplace<_Ip>(_VSTD::forward<_Args>(__args)...); 1267aed8d94eSDimitry Andric } 1268aed8d94eSDimitry Andric 1269aed8d94eSDimitry Andric template < 1270aed8d94eSDimitry Andric class _Tp, 1271aed8d94eSDimitry Andric class _Up, 1272aed8d94eSDimitry Andric class... _Args, 1273aed8d94eSDimitry Andric size_t _Ip = 1274aed8d94eSDimitry Andric __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value, 1275aed8d94eSDimitry Andric enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1276aed8d94eSDimitry Andric int> = 0> 1277aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1278540d2a8bSDimitry Andric _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) { 1279540d2a8bSDimitry Andric return __impl.template __emplace<_Ip>(__il, _VSTD::forward<_Args>(__args)...); 1280aed8d94eSDimitry Andric } 1281aed8d94eSDimitry Andric 1282aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1283aed8d94eSDimitry Andric constexpr bool valueless_by_exception() const noexcept { 1284aed8d94eSDimitry Andric return __impl.valueless_by_exception(); 1285aed8d94eSDimitry Andric } 1286aed8d94eSDimitry Andric 1287aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1288aed8d94eSDimitry Andric constexpr size_t index() const noexcept { return __impl.index(); } 1289aed8d94eSDimitry Andric 1290aed8d94eSDimitry Andric template < 1291aed8d94eSDimitry Andric bool _Dummy = true, 1292aed8d94eSDimitry Andric enable_if_t< 1293aed8d94eSDimitry Andric __all<( 1294aed8d94eSDimitry Andric __dependent_type<is_move_constructible<_Types>, _Dummy>::value && 1295aed8d94eSDimitry Andric __dependent_type<is_swappable<_Types>, _Dummy>::value)...>::value, 1296aed8d94eSDimitry Andric int> = 0> 1297aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1298aed8d94eSDimitry Andric void swap(variant& __that) noexcept( 1299aed8d94eSDimitry Andric __all<(is_nothrow_move_constructible_v<_Types> && 1300aed8d94eSDimitry Andric is_nothrow_swappable_v<_Types>)...>::value) { 1301aed8d94eSDimitry Andric __impl.__swap(__that.__impl); 1302aed8d94eSDimitry Andric } 1303aed8d94eSDimitry Andric 1304aed8d94eSDimitry Andricprivate: 1305aed8d94eSDimitry Andric __variant_detail::__impl<_Types...> __impl; 1306aed8d94eSDimitry Andric 1307aed8d94eSDimitry Andric friend struct __variant_detail::__access::__variant; 1308aed8d94eSDimitry Andric friend struct __variant_detail::__visitation::__variant; 1309aed8d94eSDimitry Andric}; 1310aed8d94eSDimitry Andric 1311aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1312aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1313aed8d94eSDimitry Andricconstexpr bool __holds_alternative(const variant<_Types...>& __v) noexcept { 1314aed8d94eSDimitry Andric return __v.index() == _Ip; 1315aed8d94eSDimitry Andric} 1316aed8d94eSDimitry Andric 1317aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1318aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1319aed8d94eSDimitry Andricconstexpr bool holds_alternative(const variant<_Types...>& __v) noexcept { 1320aed8d94eSDimitry Andric return __holds_alternative<__find_exactly_one_t<_Tp, _Types...>::value>(__v); 1321aed8d94eSDimitry Andric} 1322aed8d94eSDimitry Andric 1323aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Vp> 1324aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1325*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1326*b5893f02SDimitry Andricconstexpr auto&& __generic_get(_Vp&& __v) { 1327aed8d94eSDimitry Andric using __variant_detail::__access::__variant; 1328aed8d94eSDimitry Andric if (!__holds_alternative<_Ip>(__v)) { 1329aed8d94eSDimitry Andric __throw_bad_variant_access(); 1330aed8d94eSDimitry Andric } 1331aed8d94eSDimitry Andric return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value; 1332aed8d94eSDimitry Andric} 1333aed8d94eSDimitry Andric 1334aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1335aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1336*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1337aed8d94eSDimitry Andricconstexpr variant_alternative_t<_Ip, variant<_Types...>>& get( 1338aed8d94eSDimitry Andric variant<_Types...>& __v) { 1339aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1340aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1341aed8d94eSDimitry Andric return __generic_get<_Ip>(__v); 1342aed8d94eSDimitry Andric} 1343aed8d94eSDimitry Andric 1344aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1345aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1346*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1347aed8d94eSDimitry Andricconstexpr variant_alternative_t<_Ip, variant<_Types...>>&& get( 1348aed8d94eSDimitry Andric variant<_Types...>&& __v) { 1349aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1350aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1351aed8d94eSDimitry Andric return __generic_get<_Ip>(_VSTD::move(__v)); 1352aed8d94eSDimitry Andric} 1353aed8d94eSDimitry Andric 1354aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1355aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1356*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1357aed8d94eSDimitry Andricconstexpr const variant_alternative_t<_Ip, variant<_Types...>>& get( 1358aed8d94eSDimitry Andric const variant<_Types...>& __v) { 1359aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1360aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1361aed8d94eSDimitry Andric return __generic_get<_Ip>(__v); 1362aed8d94eSDimitry Andric} 1363aed8d94eSDimitry Andric 1364aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1365aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1366*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1367aed8d94eSDimitry Andricconstexpr const variant_alternative_t<_Ip, variant<_Types...>>&& get( 1368aed8d94eSDimitry Andric const variant<_Types...>&& __v) { 1369aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1370aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1371aed8d94eSDimitry Andric return __generic_get<_Ip>(_VSTD::move(__v)); 1372aed8d94eSDimitry Andric} 1373aed8d94eSDimitry Andric 1374aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1375aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1376*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1377aed8d94eSDimitry Andricconstexpr _Tp& get(variant<_Types...>& __v) { 1378aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1379aed8d94eSDimitry Andric return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); 1380aed8d94eSDimitry Andric} 1381aed8d94eSDimitry Andric 1382aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1383aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1384*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1385aed8d94eSDimitry Andricconstexpr _Tp&& get(variant<_Types...>&& __v) { 1386aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1387aed8d94eSDimitry Andric return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>( 1388aed8d94eSDimitry Andric _VSTD::move(__v)); 1389aed8d94eSDimitry Andric} 1390aed8d94eSDimitry Andric 1391aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1392aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1393*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1394aed8d94eSDimitry Andricconstexpr const _Tp& get(const variant<_Types...>& __v) { 1395aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1396aed8d94eSDimitry Andric return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); 1397aed8d94eSDimitry Andric} 1398aed8d94eSDimitry Andric 1399aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1400aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1401*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1402aed8d94eSDimitry Andricconstexpr const _Tp&& get(const variant<_Types...>&& __v) { 1403aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1404aed8d94eSDimitry Andric return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>( 1405aed8d94eSDimitry Andric _VSTD::move(__v)); 1406aed8d94eSDimitry Andric} 1407aed8d94eSDimitry Andric 1408aed8d94eSDimitry Andrictemplate <size_t _Ip, class _Vp> 1409aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1410aed8d94eSDimitry Andricconstexpr auto* __generic_get_if(_Vp* __v) noexcept { 1411aed8d94eSDimitry Andric using __variant_detail::__access::__variant; 1412aed8d94eSDimitry Andric return __v && __holds_alternative<_Ip>(*__v) 1413aed8d94eSDimitry Andric ? _VSTD::addressof(__variant::__get_alt<_Ip>(*__v).__value) 1414aed8d94eSDimitry Andric : nullptr; 1415aed8d94eSDimitry Andric} 1416aed8d94eSDimitry Andric 1417aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1418aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1419aed8d94eSDimitry Andricconstexpr add_pointer_t<variant_alternative_t<_Ip, variant<_Types...>>> 1420aed8d94eSDimitry Andricget_if(variant<_Types...>* __v) noexcept { 1421aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1422aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1423aed8d94eSDimitry Andric return __generic_get_if<_Ip>(__v); 1424aed8d94eSDimitry Andric} 1425aed8d94eSDimitry Andric 1426aed8d94eSDimitry Andrictemplate <size_t _Ip, class... _Types> 1427aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1428aed8d94eSDimitry Andricconstexpr add_pointer_t<const variant_alternative_t<_Ip, variant<_Types...>>> 1429aed8d94eSDimitry Andricget_if(const variant<_Types...>* __v) noexcept { 1430aed8d94eSDimitry Andric static_assert(_Ip < sizeof...(_Types)); 1431aed8d94eSDimitry Andric static_assert(!is_void_v<variant_alternative_t<_Ip, variant<_Types...>>>); 1432aed8d94eSDimitry Andric return __generic_get_if<_Ip>(__v); 1433aed8d94eSDimitry Andric} 1434aed8d94eSDimitry Andric 1435aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1436aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1437aed8d94eSDimitry Andricconstexpr add_pointer_t<_Tp> 1438aed8d94eSDimitry Andricget_if(variant<_Types...>* __v) noexcept { 1439aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1440aed8d94eSDimitry Andric return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v); 1441aed8d94eSDimitry Andric} 1442aed8d94eSDimitry Andric 1443aed8d94eSDimitry Andrictemplate <class _Tp, class... _Types> 1444aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1445aed8d94eSDimitry Andricconstexpr add_pointer_t<const _Tp> 1446aed8d94eSDimitry Andricget_if(const variant<_Types...>* __v) noexcept { 1447aed8d94eSDimitry Andric static_assert(!is_void_v<_Tp>); 1448aed8d94eSDimitry Andric return _VSTD::get_if<__find_exactly_one_t<_Tp, _Types...>::value>(__v); 1449aed8d94eSDimitry Andric} 1450aed8d94eSDimitry Andric 1451*b5893f02SDimitry Andrictemplate <class _Operator> 1452*b5893f02SDimitry Andricstruct __convert_to_bool { 1453*b5893f02SDimitry Andric template <class _T1, class _T2> 1454*b5893f02SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr bool operator()(_T1 && __t1, _T2&& __t2) const { 1455*b5893f02SDimitry Andric static_assert(std::is_convertible<decltype(_Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2))), bool>::value, 1456*b5893f02SDimitry Andric "the relational operator does not return a type which is implicitly convertible to bool"); 1457*b5893f02SDimitry Andric return _Operator{}(_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); 1458*b5893f02SDimitry Andric } 1459*b5893f02SDimitry Andric}; 1460*b5893f02SDimitry Andric 1461aed8d94eSDimitry Andrictemplate <class... _Types> 1462aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1463aed8d94eSDimitry Andricconstexpr bool operator==(const variant<_Types...>& __lhs, 1464aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1465aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1466aed8d94eSDimitry Andric if (__lhs.index() != __rhs.index()) return false; 1467aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return true; 1468*b5893f02SDimitry Andric return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<equal_to<>>{}, __lhs, __rhs); 1469aed8d94eSDimitry Andric} 1470aed8d94eSDimitry Andric 1471aed8d94eSDimitry Andrictemplate <class... _Types> 1472aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1473aed8d94eSDimitry Andricconstexpr bool operator!=(const variant<_Types...>& __lhs, 1474aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1475aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1476aed8d94eSDimitry Andric if (__lhs.index() != __rhs.index()) return true; 1477aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return false; 1478aed8d94eSDimitry Andric return __variant::__visit_value_at( 1479*b5893f02SDimitry Andric __lhs.index(), __convert_to_bool<not_equal_to<>>{}, __lhs, __rhs); 1480aed8d94eSDimitry Andric} 1481aed8d94eSDimitry Andric 1482aed8d94eSDimitry Andrictemplate <class... _Types> 1483aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1484aed8d94eSDimitry Andricconstexpr bool operator<(const variant<_Types...>& __lhs, 1485aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1486aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1487aed8d94eSDimitry Andric if (__rhs.valueless_by_exception()) return false; 1488aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return true; 1489aed8d94eSDimitry Andric if (__lhs.index() < __rhs.index()) return true; 1490aed8d94eSDimitry Andric if (__lhs.index() > __rhs.index()) return false; 1491*b5893f02SDimitry Andric return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<less<>>{}, __lhs, __rhs); 1492aed8d94eSDimitry Andric} 1493aed8d94eSDimitry Andric 1494aed8d94eSDimitry Andrictemplate <class... _Types> 1495aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1496aed8d94eSDimitry Andricconstexpr bool operator>(const variant<_Types...>& __lhs, 1497aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1498aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1499aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return false; 1500aed8d94eSDimitry Andric if (__rhs.valueless_by_exception()) return true; 1501aed8d94eSDimitry Andric if (__lhs.index() > __rhs.index()) return true; 1502aed8d94eSDimitry Andric if (__lhs.index() < __rhs.index()) return false; 1503*b5893f02SDimitry Andric return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<greater<>>{}, __lhs, __rhs); 1504aed8d94eSDimitry Andric} 1505aed8d94eSDimitry Andric 1506aed8d94eSDimitry Andrictemplate <class... _Types> 1507aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1508aed8d94eSDimitry Andricconstexpr bool operator<=(const variant<_Types...>& __lhs, 1509aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1510aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1511aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return true; 1512aed8d94eSDimitry Andric if (__rhs.valueless_by_exception()) return false; 1513aed8d94eSDimitry Andric if (__lhs.index() < __rhs.index()) return true; 1514aed8d94eSDimitry Andric if (__lhs.index() > __rhs.index()) return false; 1515aed8d94eSDimitry Andric return __variant::__visit_value_at( 1516*b5893f02SDimitry Andric __lhs.index(), __convert_to_bool<less_equal<>>{}, __lhs, __rhs); 1517aed8d94eSDimitry Andric} 1518aed8d94eSDimitry Andric 1519aed8d94eSDimitry Andrictemplate <class... _Types> 1520aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1521aed8d94eSDimitry Andricconstexpr bool operator>=(const variant<_Types...>& __lhs, 1522aed8d94eSDimitry Andric const variant<_Types...>& __rhs) { 1523aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1524aed8d94eSDimitry Andric if (__rhs.valueless_by_exception()) return true; 1525aed8d94eSDimitry Andric if (__lhs.valueless_by_exception()) return false; 1526aed8d94eSDimitry Andric if (__lhs.index() > __rhs.index()) return true; 1527aed8d94eSDimitry Andric if (__lhs.index() < __rhs.index()) return false; 1528aed8d94eSDimitry Andric return __variant::__visit_value_at( 1529*b5893f02SDimitry Andric __lhs.index(), __convert_to_bool<greater_equal<>>{}, __lhs, __rhs); 1530aed8d94eSDimitry Andric} 1531aed8d94eSDimitry Andric 1532aed8d94eSDimitry Andrictemplate <class _Visitor, class... _Vs> 1533aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1534*b5893f02SDimitry Andric_LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS 1535aed8d94eSDimitry Andricconstexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { 1536aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1537aed8d94eSDimitry Andric bool __results[] = {__vs.valueless_by_exception()...}; 1538aed8d94eSDimitry Andric for (bool __result : __results) { 1539aed8d94eSDimitry Andric if (__result) { 1540aed8d94eSDimitry Andric __throw_bad_variant_access(); 1541aed8d94eSDimitry Andric } 1542aed8d94eSDimitry Andric } 1543aed8d94eSDimitry Andric return __variant::__visit_value(_VSTD::forward<_Visitor>(__visitor), 1544aed8d94eSDimitry Andric _VSTD::forward<_Vs>(__vs)...); 1545aed8d94eSDimitry Andric} 1546aed8d94eSDimitry Andric 1547aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS monostate {}; 1548aed8d94eSDimitry Andric 1549aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1550aed8d94eSDimitry Andricconstexpr bool operator<(monostate, monostate) noexcept { return false; } 1551aed8d94eSDimitry Andric 1552aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1553aed8d94eSDimitry Andricconstexpr bool operator>(monostate, monostate) noexcept { return false; } 1554aed8d94eSDimitry Andric 1555aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1556aed8d94eSDimitry Andricconstexpr bool operator<=(monostate, monostate) noexcept { return true; } 1557aed8d94eSDimitry Andric 1558aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1559aed8d94eSDimitry Andricconstexpr bool operator>=(monostate, monostate) noexcept { return true; } 1560aed8d94eSDimitry Andric 1561aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1562aed8d94eSDimitry Andricconstexpr bool operator==(monostate, monostate) noexcept { return true; } 1563aed8d94eSDimitry Andric 1564aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1565aed8d94eSDimitry Andricconstexpr bool operator!=(monostate, monostate) noexcept { return false; } 1566aed8d94eSDimitry Andric 1567aed8d94eSDimitry Andrictemplate <class... _Types> 1568aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 1569aed8d94eSDimitry Andricauto swap(variant<_Types...>& __lhs, 1570aed8d94eSDimitry Andric variant<_Types...>& __rhs) noexcept(noexcept(__lhs.swap(__rhs))) 1571aed8d94eSDimitry Andric -> decltype(__lhs.swap(__rhs)) { 1572aed8d94eSDimitry Andric __lhs.swap(__rhs); 1573aed8d94eSDimitry Andric} 1574aed8d94eSDimitry Andric 1575aed8d94eSDimitry Andrictemplate <class... _Types> 1576540d2a8bSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash< 1577540d2a8bSDimitry Andric __enable_hash_helper<variant<_Types...>, remove_const_t<_Types>...>> { 1578aed8d94eSDimitry Andric using argument_type = variant<_Types...>; 1579aed8d94eSDimitry Andric using result_type = size_t; 1580aed8d94eSDimitry Andric 1581aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1582aed8d94eSDimitry Andric result_type operator()(const argument_type& __v) const { 1583aed8d94eSDimitry Andric using __variant_detail::__visitation::__variant; 1584aed8d94eSDimitry Andric size_t __res = 1585aed8d94eSDimitry Andric __v.valueless_by_exception() 1586aed8d94eSDimitry Andric ? 299792458 // Random value chosen by the universe upon creation 1587aed8d94eSDimitry Andric : __variant::__visit_alt( 1588aed8d94eSDimitry Andric [](const auto& __alt) { 15894ba319b5SDimitry Andric using __alt_type = __uncvref_t<decltype(__alt)>; 1590540d2a8bSDimitry Andric using __value_type = remove_const_t< 1591540d2a8bSDimitry Andric typename __alt_type::__value_type>; 1592aed8d94eSDimitry Andric return hash<__value_type>{}(__alt.__value); 1593aed8d94eSDimitry Andric }, 1594aed8d94eSDimitry Andric __v); 1595aed8d94eSDimitry Andric return __hash_combine(__res, hash<size_t>{}(__v.index())); 1596aed8d94eSDimitry Andric } 1597aed8d94eSDimitry Andric}; 1598aed8d94eSDimitry Andric 1599aed8d94eSDimitry Andrictemplate <> 1600aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS hash<monostate> { 1601aed8d94eSDimitry Andric using argument_type = monostate; 1602aed8d94eSDimitry Andric using result_type = size_t; 1603aed8d94eSDimitry Andric 1604aed8d94eSDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 1605540d2a8bSDimitry Andric result_type operator()(const argument_type&) const _NOEXCEPT { 1606aed8d94eSDimitry Andric return 66740831; // return a fundamentally attractive random value. 1607aed8d94eSDimitry Andric } 1608aed8d94eSDimitry Andric}; 1609aed8d94eSDimitry Andric 1610aed8d94eSDimitry Andric#endif // _LIBCPP_STD_VER > 14 1611aed8d94eSDimitry Andric 1612aed8d94eSDimitry Andric_LIBCPP_END_NAMESPACE_STD 1613aed8d94eSDimitry Andric 1614b2c7081bSDimitry Andric_LIBCPP_POP_MACROS 1615b2c7081bSDimitry Andric 1616aed8d94eSDimitry Andric#endif // _LIBCPP_VARIANT 1617