You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

variant.hpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. //
  12. #ifndef RANGES_V3_DETAIL_VARIANT_HPP
  13. #define RANGES_V3_DETAIL_VARIANT_HPP
  14. #include <iterator>
  15. #include <memory>
  16. #include <new>
  17. #include <stdexcept>
  18. #include <tuple>
  19. #include <type_traits>
  20. #include <utility>
  21. #include <meta/meta.hpp>
  22. #include <concepts/concepts.hpp>
  23. #include <range/v3/range_fwd.hpp>
  24. #include <range/v3/functional/compose.hpp>
  25. #include <range/v3/functional/identity.hpp>
  26. #include <range/v3/functional/invoke.hpp>
  27. #include <range/v3/functional/reference_wrapper.hpp>
  28. #include <range/v3/iterator/concepts.hpp>
  29. #include <range/v3/iterator/traits.hpp>
  30. #include <range/v3/utility/get.hpp>
  31. namespace ranges
  32. {
  33. template<std::size_t I>
  34. struct emplaced_index_t;
  35. template<std::size_t I>
  36. struct emplaced_index_t : meta::size_t<I>
  37. {};
  38. /// \cond
  39. #if !RANGES_CXX_VARIABLE_TEMPLATES
  40. template<std::size_t I>
  41. inline emplaced_index_t<I> emplaced_index()
  42. {
  43. return {};
  44. }
  45. template<std::size_t I>
  46. using _emplaced_index_t_ = emplaced_index_t<I> (&)();
  47. #define RANGES_EMPLACED_INDEX_T(I) _emplaced_index_t_<I>
  48. #else
  49. /// \endcond
  50. #if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
  51. namespace
  52. {
  53. template<std::size_t I>
  54. constexpr auto & emplaced_index = static_const<emplaced_index_t<I>>::value;
  55. }
  56. #else // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
  57. template<std::size_t I>
  58. inline constexpr emplaced_index_t<I> emplaced_index{};
  59. #endif // RANGES_CXX_INLINE_VARIABLES
  60. /// \cond
  61. #define RANGES_EMPLACED_INDEX_T(I) emplaced_index_t<I>
  62. #endif
  63. /// \endcond
  64. struct bad_variant_access : std::logic_error
  65. {
  66. explicit bad_variant_access(std::string const & what_arg)
  67. : std::logic_error(what_arg)
  68. {}
  69. explicit bad_variant_access(char const * what_arg)
  70. : std::logic_error(what_arg)
  71. {}
  72. };
  73. template<typename T, std::size_t Index>
  74. struct indexed_element
  75. {
  76. private:
  77. reference_wrapper<T> ref_;
  78. public:
  79. constexpr indexed_element(reference_wrapper<T> r) noexcept
  80. : ref_(r)
  81. {}
  82. constexpr decltype(auto) get() const noexcept
  83. {
  84. return ref_.get();
  85. }
  86. };
  87. template<std::size_t Index>
  88. struct indexed_element<void, Index>
  89. {
  90. void get() const noexcept
  91. {}
  92. };
  93. /// \cond
  94. namespace detail
  95. {
  96. struct indexed_element_fn;
  97. template<typename I, typename S, typename O>
  98. auto uninitialized_copy(I first, S last, O out) -> CPP_ret(O)( //
  99. requires(!sized_sentinel_for<S, I>))
  100. {
  101. for(; first != last; ++first, ++out)
  102. ::new((void *)std::addressof(*out)) iter_value_t<O>(*first);
  103. return out;
  104. }
  105. template<typename I, typename S, typename O>
  106. auto uninitialized_copy(I first, S last, O out) -> CPP_ret(O)( //
  107. requires sized_sentinel_for<S, I>)
  108. {
  109. return std::uninitialized_copy_n(first, (last - first), out);
  110. }
  111. template<typename I, typename O>
  112. O uninitialized_copy(I first, I last, O out)
  113. {
  114. return std::uninitialized_copy(first, last, out);
  115. }
  116. template<typename T, typename Index>
  117. struct indexed_datum
  118. {
  119. private:
  120. template<typename, typename>
  121. friend struct indexed_datum;
  122. T datum_;
  123. public:
  124. CPP_member
  125. constexpr CPP_ctor(indexed_datum)()( //
  126. noexcept(std::is_nothrow_default_constructible<T>::value) //
  127. requires default_constructible<T>)
  128. : datum_{}
  129. {}
  130. CPP_template(typename... Ts)( //
  131. requires constructible_from<T, Ts...> && (sizeof...(Ts) != 0)) //
  132. constexpr indexed_datum(Ts &&... ts) noexcept(
  133. std::is_nothrow_constructible<T, Ts...>::value)
  134. : datum_(static_cast<Ts &&>(ts)...)
  135. {}
  136. template<typename U>
  137. constexpr CPP_ctor(indexed_datum)(indexed_datum<U, Index> that)( //
  138. noexcept(std::is_nothrow_constructible<T, U>::value) //
  139. requires(!same_as<T, U>) &&
  140. convertible_to<U, T>)
  141. : datum_(std::move(that.datum_))
  142. {}
  143. constexpr indexed_element<T, Index::value> ref() noexcept
  144. {
  145. return {datum_};
  146. }
  147. constexpr indexed_element<T const, Index::value> ref() const noexcept
  148. {
  149. return {datum_};
  150. }
  151. constexpr T & get() noexcept
  152. {
  153. return datum_;
  154. }
  155. constexpr T const & get() const noexcept
  156. {
  157. return datum_;
  158. }
  159. };
  160. template<typename T, std::size_t N, typename Index>
  161. struct indexed_datum<T[N], Index>;
  162. template<typename T, typename Index>
  163. struct indexed_datum<T &, Index>
  164. {
  165. private:
  166. template<typename, typename>
  167. friend struct indexed_datum;
  168. reference_wrapper<T &> ref_;
  169. public:
  170. constexpr indexed_datum(reference_wrapper<T &> ref) noexcept
  171. : ref_(ref)
  172. {}
  173. constexpr indexed_element<T &, Index::value> ref() const noexcept
  174. {
  175. return {ref_.get()};
  176. }
  177. };
  178. template<typename T, typename Index>
  179. struct indexed_datum<T &&, Index>
  180. {
  181. private:
  182. template<typename, typename>
  183. friend struct indexed_datum;
  184. reference_wrapper<T &&> ref_;
  185. public:
  186. constexpr indexed_datum(reference_wrapper<T &&> ref) noexcept
  187. : ref_(ref)
  188. {}
  189. constexpr indexed_element<T &&, Index::value> ref() const noexcept
  190. {
  191. return {ref_.get()};
  192. }
  193. };
  194. template<typename Index>
  195. struct indexed_datum<void, Index>
  196. {
  197. void get() const noexcept
  198. {}
  199. constexpr indexed_element<void, Index::value> ref() const noexcept
  200. {
  201. return {};
  202. }
  203. };
  204. template<std::size_t Index, typename... Ts>
  205. using variant_datum_t =
  206. detail::indexed_datum<meta::at_c<meta::list<Ts...>, Index>,
  207. meta::size_t<Index>>;
  208. } // namespace detail
  209. template<std::size_t N, typename... Ts, typename... Args>
  210. meta::if_c<(bool)constructible_from<detail::variant_datum_t<N, Ts...>, Args...>>
  211. emplace(variant<Ts...> &, Args &&...);
  212. namespace detail
  213. {
  214. using variant_nil = indexed_datum<void, meta::npos>;
  215. template<typename Ts,
  216. bool Trivial = meta::apply<
  217. meta::quote<meta::and_>,
  218. meta::transform<Ts, meta::quote<std::is_trivially_destructible>>>::
  219. type::value>
  220. struct variant_data_
  221. {
  222. using type = indexed_datum<void, meta::npos>;
  223. };
  224. template<typename T, typename... Ts>
  225. struct variant_data_<meta::list<T, Ts...>, true>
  226. {
  227. struct type
  228. {
  229. using head_t = T;
  230. using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
  231. union
  232. {
  233. head_t head;
  234. tail_t tail;
  235. };
  236. type() noexcept
  237. {}
  238. template<typename... Args>
  239. constexpr type(meta::size_t<0>, Args &&... args) noexcept(
  240. std::is_nothrow_constructible<head_t, Args...>::value)
  241. : head{((Args &&) args)...}
  242. {}
  243. template<std::size_t N, typename... Args>
  244. constexpr type(meta::size_t<N>, Args &&... args) noexcept(
  245. std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
  246. Args...>::value)
  247. : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
  248. {}
  249. };
  250. };
  251. template<typename T, typename... Ts>
  252. struct variant_data_<meta::list<T, Ts...>, false>
  253. {
  254. struct type
  255. {
  256. using head_t = T;
  257. using tail_t = meta::_t<variant_data_<meta::list<Ts...>>>;
  258. union
  259. {
  260. head_t head;
  261. tail_t tail;
  262. };
  263. type() noexcept
  264. {}
  265. ~type()
  266. {}
  267. template<typename... Args>
  268. constexpr type(meta::size_t<0>, Args &&... args) noexcept(
  269. std::is_nothrow_constructible<head_t, Args...>::value)
  270. : head{((Args &&) args)...}
  271. {}
  272. template<std::size_t N, typename... Args>
  273. constexpr type(meta::size_t<N>, Args &&... args) noexcept(
  274. std::is_nothrow_constructible<tail_t, meta::size_t<N - 1>,
  275. Args...>::value)
  276. : tail{meta::size_t<N - 1>{}, ((Args &&) args)...}
  277. {}
  278. };
  279. };
  280. template<typename... Ts>
  281. using variant_data = meta::_t<variant_data_<meta::transform<
  282. meta::list<Ts...>, meta::as_list<meta::make_index_sequence<sizeof...(Ts)>>,
  283. meta::quote<indexed_datum>>>>;
  284. inline std::size_t variant_move_copy_(std::size_t, variant_nil, variant_nil)
  285. {
  286. return 0;
  287. }
  288. template<typename Data0, typename Data1>
  289. std::size_t variant_move_copy_(std::size_t n, Data0 & self, Data1 && that)
  290. {
  291. using Head = typename Data0::head_t;
  292. return 0 == n
  293. ? ((void)::new((void *)&self.head) Head(((Data1 &&) that).head), 0)
  294. : variant_move_copy_(n - 1, self.tail, ((Data1 &&) that).tail) + 1;
  295. }
  296. constexpr bool variant_equal_(std::size_t, variant_nil, variant_nil)
  297. {
  298. return true;
  299. }
  300. template<typename Data0, typename Data1>
  301. constexpr bool variant_equal_(std::size_t n, Data0 const & self,
  302. Data1 const & that)
  303. {
  304. return n == 0 ? self.head.get() == that.head.get()
  305. : variant_equal_(n - 1, self.tail, that.tail);
  306. }
  307. template<typename Fun, typename Proj = indexed_element_fn>
  308. constexpr int variant_visit_(std::size_t, variant_nil, Fun, Proj = {})
  309. {
  310. return (RANGES_EXPECT(false), 0);
  311. }
  312. template<typename Data, typename Fun, typename Proj = indexed_element_fn>
  313. constexpr int variant_visit_(std::size_t n, Data & self, Fun fun, Proj proj = {})
  314. {
  315. return 0 == n ? ((void)invoke(fun, invoke(proj, self.head)), 0)
  316. : detail::variant_visit_(
  317. n - 1, self.tail, detail::move(fun), detail::move(proj));
  318. }
  319. struct get_datum_fn
  320. {
  321. template<typename T>
  322. decltype(auto) operator()(T && t) const noexcept
  323. {
  324. return t.get();
  325. }
  326. };
  327. struct indexed_element_fn
  328. {
  329. template<typename T>
  330. decltype(auto) operator()(T && t) const noexcept
  331. {
  332. return t.ref();
  333. }
  334. };
  335. struct empty_variant_tag
  336. {};
  337. struct variant_core_access
  338. {
  339. template<typename... Ts>
  340. static constexpr variant_data<Ts...> & data(variant<Ts...> & var) noexcept
  341. {
  342. return var.data_();
  343. }
  344. template<typename... Ts>
  345. static constexpr variant_data<Ts...> const & data(
  346. variant<Ts...> const & var) noexcept
  347. {
  348. return var.data_();
  349. }
  350. template<typename... Ts>
  351. static constexpr variant_data<Ts...> && data(variant<Ts...> && var) noexcept
  352. {
  353. return detail::move(var.data_());
  354. }
  355. template<typename... Ts>
  356. static variant<Ts...> make_empty(meta::id<variant<Ts...>> = {}) noexcept
  357. {
  358. return variant<Ts...>{empty_variant_tag{}};
  359. }
  360. };
  361. struct delete_fn
  362. {
  363. template<typename T>
  364. void operator()(T const & t) const noexcept
  365. {
  366. t.~T();
  367. }
  368. };
  369. template<std::size_t N, typename... Ts>
  370. struct construct_fn
  371. {
  372. std::tuple<Ts...> args_;
  373. template<typename U, std::size_t... Is>
  374. void construct_(U & u, meta::index_sequence<Is...>) noexcept(
  375. std::is_nothrow_constructible<U, Ts...>::value)
  376. {
  377. ::new((void *)std::addressof(u))
  378. U(static_cast<Ts &&>(std::get<Is>(args_))...);
  379. }
  380. construct_fn(Ts &&... ts) noexcept(
  381. std::is_nothrow_constructible<std::tuple<Ts...>, Ts...>::value)
  382. : args_{static_cast<Ts &&>(ts)...}
  383. {}
  384. template<typename U, std::size_t M>
  385. [[noreturn]] meta::if_c<N != M> operator()(
  386. indexed_datum<U, meta::size_t<M>> &) noexcept
  387. {
  388. RANGES_EXPECT(false);
  389. }
  390. template<typename U>
  391. meta::if_<std::is_object<U>> operator()(
  392. indexed_datum<U, meta::size_t<N>> &
  393. u) noexcept(std::is_nothrow_constructible<U, Ts...>::value)
  394. {
  395. this->construct_(u.get(), meta::make_index_sequence<sizeof...(Ts)>{});
  396. }
  397. template<typename U>
  398. meta::if_<meta::not_<std::is_object<U>>> operator()(
  399. indexed_datum<U, meta::size_t<N>> &
  400. u) noexcept(std::is_nothrow_constructible<detail::decay_t<U>,
  401. Ts...>::value)
  402. {
  403. this->construct_(u, meta::make_index_sequence<sizeof...(Ts)>{});
  404. }
  405. };
  406. template<typename T, std::size_t N>
  407. struct get_fn
  408. {
  409. T ** t_;
  410. template<typename U, std::size_t M>
  411. [[noreturn]] meta::if_c<M != N> operator()(indexed_element<U, M>) const
  412. {
  413. throw bad_variant_access("bad variant access");
  414. }
  415. template<typename U>
  416. void operator()(indexed_element<U, N> t) const noexcept
  417. {
  418. *t_ = std::addressof(t.get());
  419. }
  420. template<typename U>
  421. void operator()(indexed_element<U &&, N> t) const noexcept
  422. {
  423. U && u = t.get();
  424. *t_ = std::addressof(u);
  425. }
  426. void operator()(indexed_element<void, N>) const noexcept
  427. {}
  428. };
  429. template<typename Variant, std::size_t N>
  430. struct emplace_fn
  431. {
  432. Variant * var_;
  433. // clang-format off
  434. template<typename...Ts>
  435. auto CPP_auto_fun(operator())(Ts &&...ts) (const)
  436. (
  437. return ranges::emplace<N>(*var_, static_cast<Ts &&>(ts)...)
  438. )
  439. // clang-format on
  440. };
  441. template<typename Fun, typename Variant>
  442. struct variant_visitor
  443. {
  444. Fun fun_;
  445. Variant * var_;
  446. // clang-format off
  447. template<typename U, std::size_t N>
  448. auto CPP_auto_fun(operator())(indexed_element<U, N> u)
  449. (
  450. return compose(emplace_fn<Variant, N>{var_}, fun_)(u)
  451. )
  452. // clang-format on
  453. };
  454. template<typename Variant, typename Fun>
  455. variant_visitor<Fun, Variant> make_variant_visitor(
  456. Variant & var,
  457. Fun fun) noexcept(std::is_nothrow_move_constructible<Fun>::value)
  458. {
  459. return {detail::move(fun), &var};
  460. }
  461. template<typename To, typename From>
  462. struct unique_visitor;
  463. template<typename... To, typename... From>
  464. struct unique_visitor<variant<To...>, variant<From...>>
  465. {
  466. variant<To...> * var_;
  467. template<typename T, std::size_t N>
  468. void operator()(indexed_element<T, N> t) const
  469. {
  470. using E = meta::at_c<meta::list<From...>, N>;
  471. static_assert(RANGES_IS_SAME(T const, E const),
  472. "Is indexed_element broken?");
  473. using F = meta::find<meta::list<To...>, E>;
  474. static constexpr std::size_t M = sizeof...(To) - F::size();
  475. compose(emplace_fn<variant<To...>, M>{var_}, get_datum_fn{})(t);
  476. }
  477. };
  478. template<typename T>
  479. constexpr T & variant_deref_(T * t) noexcept
  480. {
  481. return *t;
  482. }
  483. inline void variant_deref_(void const volatile *) noexcept
  484. {}
  485. template<typename Variant>
  486. struct variant_get
  487. {
  488. ////////////////////////////////////////////////////////////////////////////////////////////
  489. // get
  490. template<std::size_t N>
  491. friend meta::_t<
  492. std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
  493. get(Variant & var)
  494. {
  495. using elem_t = meta::_t<
  496. std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
  497. elem_t * elem = nullptr;
  498. auto & data_var = detail::variant_core_access::data(var);
  499. detail::variant_visit_(
  500. var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
  501. return detail::variant_deref_(elem);
  502. }
  503. template<std::size_t N>
  504. friend meta::_t<
  505. std::add_lvalue_reference<meta::at_c<meta::as_list<Variant>, N> const>>
  506. get(Variant const & var)
  507. {
  508. using elem_t = meta::_t<
  509. std::remove_reference<meta::at_c<meta::as_list<Variant>, N> const>>;
  510. elem_t * elem = nullptr;
  511. auto & data_var = detail::variant_core_access::data(var);
  512. detail::variant_visit_(
  513. var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
  514. return detail::variant_deref_(elem);
  515. }
  516. template<std::size_t N>
  517. friend meta::_t<
  518. std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>
  519. get(Variant && var)
  520. {
  521. using elem_t = meta::_t<
  522. std::remove_reference<meta::at_c<meta::as_list<Variant>, N>>>;
  523. elem_t * elem = nullptr;
  524. auto & data_var = detail::variant_core_access::data(var);
  525. detail::variant_visit_(
  526. var.index(), data_var, detail::get_fn<elem_t, N>{&elem});
  527. using res_t = meta::_t<
  528. std::add_rvalue_reference<meta::at_c<meta::as_list<Variant>, N>>>;
  529. return static_cast<res_t>(detail::variant_deref_(elem));
  530. }
  531. };
  532. template<typename Variant,
  533. bool Trivial = std::is_trivially_destructible<meta::apply<
  534. meta::quote<variant_data>, meta::as_list<Variant>>>::value>
  535. struct variant_base : variant_get<Variant>
  536. {
  537. ~variant_base()
  538. {
  539. static_cast<Variant *>(this)->clear_();
  540. }
  541. };
  542. template<typename... Ts>
  543. struct variant_base<variant<Ts...>, true> : variant_get<variant<Ts...>>
  544. {};
  545. template<typename Fun, typename Types, typename Indices, typename = void>
  546. struct variant_visit_results
  547. {};
  548. template<typename Fun, typename... Ts, std::size_t... Is>
  549. struct variant_visit_results<
  550. Fun, meta::list<Ts...>, meta::index_sequence<Is...>,
  551. meta::void_<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>>
  552. {
  553. using type = variant<invoke_result_t<Fun &, indexed_element<Ts, Is>>...>;
  554. };
  555. template<typename Fun, typename... Ts>
  556. using variant_visit_results_t =
  557. meta::_t<variant_visit_results<Fun, meta::list<Ts...>,
  558. meta::make_index_sequence<sizeof...(Ts)>>>;
  559. } // namespace detail
  560. /// \endcond
  561. /// \addtogroup group-utility
  562. /// @{
  563. template<typename... Ts>
  564. struct variant
  565. : private detail::variant_data<Ts...>
  566. , private detail::variant_base<variant<Ts...>>
  567. {
  568. private:
  569. friend detail::variant_core_access;
  570. template<typename...>
  571. friend struct variant;
  572. friend detail::variant_base<variant, false>;
  573. template<std::size_t Index>
  574. using datum_t = detail::variant_datum_t<Index, Ts...>;
  575. template<typename T>
  576. using add_const_t = meta::if_<std::is_void<T>, void, T const>;
  577. using unbox_fn = detail::get_datum_fn;
  578. detail::variant_data<Ts...> & data_() & noexcept
  579. {
  580. return *this;
  581. }
  582. detail::variant_data<Ts...> const & data_() const & noexcept
  583. {
  584. return *this;
  585. }
  586. detail::variant_data<Ts...> && data_() && noexcept
  587. {
  588. return static_cast<detail::variant_data<Ts...> &&>(*this);
  589. }
  590. std::size_t index_;
  591. void clear_() noexcept
  592. {
  593. if(valid())
  594. {
  595. detail::variant_visit_(index_, data_(), detail::delete_fn{}, identity{});
  596. index_ = (std::size_t)-1;
  597. }
  598. }
  599. template<typename That>
  600. void assign_(That && that)
  601. {
  602. if(that.valid())
  603. index_ = detail::variant_move_copy_(
  604. that.index_, data_(), ((That &&) that).data_());
  605. }
  606. constexpr variant(detail::empty_variant_tag) noexcept
  607. : detail::variant_data<Ts...>{}
  608. , index_((std::size_t)-1)
  609. {}
  610. template<typename... Args>
  611. static constexpr auto all_convertible_to(int) noexcept -> CPP_ret(bool)( //
  612. requires(sizeof...(Args) == sizeof...(Ts)))
  613. {
  614. return and_v<convertible_to<Args, Ts>...>;
  615. }
  616. template<typename... Args>
  617. static constexpr bool all_convertible_to(long) noexcept
  618. {
  619. return false;
  620. }
  621. public:
  622. CPP_member
  623. constexpr CPP_ctor(variant)()( //
  624. noexcept(std::is_nothrow_default_constructible<datum_t<0>>::value) //
  625. requires default_constructible<datum_t<0>>)
  626. : variant{emplaced_index<0>}
  627. {}
  628. CPP_template(std::size_t N, typename... Args)( //
  629. requires constructible_from<datum_t<N>, Args...>) //
  630. constexpr variant(RANGES_EMPLACED_INDEX_T(N), Args &&... args) noexcept(
  631. std::is_nothrow_constructible<datum_t<N>, Args...>::value)
  632. : detail::variant_data<Ts...>{meta::size_t<N>{}, static_cast<Args &&>(args)...}
  633. , index_(N)
  634. {}
  635. CPP_template(std::size_t N, typename T, typename... Args)( //
  636. requires constructible_from<datum_t<N>, std::initializer_list<T> &,
  637. Args...>) //
  638. constexpr variant(
  639. RANGES_EMPLACED_INDEX_T(N), std::initializer_list<T> il,
  640. Args &&... args) noexcept(std::
  641. is_nothrow_constructible<
  642. datum_t<N>, std::initializer_list<T> &,
  643. Args...>::value)
  644. : detail::variant_data<Ts...>{meta::size_t<N>{},
  645. il,
  646. static_cast<Args &&>(args)...}
  647. , index_(N)
  648. {}
  649. template<std::size_t N>
  650. constexpr CPP_ctor(variant)(RANGES_EMPLACED_INDEX_T(N), meta::nil_)( //
  651. noexcept(std::is_nothrow_constructible<datum_t<N>, meta::nil_>::value) //
  652. requires constructible_from<datum_t<N>, meta::nil_>)
  653. : detail::variant_data<Ts...>{meta::size_t<N>{}, meta::nil_{}}
  654. , index_(N)
  655. {}
  656. variant(variant && that)
  657. : detail::variant_data<Ts...>{}
  658. , index_(detail::variant_move_copy_(that.index(), data_(),
  659. std::move(that.data_())))
  660. {}
  661. variant(variant const & that)
  662. : detail::variant_data<Ts...>{}
  663. , index_(detail::variant_move_copy_(that.index(), data_(), that.data_()))
  664. {}
  665. template<typename... Args>
  666. CPP_ctor(variant)(variant<Args...> that)( //
  667. requires(!same_as<variant<Args...>, variant>) &&
  668. (all_convertible_to<Args...>(0)))
  669. : detail::variant_data<Ts...>{}
  670. , index_(detail::variant_move_copy_(that.index(), data_(),
  671. std::move(that.data_())))
  672. {}
  673. variant & operator=(variant && that)
  674. {
  675. // TODO do a simple move assign when index()==that.index()
  676. this->clear_();
  677. this->assign_(detail::move(that));
  678. return *this;
  679. }
  680. variant & operator=(variant const & that)
  681. {
  682. // TODO do a simple copy assign when index()==that.index()
  683. this->clear_();
  684. this->assign_(that);
  685. return *this;
  686. }
  687. template<typename... Args>
  688. auto operator=(variant<Args...> that) -> CPP_ret(variant &)( //
  689. requires(!same_as<variant<Args...>, variant>) &&
  690. (all_convertible_to<Args...>(0)))
  691. {
  692. // TODO do a simple copy assign when index()==that.index()
  693. this->clear_();
  694. this->assign_(that);
  695. return *this;
  696. }
  697. static constexpr std::size_t size() noexcept
  698. {
  699. return sizeof...(Ts);
  700. }
  701. template<std::size_t N, typename... Args>
  702. auto emplace(Args &&... args) -> CPP_ret(void)( //
  703. requires constructible_from<datum_t<N>, Args...>)
  704. {
  705. this->clear_();
  706. detail::construct_fn<N, Args &&...> fn{static_cast<Args &&>(args)...};
  707. detail::variant_visit_(N, data_(), std::ref(fn), identity{});
  708. index_ = N;
  709. }
  710. constexpr bool valid() const noexcept
  711. {
  712. return index() != (std::size_t)-1;
  713. }
  714. constexpr std::size_t index() const noexcept
  715. {
  716. return index_;
  717. }
  718. template<typename Fun>
  719. detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> visit(Fun fun)
  720. {
  721. detail::variant_visit_results_t<composed<Fun, unbox_fn>, Ts...> res{
  722. detail::empty_variant_tag{}};
  723. detail::variant_visit_(index_,
  724. data_(),
  725. detail::make_variant_visitor(
  726. res, compose(detail::move(fun), unbox_fn{})));
  727. return res;
  728. }
  729. template<typename Fun>
  730. detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
  731. visit(Fun fun) const
  732. {
  733. detail::variant_visit_results_t<composed<Fun, unbox_fn>, add_const_t<Ts>...>
  734. res{detail::empty_variant_tag{}};
  735. detail::variant_visit_(index_,
  736. data_(),
  737. detail::make_variant_visitor(
  738. res, compose(detail::move(fun), unbox_fn{})));
  739. return res;
  740. }
  741. template<typename Fun>
  742. detail::variant_visit_results_t<Fun, Ts...> visit_i(Fun fun)
  743. {
  744. detail::variant_visit_results_t<Fun, Ts...> res{detail::empty_variant_tag{}};
  745. detail::variant_visit_(
  746. index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
  747. return res;
  748. }
  749. template<typename Fun>
  750. detail::variant_visit_results_t<Fun, add_const_t<Ts>...> visit_i(Fun fun) const
  751. {
  752. detail::variant_visit_results_t<Fun, add_const_t<Ts>...> res{
  753. detail::empty_variant_tag{}};
  754. detail::variant_visit_(
  755. index_, data_(), detail::make_variant_visitor(res, detail::move(fun)));
  756. return res;
  757. }
  758. };
  759. template<typename... Ts, typename... Us>
  760. auto operator==(variant<Ts...> const & lhs, variant<Us...> const & rhs)
  761. -> CPP_ret(bool)( //
  762. requires and_v<equality_comparable_with<Ts, Us>...>)
  763. {
  764. return (!lhs.valid() && !rhs.valid()) ||
  765. (lhs.index() == rhs.index() &&
  766. detail::variant_equal_(lhs.index(),
  767. detail::variant_core_access::data(lhs),
  768. detail::variant_core_access::data(rhs)));
  769. }
  770. template<typename... Ts, typename... Us>
  771. auto operator!=(variant<Ts...> const & lhs, variant<Us...> const & rhs)
  772. -> CPP_ret(bool)( //
  773. requires and_v<equality_comparable_with<Ts, Us>...>)
  774. {
  775. return !(lhs == rhs);
  776. }
  777. ////////////////////////////////////////////////////////////////////////////////////////////
  778. // emplace
  779. template<std::size_t N, typename... Ts, typename... Args>
  780. meta::if_c<(bool)constructible_from<detail::variant_datum_t<N, Ts...>, Args...>>
  781. emplace(variant<Ts...> & var, Args &&... args)
  782. {
  783. var.template emplace<N>(static_cast<Args &&>(args)...);
  784. }
  785. ////////////////////////////////////////////////////////////////////////////////////////////
  786. // variant_unique
  787. template<typename Var>
  788. struct variant_unique
  789. {};
  790. template<typename... Ts>
  791. struct variant_unique<variant<Ts...>>
  792. {
  793. using type = meta::apply<meta::quote<variant>, meta::unique<meta::list<Ts...>>>;
  794. };
  795. template<typename Var>
  796. using variant_unique_t = meta::_t<variant_unique<Var>>;
  797. ////////////////////////////////////////////////////////////////////////////////////////////
  798. // unique_variant
  799. template<typename... Ts>
  800. variant_unique_t<variant<Ts...>> unique_variant(variant<Ts...> const & var)
  801. {
  802. using From = variant<Ts...>;
  803. using To = variant_unique_t<From>;
  804. auto res = detail::variant_core_access::make_empty(meta::id<To>{});
  805. var.visit_i(detail::unique_visitor<To, From>{&res});
  806. RANGES_EXPECT(res.valid());
  807. return res;
  808. }
  809. /// @}
  810. } // namespace ranges
  811. RANGES_DIAGNOSTIC_PUSH
  812. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  813. namespace std
  814. {
  815. template<typename... Ts>
  816. struct tuple_size<::ranges::variant<Ts...>> : tuple_size<tuple<Ts...>>
  817. {};
  818. template<size_t I, typename... Ts>
  819. struct tuple_element<I, ::ranges::variant<Ts...>> : tuple_element<I, tuple<Ts...>>
  820. {};
  821. } // namespace std
  822. RANGES_DIAGNOSTIC_POP
  823. #endif