Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:47

0001 // Range v3 library
0002 //
0003 //  Copyright Eric Niebler 2014-present
0004 //
0005 //  Use, modification and distribution is subject to the
0006 //  Boost Software License, Version 1.0. (See accompanying
0007 //  file LICENSE_1_0.txt or copy at
0008 //  http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // Project home: https://github.com/ericniebler/range-v3
0011 //
0012 
0013 #ifndef RANGES_V3_DETAIL_VARIANT_HPP
0014 #define RANGES_V3_DETAIL_VARIANT_HPP
0015 
0016 #include <iterator>
0017 #include <memory>
0018 #include <new>
0019 #include <stdexcept>
0020 #include <tuple>
0021 #include <type_traits>
0022 #include <utility>
0023 
0024 #include <meta/meta.hpp>
0025 
0026 #include <concepts/concepts.hpp>
0027 
0028 #include <range/v3/range_fwd.hpp>
0029 
0030 #include <range/v3/functional/compose.hpp>
0031 #include <range/v3/functional/identity.hpp>
0032 #include <range/v3/functional/invoke.hpp>
0033 #include <range/v3/iterator/concepts.hpp>
0034 #include <range/v3/iterator/traits.hpp>
0035 #include <range/v3/utility/get.hpp>
0036 
0037 #include <range/v3/detail/prologue.hpp>
0038 
0039 namespace ranges
0040 {
0041     template<std::size_t I>
0042     struct emplaced_index_t;
0043 
0044     template<std::size_t I>
0045     struct emplaced_index_t : meta::size_t<I>
0046     {};
0047 
0048 #if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
0049     namespace
0050     {
0051         template<std::size_t I>
0052         constexpr auto & emplaced_index = static_const<emplaced_index_t<I>>::value;
0053     }
0054 #else  // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
0055     template<std::size_t I>
0056     inline constexpr emplaced_index_t<I> emplaced_index{};
0057 #endif // RANGES_CXX_INLINE_VARIABLES
0058 
0059     struct bad_variant_access : std::logic_error
0060     {
0061         explicit bad_variant_access(std::string const & what_arg)
0062           : std::logic_error(what_arg)
0063         {}
0064         explicit bad_variant_access(char const * what_arg)
0065           : std::logic_error(what_arg)
0066         {}
0067     };
0068 
0069     template<typename T, std::size_t Index>
0070     struct indexed_element
0071     {
0072     private:
0073         std::add_pointer_t<T> t_;
0074 
0075     public:
0076         constexpr explicit indexed_element(T & t) noexcept
0077           : t_(std::addressof(t))
0078         {}
0079         constexpr T & get() const noexcept
0080         {
0081             return *t_;
0082         }
0083     };
0084     template<typename T, std::size_t Index>
0085     struct indexed_element<T &&, Index>
0086     {
0087     private:
0088         T * t_;
0089 
0090     public:
0091         constexpr explicit indexed_element(T && t) noexcept
0092           : t_(std::addressof(t))
0093         {}
0094         constexpr T && get() const noexcept
0095         {
0096             return static_cast<T &&>(*t_);
0097         }
0098     };
0099     template<std::size_t Index>
0100     struct indexed_element<void, Index>
0101     {
0102         void get() const noexcept
0103         {}
0104     };
0105 
0106     /// \cond
0107     namespace detail
0108     {
0109         struct indexed_element_fn;
0110 
0111         template(typename I, typename S, typename O)(
0112             requires (!sized_sentinel_for<S, I>)) //
0113         O uninitialized_copy(I first, S last, O out)
0114         {
0115             for(; first != last; ++first, ++out)
0116                 ::new((void *)std::addressof(*out)) iter_value_t<O>(*first);
0117             return out;
0118         }
0119 
0120         template(typename I, typename S, typename O)(
0121             requires sized_sentinel_for<S, I>)
0122         O uninitialized_copy(I first, S last, O out)
0123         {
0124             return std::uninitialized_copy_n(first, (last - first), out);
0125         }
0126 
0127         template<typename I, typename O>
0128         O uninitialized_copy(I first, I last, O out)
0129         {
0130             return std::uninitialized_copy(first, last, out);
0131         }
0132 
0133         template<typename T, typename Index>
0134         struct indexed_datum
0135         {
0136         private:
0137             template<typename, typename>
0138             friend struct indexed_datum;
0139             T datum_;
0140 
0141         public:
0142             CPP_member
0143             constexpr CPP_ctor(indexed_datum)()(                          //
0144                 noexcept(std::is_nothrow_default_constructible<T>::value) //
0145                     requires default_constructible<T>)
0146               : datum_{}
0147             {}
0148             template(typename... Ts)(
0149                 requires constructible_from<T, Ts...> AND (sizeof...(Ts) != 0)) //
0150             constexpr indexed_datum(Ts &&... ts) noexcept(
0151                     std::is_nothrow_constructible<T, Ts...>::value)
0152               : datum_(static_cast<Ts &&>(ts)...)
0153             {}
0154             template(typename U)(
0155                 requires (!same_as<T, U>) AND convertible_to<U, T>)
0156             constexpr indexed_datum(indexed_datum<U, Index> that) //
0157                 noexcept(std::is_nothrow_constructible<T, U>::value) //
0158               : datum_(std::move(that.datum_))
0159             {}
0160             constexpr auto ref() noexcept
0161             {
0162                 return indexed_element<T, Index::value>{datum_};
0163             }
0164             constexpr auto ref() const noexcept
0165             {
0166                 return indexed_element<T const, Index::value>{datum_};
0167             }
0168             constexpr T & get() noexcept
0169             {
0170                 return datum_;
0171             }
0172             constexpr T const & get() const noexcept
0173             {
0174                 return datum_;
0175             }
0176         };
0177 
0178         template<typename T, std::size_t N, typename Index>
0179         struct indexed_datum<T[N], Index>;
0180 
0181         template<typename T, typename Index>
0182         struct indexed_datum<T &, Index>
0183         {
0184         private:
0185             template<typename, typename>
0186             friend struct indexed_datum;
0187             T * t_;
0188 
0189         public:
0190             constexpr indexed_datum(T & t) noexcept
0191               : t_(std::addressof(t))
0192             {}
0193             constexpr T & get() const noexcept
0194             {
0195                 return *t_;
0196             }
0197             constexpr auto ref() const noexcept
0198             {
0199                 return indexed_element<T &, Index::value>{*t_};
0200             }
0201         };
0202         template<typename T, typename Index>
0203         struct indexed_datum<T &&, Index>
0204         {
0205         private:
0206             template<typename, typename>
0207             friend struct indexed_datum;
0208             T * t_;
0209 
0210         public:
0211             constexpr indexed_datum(T && t) noexcept
0212               : t_(std::addressof(t))
0213             {}
0214             constexpr T && get() const noexcept
0215             {
0216                 return static_cast<T &&>(*t_);
0217             }
0218             constexpr auto ref() const noexcept
0219             {
0220                 return indexed_element<T &&, Index::value>{static_cast<T &&>(*t_)};
0221             }
0222         };
0223         template<typename Index>
0224         struct indexed_datum<void, Index>
0225         {
0226             void get() const noexcept
0227             {}
0228             constexpr indexed_element<void, Index::value> ref() const noexcept
0229             {
0230                 return {};
0231             }
0232         };
0233 
0234         template<std::size_t Index, typename... Ts>
0235         using variant_datum_t =
0236             detail::indexed_datum<meta::at_c<meta::list<Ts...>, Index>,
0237                                   meta::size_t<Index>>;
0238 
0239         using variant_nil = indexed_datum<void, meta::npos>;
0240 
0241         template<typename Ts,
0242                  bool Trivial = meta::apply<
0243                      meta::quote<meta::and_>,
0244                      meta::transform<Ts, meta::quote<std::is_trivially_destructible>>>::
0245                      type::value>
0246         struct variant_data_
0247         {
0248             using type = indexed_datum<void, meta::npos>;
0249         };
0250 
0251         template<typename T, typename... Ts>
0252         struct variant_data_<meta::list<T, Ts...>, true>
0253         {
0254             struct type
0255             {
0256                 using head_t = T;
0257                 using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
0258                 union
0259                 {
0260                     head_t head;
0261                     tail_t tail;
0262                 };
0263 
0264                 type() noexcept
0265                 {}
0266                 template<typename... Args>
0267                 constexpr type(meta::size_t<0>, Args &&... args) noexcept(
0268                     std::is_nothrow_constructible<head_t, Args...>::value)
0269                   : head{((Args &&) args)...}
0270                 {}
0271                 template<std::size_t N, typename... Args>
0272                 constexpr type(meta::size_t<N>, Args &&... args) noexcept(
0273                     std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
0274                                                   Args...>::value)
0275                   : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
0276                 {}
0277             };
0278         };
0279 
0280         template<typename T, typename... Ts>
0281         struct variant_data_<meta::list<T, Ts...>, false>
0282         {
0283             struct type
0284             {
0285                 using head_t = T;
0286                 using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
0287                 union
0288                 {
0289                     head_t head;
0290                     tail_t tail;
0291                 };
0292 
0293                 type() noexcept
0294                 {}
0295                 ~type()
0296                 {}
0297                 template<typename... Args>
0298                 constexpr type(meta::size_t<0>, Args &&... args) noexcept(
0299                     std::is_nothrow_constructible<head_t, Args...>::value)
0300                   : head{((Args &&) args)...}
0301                 {}
0302                 template<std::size_t N, typename... Args>
0303                 constexpr type(meta::size_t<N>, Args &&... args) noexcept(
0304                     std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
0305                                                   Args...>::value)
0306                   : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
0307                 {}
0308             };
0309         };
0310 
0311         template<typename... Ts>
0312         using variant_data = meta::_t<variant_data_<meta::transform<
0313             meta::list<Ts...>, meta::as_list<meta::make_index_sequence<sizeof...(Ts)>>,
0314             meta::quote<indexed_datum>>>>;
0315 
0316         inline std::size_t variant_move_copy_(std::size_t, variant_nil, variant_nil)
0317         {
0318             return 0;
0319         }
0320         template<typename Data0, typename Data1>
0321         std::size_t variant_move_copy_(std::size_t n, Data0 & self, Data1 && that)
0322         {
0323             using Head = typename Data0::head_t;
0324             return 0 == n
0325                        ? ((void)::new((void *)&self.head) Head(((Data1 &&) that).head), 0)
0326                        : variant_move_copy_(n - 1, self.tail, ((Data1 &&) that).tail) + 1;
0327         }
0328         constexpr bool variant_equal_(std::size_t, variant_nil, variant_nil)
0329         {
0330             return true;
0331         }
0332         template<typename Data0, typename Data1>
0333         constexpr bool variant_equal_(std::size_t n, Data0 const & self,
0334                                       Data1 const & that)
0335         {
0336             return n == 0 ? self.head.get() == that.head.get()
0337                           : variant_equal_(n - 1, self.tail, that.tail);
0338         }
0339         template<typename Fun, typename Proj = indexed_element_fn>
0340         constexpr int variant_visit_(std::size_t, variant_nil, Fun, Proj = {})
0341         {
0342             return (RANGES_EXPECT(false), 0);
0343         }
0344         template<typename Data, typename Fun, typename Proj = indexed_element_fn>
0345         constexpr int variant_visit_(std::size_t n, Data & self, Fun fun, Proj proj = {})
0346         {
0347             return 0 == n ? ((void)invoke(fun, invoke(proj, self.head)), 0)
0348                           : detail::variant_visit_(
0349                                 n - 1, self.tail, detail::move(fun), detail::move(proj));
0350         }
0351 
0352         struct get_datum_fn
0353         {
0354             template<typename T>
0355             decltype(auto) operator()(T && t) const noexcept
0356             {
0357                 return t.get();
0358             }
0359         };
0360 
0361         struct indexed_element_fn
0362         {
0363             template<typename T>
0364             decltype(auto) operator()(T && t) const noexcept
0365             {
0366                 return t.ref();
0367             }
0368         };
0369 
0370         struct empty_variant_tag
0371         {};
0372 
0373         struct variant_core_access
0374         {
0375             template<typename... Ts>
0376             static constexpr variant_data<Ts...> & data(variant<Ts...> & var) noexcept
0377             {
0378                 return var.data_();
0379             }
0380             template<typename... Ts>
0381             static constexpr variant_data<Ts...> const & data(
0382                 variant<Ts...> const & var) noexcept
0383             {
0384                 return var.data_();
0385             }
0386             template<typename... Ts>
0387             static constexpr variant_data<Ts...> && data(variant<Ts...> && var) noexcept
0388             {
0389                 return detail::move(var.data_());
0390             }
0391             template<typename... Ts>
0392             static variant<Ts...> make_empty(meta::id<variant<Ts...>> = {}) noexcept
0393             {
0394                 return variant<Ts...>{empty_variant_tag{}};
0395             }
0396         };
0397 
0398         struct delete_fn
0399         {
0400             template<typename T>
0401             void operator()(T const & t) const noexcept
0402             {
0403                 t.~T();
0404             }
0405         };
0406 
0407         template<std::size_t N, typename... Ts>
0408         struct construct_fn
0409         {
0410             std::tuple<Ts...> args_;
0411 
0412             template<typename U, std::size_t... Is>
0413             void construct_(U & u, meta::index_sequence<Is...>) noexcept(
0414                 std::is_nothrow_constructible<U, Ts...>::value)
0415             {
0416                 ::new((void *)std::addressof(u))
0417                     U(static_cast<Ts &&>(std::get<Is>(args_))...);
0418             }
0419 
0420             construct_fn(Ts &&... ts) noexcept(
0421                 std::is_nothrow_constructible<std::tuple<Ts...>, Ts...>::value)
0422               : args_{static_cast<Ts &&>(ts)...}
0423             {}
0424             template<typename U, std::size_t M>
0425             [[noreturn]] meta::if_c<N != M> operator()(
0426                 indexed_datum<U, meta::size_t<M>> &) noexcept
0427             {
0428                 RANGES_EXPECT(false);
0429             }
0430             template<typename U>
0431             meta::if_<std::is_object<U>> operator()(
0432                 indexed_datum<U, meta::size_t<N>> &
0433                     u) noexcept(std::is_nothrow_constructible<U, Ts...>::value)
0434             {
0435                 this->construct_(u.get(), meta::make_index_sequence<sizeof...(Ts)>{});
0436             }
0437             template<typename U>
0438             meta::if_<meta::not_<std::is_object<U>>> operator()(
0439                 indexed_datum<U, meta::size_t<N>> &
0440                     u) noexcept(std::is_nothrow_constructible<detail::decay_t<U>,
0441                                                               Ts...>::value)
0442             {
0443                 this->construct_(u, meta::make_index_sequence<sizeof...(Ts)>{});
0444             }
0445         };
0446 
0447         template<typename T, std::size_t N>
0448         struct get_fn
0449         {
0450             T ** t_;
0451 
0452             template<typename U, std::size_t M>
0453             [[noreturn]] meta::if_c<M != N> operator()(indexed_element<U, M>) const
0454             {
0455                 throw bad_variant_access("bad variant access");
0456             }
0457             template<typename U>
0458             void operator()(indexed_element<U, N> t) const noexcept
0459             {
0460                 *t_ = std::addressof(t.get());
0461             }
0462             template<typename U>
0463             void operator()(indexed_element<U &&, N> t) const noexcept
0464             {
0465                 U && u = t.get();
0466                 *t_ = std::addressof(u);
0467             }
0468             void operator()(indexed_element<void, N>) const noexcept
0469             {}
0470         };
0471 
0472         template<typename Variant, std::size_t N>
0473         struct emplace_fn
0474         {
0475             Variant * var_;
0476             // clang-format off
0477             template<typename...Ts>
0478             auto CPP_auto_fun(operator())(Ts &&...ts) (const)
0479             (
0480                 return var_->template emplace<N>(static_cast<Ts &&>(ts)...)
0481             )
0482             // clang-format on
0483         };
0484 
0485         template<typename Fun, typename Variant>
0486         struct variant_visitor
0487         {
0488             Fun fun_;
0489             Variant * var_;
0490 
0491             // clang-format off
0492             template<typename U, std::size_t N>
0493             auto CPP_auto_fun(operator())(indexed_element<U, N> u)
0494             (
0495                 return compose(emplace_fn<Variant, N>{var_}, fun_)(u)
0496             )
0497             // clang-format on
0498         };
0499 
0500         template<typename Variant, typename Fun>
0501         variant_visitor<Fun, Variant> make_variant_visitor(
0502             Variant & var,
0503             Fun fun) noexcept(std::is_nothrow_move_constructible<Fun>::value)
0504         {
0505             return {detail::move(fun), &var};
0506         }
0507 
0508         template<typename To, typename From>
0509         struct unique_visitor;
0510 
0511         template<typename... To, typename... From>
0512         struct unique_visitor<variant<To...>, variant<From...>>
0513         {
0514             variant<To...> * var_;
0515 
0516             template<typename T, std::size_t N>
0517             void operator()(indexed_element<T, N> t) const
0518             {
0519                 using E = meta::at_c<meta::list<From...>, N>;
0520                 static_assert(RANGES_IS_SAME(T const, E const),
0521                               "Is indexed_element broken?");
0522                 using F = meta::find<meta::list<To...>, E>;
0523                 static constexpr std::size_t M = sizeof...(To) - F::size();
0524                 compose(emplace_fn<variant<To...>, M>{var_}, get_datum_fn{})(t);
0525             }
0526         };
0527 
0528         template<typename T>
0529         constexpr T & variant_deref_(T * t) noexcept
0530         {
0531             return *t;
0532         }
0533         inline void variant_deref_(void const volatile *) noexcept
0534         {}
0535 
0536         template<typename Variant>
0537         struct variant_get
0538         {
0539             //////////////////////////////////////////////////////////////////////////////
0540             // get
0541             template<std::size_t N>
0542             friend meta::_t<
0543                 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
0544             get(Variant & var)
0545             {
0546                 using elem_t = meta::_t<
0547                     std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0548                 elem_t * elem = nullptr;
0549                 auto & data_var = detail::variant_core_access::data(var);
0550                 detail::variant_visit_(
0551                     var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0552                 return detail::variant_deref_(elem);
0553             }
0554             template<std::size_t N>
0555             friend meta::_t<
0556                 std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N> const>>
0557             get(Variant const & var)
0558             {
0559                 using elem_t = meta::_t<
0560                     std::remove_reference<meta::at_c<meta::as_list<Variant>, N> const>>;
0561                 elem_t * elem = nullptr;
0562                 auto & data_var = detail::variant_core_access::data(var);
0563                 detail::variant_visit_(
0564                     var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0565                 return detail::variant_deref_(elem);
0566             }
0567             template<std::size_t N>
0568             friend meta::_t<
0569                 std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
0570             get(Variant && var)
0571             {
0572                 using elem_t = meta::_t<
0573                     std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0574                 elem_t * elem = nullptr;
0575                 auto & data_var = detail::variant_core_access::data(var);
0576                 detail::variant_visit_(
0577                     var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
0578                 using res_t = meta::_t<
0579                     std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>;
0580                 return static_cast<res_t>(detail::variant_deref_(elem));
0581             }
0582         };
0583 
0584         template<typename Variant,
0585                  bool Trivial = std::is_trivially_destructible<meta::apply<
0586                      meta::quote<variant_data>, meta::as_list<Variant>>>::value>
0587         struct variant_base : variant_get<Variant>
0588         {
0589             ~variant_base()
0590             {
0591                 static_cast<Variant *>(this)->clear_();
0592             }
0593         };
0594         template<typename... Ts>
0595         struct variant_base<variant<Ts...>, true> : variant_get<variant<Ts...>>
0596         {};
0597 
0598         template<typename Fun, typename Types, typename Indices, typename = void>
0599         struct variant_visit_results
0600         {};
0601         template<typename Fun, typename... Ts, std::size_t... Is>
0602         struct variant_visit_results<
0603             Fun, meta::list<Ts...>, meta::index_sequence<Is...>,
0604             meta::void_<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>>
0605         {
0606             using type = variant<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>;
0607         };
0608         template<typename Fun, typename... Ts>
0609         using variant_visit_results_t =
0610             meta::_t<variant_visit_results<Fun, meta::list<Ts...>,
0611                                            meta::make_index_sequence<sizeof...(Ts)>>>;
0612     } // namespace detail
0613     /// \endcond
0614 
0615     /// \addtogroup group-utility
0616     /// @{
0617     template<typename... Ts>
0618     struct variant
0619       : private detail::variant_data<Ts...>
0620       , private detail::variant_base<variant<Ts...>>
0621     {
0622     private:
0623         friend detail::variant_core_access;
0624         template<typename...>
0625         friend struct variant;
0626         friend detail::variant_base<variant, false>;
0627         template<std::size_t Index>
0628         using datum_t = detail::variant_datum_t<Index, Ts...>;
0629         template<typename T>
0630         using add_const_t = meta::if_<std::is_void<T>, void, T const>;
0631         using unbox_fn = detail::get_datum_fn;
0632 
0633         detail::variant_data<Ts...> & data_() & noexcept
0634         {
0635             return *this;
0636         }
0637         detail::variant_data<Ts...> const & data_() const & noexcept
0638         {
0639             return *this;
0640         }
0641         detail::variant_data<Ts...> && data_() && noexcept
0642         {
0643             return static_cast<detail::variant_data<Ts...> &&>(*this);
0644         }
0645 
0646         std::size_t index_;
0647 
0648         void clear_() noexcept
0649         {
0650             if(valid())
0651             {
0652                 detail::variant_visit_(index_, data_(), detail::delete_fn{}, identity{});
0653                 index_ = (std::size_t)-1;
0654             }
0655         }
0656         template<typename That>
0657         void assign_(That && that)
0658         {
0659             if(that.valid())
0660                 index_ = detail::variant_move_copy_(
0661                     that.index_, data_(), ((That &&) that).data_());
0662         }
0663         constexpr variant(detail::empty_variant_tag) noexcept
0664           : detail::variant_data<Ts...>{}
0665           , index_((std::size_t)-1)
0666         {}
0667         template(typename... Args)(
0668             requires (sizeof...(Args) == sizeof...(Ts))) //
0669         static constexpr bool all_convertible_to(int) noexcept
0670         {
0671             return and_v<convertible_to<Args, Ts>...>;
0672         }
0673         template<typename... Args>
0674         static constexpr bool all_convertible_to(long) noexcept
0675         {
0676             return false;
0677         }
0678 
0679     public:
0680         CPP_member
0681         constexpr CPP_ctor(variant)()(                                         //
0682             noexcept(std::is_nothrow_default_constructible<datum_t<0>>::value) //
0683                 requires default_constructible<datum_t<0>>)
0684           : variant{emplaced_index<0>}
0685         {}
0686         template(std::size_t N, typename... Args)(
0687             requires constructible_from<datum_t<N>, Args...>)
0688             constexpr variant(emplaced_index_t<N>, Args &&... args) noexcept(
0689                 std::is_nothrow_constructible<datum_t<N>, Args...>::value)
0690           : detail::variant_data<Ts...>{meta::size_t<N>{}, static_cast<Args &&>(args)...}
0691           , index_(N)
0692         {}
0693         template(std::size_t N, typename T, typename... Args)(
0694             requires constructible_from<datum_t<N>, std::initializer_list<T> &,
0695                                         Args...>)
0696             constexpr variant(
0697                 emplaced_index_t<N>, std::initializer_list<T> il,
0698                 Args &&... args) noexcept(std::
0699                                               is_nothrow_constructible<
0700                                                   datum_t<N>, std::initializer_list<T> &,
0701                                                   Args...>::value)
0702           : detail::variant_data<Ts...>{meta::size_t<N>{},
0703                                         il,
0704                                         static_cast<Args &&>(args)...}
0705           , index_(N)
0706         {}
0707         template(std::size_t N)(
0708             requires constructible_from<datum_t<N>, meta::nil_>)
0709         constexpr variant(emplaced_index_t<N>, meta::nil_)
0710             noexcept(std::is_nothrow_constructible<datum_t<N>, meta::nil_>::value)
0711           : detail::variant_data<Ts...>{meta::size_t<N>{}, meta::nil_{}}
0712           , index_(N)
0713         {}
0714         variant(variant && that)
0715           : detail::variant_data<Ts...>{}
0716           , index_(detail::variant_move_copy_(that.index(), data_(),
0717                                               std::move(that.data_())))
0718         {}
0719         variant(variant const & that)
0720           : detail::variant_data<Ts...>{}
0721           , index_(detail::variant_move_copy_(that.index(), data_(), that.data_()))
0722         {}
0723         template(typename... Args)(
0724             requires (!same_as<variant<Args...>, variant>) AND
0725             (all_convertible_to<Args...>(0))) //
0726         variant(variant<Args...> that)
0727           : detail::variant_data<Ts...>{}
0728           , index_(detail::variant_move_copy_(that.index(), data_(),
0729                                               std::move(that.data_())))
0730         {}
0731         variant & operator=(variant && that)
0732         {
0733             // TODO do a simple move assign when index()==that.index()
0734             this->clear_();
0735             this->assign_(detail::move(that));
0736             return *this;
0737         }
0738         variant & operator=(variant const & that)
0739         {
0740             // TODO do a simple copy assign when index()==that.index()
0741             this->clear_();
0742             this->assign_(that);
0743             return *this;
0744         }
0745         template(typename... Args)(
0746             requires (!same_as<variant<Args...>, variant>) AND
0747             (all_convertible_to<Args...>(0)))
0748         variant & operator=(variant<Args...> that)
0749         {
0750             // TODO do a simple copy assign when index()==that.index() //
0751             this->clear_();
0752             this->assign_(that);
0753             return *this;
0754         }
0755         static constexpr std::size_t size() noexcept
0756         {
0757             return sizeof...(Ts);
0758         }
0759         template(std::size_t N, typename... Args)(
0760             requires constructible_from<datum_t<N>, Args...>)
0761         void emplace(Args &&... args)
0762         {
0763             this->clear_();
0764             detail::construct_fn<N, Args &&...> fn{static_cast<Args &&>(args)...};
0765             detail::variant_visit_(N, data_(), std::ref(fn), identity{});
0766             index_ = N;
0767         }
0768         constexpr bool valid() const noexcept
0769         {
0770             return index() != (std::size_t)-1;
0771         }
0772         constexpr std::size_t index() const noexcept
0773         {
0774             return index_;
0775         }
0776         template<typename Fun>
0777         detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> visit(Fun fun)
0778         {
0779             detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> res{
0780                 detail::empty_variant_tag{}};
0781             detail::variant_visit_(index_,
0782                                    data_(),
0783                                    detail::make_variant_visitor(
0784                                        res, compose(detail::move(fun), unbox_fn{})));
0785             return res;
0786         }
0787         template<typename Fun>
0788         detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
0789         visit(Fun fun) const
0790         {
0791             detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
0792                 res{detail::empty_variant_tag{}};
0793             detail::variant_visit_(index_,
0794                                    data_(),
0795                                    detail::make_variant_visitor(
0796                                        res, compose(detail::move(fun), unbox_fn{})));
0797             return res;
0798         }
0799         template<typename Fun>
0800         detail::variant_visit_results_t<Fun, Ts...> visit_i(Fun fun)
0801         {
0802             detail::variant_visit_results_t<Fun, Ts...> res{detail::empty_variant_tag{}};
0803             detail::variant_visit_(
0804                 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
0805             return res;
0806         }
0807         template<typename Fun>
0808         detail::variant_visit_results_t<Fun, add_const_t<Ts>...> visit_i(Fun fun) const
0809         {
0810             detail::variant_visit_results_t<Fun, add_const_t<Ts>...> res{
0811                 detail::empty_variant_tag{}};
0812             detail::variant_visit_(
0813                 index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
0814             return res;
0815         }
0816     };
0817 
0818     template(typename... Ts, typename... Us)(
0819         requires and_v<equality_comparable_with<Ts, Us>...>)
0820     bool operator==(variant<Ts...> const & lhs, variant<Us...> const & rhs)
0821     {
0822         return (!lhs.valid() && !rhs.valid()) ||
0823                (lhs.index() == rhs.index() &&
0824                 detail::variant_equal_(lhs.index(),
0825                                        detail::variant_core_access::data(lhs),
0826                                        detail::variant_core_access::data(rhs)));
0827     }
0828 
0829     template(typename... Ts, typename... Us)(
0830         requires and_v<equality_comparable_with<Ts, Us>...>)
0831     bool operator!=(variant<Ts...> const & lhs, variant<Us...> const & rhs)
0832     {
0833         return !(lhs == rhs);
0834     }
0835 
0836     //////////////////////////////////////////////////////////////////////////////////////
0837     // emplace
0838     template(std::size_t N, typename... Ts, typename... Args)(
0839         requires constructible_from<detail::variant_datum_t<N, Ts...>, Args...>)
0840     void emplace(variant<Ts...> & var, Args &&... args)
0841     {
0842         var.template emplace<N>(static_cast<Args &&>(args)...);
0843     }
0844 
0845     //////////////////////////////////////////////////////////////////////////////////////
0846     // variant_unique
0847     template<typename Var>
0848     struct variant_unique
0849     {};
0850 
0851     template<typename... Ts>
0852     struct variant_unique<variant<Ts...>>
0853     {
0854         using type = meta::apply<meta::quote<variant>, meta::unique<meta::list<Ts...>>>;
0855     };
0856 
0857     template<typename Var>
0858     using variant_unique_t = meta::_t<variant_unique<Var>>;
0859 
0860     //////////////////////////////////////////////////////////////////////////////////////
0861     // unique_variant
0862     template<typename... Ts>
0863     variant_unique_t<variant<Ts...>> unique_variant(variant<Ts...> const & var)
0864     {
0865         using From = variant<Ts...>;
0866         using To = variant_unique_t<From>;
0867         auto res = detail::variant_core_access::make_empty(meta::id<To>{});
0868         var.visit_i(detail::unique_visitor<To, From>{&res});
0869         RANGES_EXPECT(res.valid());
0870         return res;
0871     }
0872     /// @}
0873 } // namespace ranges
0874 
0875 RANGES_DIAGNOSTIC_PUSH
0876 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0877 
0878 namespace std
0879 {
0880     template<typename... Ts>
0881     struct tuple_size<::ranges::variant<Ts...>> : tuple_size<tuple<Ts...>>
0882     {};
0883 
0884     template<size_t I, typename... Ts>
0885     struct tuple_element<I, ::ranges::variant<Ts...>> : tuple_element<I, tuple<Ts...>>
0886     {};
0887 } // namespace std
0888 
0889 RANGES_DIAGNOSTIC_POP
0890 
0891 #include <range/v3/detail/epilogue.hpp>
0892 
0893 #endif