Backport
variant.hpp
Go to the documentation of this file.
1 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2020 Matthew Rodusek All rights reserved.
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BPSTD_VARIANT_HPP
31 #define BPSTD_VARIANT_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "detail/config.hpp"
38 #include "detail/enable_overload.hpp" // enable_overload_if
39 #include "detail/nth_type.hpp"
40 #include "detail/variant_base.hpp"
41 #include "detail/variant_visitors.hpp"
42 #include "detail/variant_traits.hpp"
43 #include "tuple.hpp"
44 #include "utility.hpp" // in_place_index_t, in_place_type_t
45 #include "type_traits.hpp" // conjunction
46 #include "functional.hpp" // less, greater, equal_to, etc
47 
48 #include <initializer_list> // std::initializer_list
49 #include <memory> // std::uses_allocator
50 #include <exception> // std::exception
51 #include <cstddef> // std::size_t
52 #include <utility> // std::forward, std::move
53 
54 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
55 
56 namespace bpstd {
57 
58  //============================================================================
59  // class : monostate
60  //============================================================================
61 
62  struct monostate{};
63 
64  constexpr bool operator==(monostate, monostate) noexcept;
65  constexpr bool operator!=(monostate, monostate) noexcept;
66  constexpr bool operator<(monostate, monostate) noexcept;
67  constexpr bool operator>(monostate, monostate) noexcept;
68  constexpr bool operator<=(monostate, monostate) noexcept;
69  constexpr bool operator>=(monostate, monostate) noexcept;
70 
71  //============================================================================
72  // forward declaration : variant
73  //============================================================================
74 
75  template <typename...Types>
76  class variant;
77 
78  //=========================================================================
79  // trait : variant_size
80  //=========================================================================
81 
87  template <typename T>
88  struct variant_size; // not defined
89 
90  template <typename T>
91  struct variant_size<const T>
92  : variant_size<T>{};
93 
94  template <typename T>
95  struct variant_size<volatile T>
96  : variant_size<T>{};
97 
98  template <typename T>
99  struct variant_size<const volatile T>
100  : variant_size<T>{};
101 
102  template <typename...Types>
103  struct variant_size<variant<Types...>>
104  : integral_constant<std::size_t,sizeof...(Types)>{};
106 
108 #if BPSTD_HAS_TEMPLATE_VARIABLES
109  template <typename T>
110  BPSTD_CPP17_INLINE constexpr auto variant_size_v = variant_size<T>::value;
111 #endif
112 
113  //============================================================================
114  // trait : variant_alternative
115  //============================================================================
116 
127  template <std::size_t I, typename T>
128  struct variant_alternative; // not defined
129 
130  template <std::size_t I, typename T>
131  struct variant_alternative<I, const T>
132  : add_const<typename variant_alternative<I,T>::type>{};
133 
134  template <std::size_t I, typename T>
135  struct variant_alternative<I, volatile T>
136  : add_volatile<typename variant_alternative<I,T>::type>{};
137 
138  template <std::size_t I, typename T>
139  struct variant_alternative<I, const volatile T>
140  : add_cv<typename variant_alternative<I,T>::type>{};
141 
142  template <std::size_t I, typename...Types>
143  struct variant_alternative<I, variant<Types...>>
144  : detail::nth_type<I,Types...>{};
146 
147  //----------------------------------------------------------------------------
148 
154  template <std::size_t I, typename T>
156 
157  //============================================================================
158  // globals : variant
159  //============================================================================
160 
164  BPSTD_CPP17_INLINE constexpr auto variant_npos = static_cast<std::size_t>(-1);
165 
166  //============================================================================
167  // class : bad_variant_access
168  //============================================================================
169 
179  class bad_variant_access : public std::exception
180  {
181  //--------------------------------------------------------------------------
182  // Constructor
183  //--------------------------------------------------------------------------
184  public:
185 
187  bad_variant_access() noexcept = default;
188 
189  //--------------------------------------------------------------------------
190  // Observers
191  //--------------------------------------------------------------------------
192  public:
193 
197  const char* what() const noexcept override;
198  };
199 
200  namespace detail {
201 
202  //==========================================================================
203  // trait : index_from
204  //==========================================================================
205 
206  template <std::size_t I, typename T, typename...Ts>
207  struct index_from_impl;
208 
209  template <std::size_t I, typename T>
210  struct index_from_impl<I, T>
211  : integral_constant<std::size_t,variant_npos>{};
212 
213  template <std::size_t I, typename T, typename T0, typename...Ts>
214  struct index_from_impl<I,T,T0,Ts...>
215  : index_from_impl<I+1,T,Ts...>{};
216 
217  template <std::size_t I, typename T, typename...Ts>
218  struct index_from_impl<I,T,T,Ts...>
219  : integral_constant<std::size_t,I>{};
220 
222  template <typename T, typename...Ts>
223  struct index_from : index_from_impl<0,T,Ts...>{};
224 
225  //==========================================================================
226  // trait : is_not_in_place
227  //==========================================================================
228 
230  template <typename T>
231  struct is_not_in_place : true_type{};
232 
233  template <typename T>
234  struct is_not_in_place<in_place_type_t<T>> : false_type{};
235 
236  template <std::size_t N>
237  struct is_not_in_place<in_place_index_t<N>> : false_type{};
238 
239  template <>
240  struct is_not_in_place<in_place_t> : false_type{};
241 
242  //==========================================================================
243  // trait : index_of_constructible_alternative
244  //==========================================================================
245 
246  template <std::size_t I, typename...Types>
247  struct variant_f_impl;
248 
249  template <std::size_t I, typename T0, typename...Types>
250  struct variant_f_impl<I,T0,Types...>
251  : variant_f_impl<I+1,Types...>
252  {
253  using variant_f_impl<I+1,Types...>::operator();
254 
255  integral_constant<std::size_t,I> operator()(T0);
256  };
257 
258  // skip 'bool' overloads from consideration
259  template <std::size_t I, typename...Types>
260  struct variant_f_impl<I,bool,Types...>
261  : variant_f_impl<I+1,Types...>
262  {
263  using variant_f_impl<I+1,Types...>::operator();
264  };
265 
266  template <std::size_t I, typename...Types>
267  struct variant_f_impl<I,const bool,Types...>
268  : variant_f_impl<I+1,Types...>
269  {
270  using variant_f_impl<I+1,Types...>::operator();
271  };
272 
273  template <std::size_t I, typename...Types>
274  struct variant_f_impl<I,volatile bool,Types...>
275  : variant_f_impl<I+1,Types...>
276  {
277  using variant_f_impl<I+1,Types...>::operator();
278  };
279 
280  template <std::size_t I, typename...Types>
281  struct variant_f_impl<I,const volatile bool,Types...>
282  : variant_f_impl<I+1,Types...>
283  {
284  using variant_f_impl<I+1,Types...>::operator();
285  };
286 
287  template <std::size_t I>
288  struct variant_f_impl<I>
289  {
290  // End recursion with a variant_npos
291  integral_constant<std::size_t,variant_npos> operator()(...);
292  };
293 
294  template <typename...Types>
295  struct variant_f : variant_f_impl<0,Types...> {};
296 
297  //--------------------------------------------------------------------------
298 
307  template <typename T, typename...Types>
308  struct index_of_constructible_alternative
309  : conditional_t<
310  is_same<remove_cvref_t<T>,bool>::value,
311  index_from<bool, remove_cv_t<Types>...>,
312  decltype(std::declval<variant_f<Types...>>()(std::declval<T>()))
313  >{};
314 
315  template <typename T, typename...Types>
316  struct constructible_alternative
317  : nth_type<index_of_constructible_alternative<T, Types...>::value, Types...>{};
318 
319  template <typename T, typename...Types>
320  using constructible_alternative_t
321  = typename constructible_alternative<T, Types...>::type;
322 
323  //==========================================================================
324  // trait : has_constructible_alternative
325  //==========================================================================
326 
329  template <typename T, typename...Types>
330  struct has_constructible_alternative
331  : bool_constant<(index_of_constructible_alternative<T,Types...>::value != variant_npos)>{};
332 
333  template <bool HasConstructibleAlternative, typename T, typename...Types>
334  struct can_construct_alternative_impl : false_type{};
335 
336  template <typename T, typename...Types>
337  struct can_construct_alternative_impl<true,T,Types...>
338  : is_constructible<constructible_alternative_t<T,Types...>,T>{};
339 
340  template <typename T, typename...Types>
341  using can_construct_alternative
342  = can_construct_alternative_impl<has_constructible_alternative<T,Types...>::value,T,Types...>;
343 
344  template <bool HasConstructibleAlternative, typename T, typename...Types>
345  struct can_assign_alternative_impl : false_type{};
346 
347  template <typename T, typename...Types>
348  struct can_assign_alternative_impl<true,T,Types...>
349  : is_assignable<constructible_alternative_t<T,Types...>,T>{};
350 
351  template <typename T, typename...Types>
352  using can_assign_alternative
353  = can_assign_alternative_impl<has_constructible_alternative<T,Types...>::value,T,Types...>;
354 
355  } // namespace detail
356 
357  //============================================================================
358  // class : variant
359  //============================================================================
360 
388  template <typename...Types>
389  class variant
390  : detail::variant_base<
391  conjunction<is_trivially_destructible<Types>...>::value,
392  Types...
393  >
394  {
395  //--------------------------------------------------------------------------
396  // Validation
397  //--------------------------------------------------------------------------
398 
399  static_assert(
400  sizeof...(Types) > 0,
401  "A variant of 0 types is ill-formed. Use variant<monostate> instead."
402  );
403  static_assert(
404  conjunction<negation<is_reference<Types>>...>::value,
405  "A variant containing a reference type is ill-formed. Use reference_wrapper"
406  );
407  static_assert(
408  conjunction<negation<is_void<Types>>...>::value,
409  "A variant containing void is ill-formed."
410  );
411 
412  //--------------------------------------------------------------------------
413  // Public Member Types
414  //--------------------------------------------------------------------------
415 
416  using base_type = detail::variant_base<
417  conjunction<is_trivially_destructible<Types>...>::value,
418  Types...
419  >;
420  using first_type = typename detail::nth_type_t<0,Types...>;
421 
422  static constexpr bool is_default_constructible
423  = bpstd::is_default_constructible<first_type>::value;
424 
425  static constexpr bool is_move_constructible = conjunction<
426  bpstd::is_move_constructible<Types>...
427  >::value;
428 
429  static constexpr bool is_copy_constructible = conjunction<
430  bpstd::is_copy_constructible<Types>...
431  >::value;
432 
433  static constexpr bool is_copy_assignable = conjunction<
434  bpstd::is_copy_constructible<Types>...,
435  bpstd::is_copy_assignable<Types>...
436  >::value;
437 
438  static constexpr bool is_move_assignable = conjunction<
439  bpstd::is_move_constructible<Types>...,
440  bpstd::is_move_assignable<Types>...
441  >::value;
442 
443  static constexpr bool is_nothrow_default_constructible = conjunction<
444  bpstd::is_nothrow_default_constructible<Types>...
445  >::value;
446 
447  static constexpr bool is_nothrow_move_constructible = conjunction<
448  bpstd::is_nothrow_move_constructible<Types>...
449  >::value;
450 
451  static constexpr bool is_nothrow_copy_constructible = conjunction<
452  bpstd::is_nothrow_copy_constructible<Types>...
453  >::value;
454 
455  template <std::size_t I>
456  using i_is_in_range = bool_constant<(I < sizeof...(Types))>;
457 
458  template <typename U>
459  using enable_if_convertible =
460  enable_if_t<
461  conjunction<
462  negation<is_same<decay_t<U>, variant>>,
463  detail::is_not_in_place<decay_t<U>>,
464  detail::has_constructible_alternative<U,Types...>,
465  detail::can_construct_alternative<U,Types...>
466  >::value
467  >;
468 
469  template <typename U>
470  using enable_if_convert_assignable =
471  enable_if_t<
472  conjunction<
473  negation<is_same<decay_t<U>, variant>>,
474  detail::is_not_in_place<decay_t<U>>,
475  detail::has_constructible_alternative<U,Types...>,
476  detail::can_construct_alternative<U,Types...>,
477  detail::can_assign_alternative<U,Types...>
478  >::value
479  >;
480 
481  template <typename U>
482  using T_j = detail::constructible_alternative_t<U, Types...>;
483 
484  struct variant_ctor{};
485 
486  //--------------------------------------------------------------------------
487  // Constructors
488  //--------------------------------------------------------------------------
489  public:
490 
491  // (1)
492 
504  constexpr variant(detail::enable_overload_if_t<is_default_constructible,variant_ctor> = {})
505  noexcept(std::is_nothrow_default_constructible<first_type>::value);
506 
507  // (2)
508 
520  variant(detail::enable_overload_if_t<is_copy_constructible,const variant&> other)
521  noexcept(bpstd::conjunction<bpstd::is_nothrow_copy_constructible<Types>...>::value);
522  variant(detail::disable_overload_if_t<is_copy_constructible,const variant&> other) = delete;
523 
524  // (3)
525 
537  variant(detail::enable_overload_if_t<is_move_constructible,variant&&> other)
538  noexcept(bpstd::conjunction<bpstd::is_nothrow_move_constructible<Types>...>::value);
539  variant(detail::disable_overload_if_t<is_move_constructible,variant&&> other) = delete;
540 
541  // (4)
542 
566  template <typename T, typename=enable_if_convertible<T>>
567  constexpr variant(T&& t)
568  noexcept(bpstd::is_nothrow_constructible<typename bpstd::variant<Types...>::template T_j<T>,T>::value);
569 
570  // (5)
571 
584  template <typename T, typename... Args,
585  typename = enable_if_t<bpstd::is_constructible<T,Args...>::value>>
586  constexpr explicit variant(in_place_type_t<T>, Args&&... args);
587 
601  template <typename T, typename U, typename... Args,
602  typename = enable_if_t<bpstd::is_constructible<T,std::initializer_list<U>,Args...>::value>>
603  constexpr explicit variant(in_place_type_t<T>,
604  std::initializer_list<U> il, Args&&... args);
605 
606  // (7)
607 
620  template <std::size_t I, typename... Args,
621  typename = enable_if_t<i_is_in_range<I>::value && std::is_constructible<variant_alternative_t<I,variant>,Args...>::value>>
622  constexpr explicit variant(in_place_index_t<I>, Args&&... args);
623 
624  // (8)
625 
640  template <std::size_t I, typename U, typename...Args,
641  typename = enable_if_t<i_is_in_range<I>::value && std::is_constructible<variant_alternative_t<I,variant>,std::initializer_list<U>,Args...>::value>>
642  constexpr explicit variant(in_place_index_t<I>,
643  std::initializer_list<U> il, Args&&... args);
644 
645  //--------------------------------------------------------------------------
646 
654  variant& operator=(detail::enable_overload_if_t<is_copy_assignable,const variant&> other);
655  variant& operator=(detail::disable_overload_if_t<is_copy_assignable,const variant&> other) = delete;
656 
664  variant& operator=(detail::enable_overload_if_t<is_move_assignable,variant&&> other)
665  noexcept(conjunction<std::is_nothrow_move_constructible<Types>...,
666  std::is_nothrow_move_assignable<Types>...>::value);
667  variant& operator=(detail::disable_overload_if_t<is_move_assignable,variant&&> other) = delete;
668 
669  template <typename T, typename = enable_if_convert_assignable<T>>
670  variant& operator=(T&& t)
671  noexcept(std::is_nothrow_assignable<typename bpstd::variant<Types...>::template T_j<T>,T>::value &&
672  std::is_nothrow_constructible<typename bpstd::variant<Types...>::template T_j<T>,T>::value);
673 
674  //--------------------------------------------------------------------------
675  // Observers
676  //--------------------------------------------------------------------------
677  public:
678 
685  constexpr std::size_t index() const noexcept;
686 
690  constexpr bool valueless_by_exception() const noexcept;
691 
692  //--------------------------------------------------------------------------
693  // Modifiers
694  //--------------------------------------------------------------------------
695  public:
696 
709  template <typename T, typename...Args,
710  typename=enable_if_t<std::is_constructible<T,Args...>::value>>
711  T& emplace(Args&&... args);
712 
726  template <typename T, typename U, typename...Args,
727  typename=enable_if_t<std::is_constructible<T,std::initializer_list<U>&,Args...>::value>>
728  T& emplace(std::initializer_list<U> il, Args&&... args);
729 
747  template <std::size_t I, typename... Args,
748  typename=enable_if_t<std::is_constructible<detail::nth_type_t<I,Types...>,Args...>::value>>
749  variant_alternative_t<I, variant>& emplace(Args&&... args);
750 
770  template <std::size_t I, typename U, typename... Args,
771  typename=enable_if_t<std::is_constructible<detail::nth_type_t<I,Types...>,std::initializer_list<U>&,Args...>::value>>
772  variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il, Args&&... args);
773 
777  void swap(variant& rhs)
778  noexcept(bpstd::conjunction<bpstd::is_nothrow_move_constructible<Types>...,
779  bpstd::is_nothrow_swappable<Types>...>::value);
780 
781 
782  //--------------------------------------------------------------------------
783  // Private Members
784  //--------------------------------------------------------------------------
785  private:
786 
787  static bool alternative_is_nothrow_copy_constructible(std::size_t i) noexcept;
788  static bool alternative_is_nothrow_move_constructible(std::size_t i) noexcept;
789 
790  //--------------------------------------------------------------------------
791  // Friend Declarations
792  //--------------------------------------------------------------------------
793  private:
794 
795  // 'variant' requires a whole lot of friends, due to most of its API
796  // consisting of free-functions that access the underlying data.
797 
798  template <typename...UTypes>
799  friend BPSTD_CPP14_CONSTEXPR
800  bool operator==(const variant<UTypes...>&,
801  const variant<UTypes...>&) noexcept;
802 
803  template <typename...UTypes>
804  friend BPSTD_CPP14_CONSTEXPR
805  bool operator!=(const variant<UTypes...>&,
806  const variant<UTypes...>&) noexcept;
807 
808  template <typename...UTypes>
809  friend BPSTD_CPP14_CONSTEXPR
810  bool operator<(const variant<UTypes...>&,
811  const variant<UTypes...>&) noexcept;
812 
813  template <typename...UTypes>
814  friend BPSTD_CPP14_CONSTEXPR
815  bool operator>(const variant<UTypes...>&,
816  const variant<UTypes...>&) noexcept;
817 
818  template <typename...UTypes>
819  friend BPSTD_CPP14_CONSTEXPR
820  bool operator<=(const variant<UTypes...>&,
821  const variant<UTypes...>&) noexcept;
822 
823  template <typename...UTypes>
824  friend BPSTD_CPP14_CONSTEXPR
825  bool operator>=(const variant<UTypes...>&,
826  const variant<UTypes...>&) noexcept;
827 
828  template <typename Visitor, typename Variant>
829  BPSTD_CPP14_CONSTEXPR
830  friend detail::variant_visitor_invoke_result_t<Visitor,Variant>
831  visit(Visitor&&, Variant&&);
832 
833  template <std::size_t I, typename...UTypes>
834  friend BPSTD_CPP14_CONSTEXPR
835  variant_alternative_t<I, variant<UTypes...>>&
836  get(variant<UTypes...>&);
837 
838  template <std::size_t I, typename...UTypes>
839  friend BPSTD_CPP14_CONSTEXPR
840  variant_alternative_t<I, variant<UTypes...>>&&
841  get(variant<UTypes...>&&);
842 
843  template <std::size_t I, typename...UTypes>
844  friend BPSTD_CPP14_CONSTEXPR
845  const variant_alternative_t<I, variant<UTypes...>>&
846  get(const variant<UTypes...>&);
847 
848  template <std::size_t I, typename...UTypes>
849  friend BPSTD_CPP14_CONSTEXPR
850  const variant_alternative_t<I, variant<UTypes...>>&&
851  get(const variant<UTypes...>&&);
852 
853  template <std::size_t I, typename...UTypes>
854  friend constexpr
855  add_pointer_t<variant_alternative_t<I, variant<UTypes...>>>
856  get_if(variant<UTypes...>*) noexcept;
857 
858  template <std::size_t I, typename...UTypes>
859  friend constexpr
860  add_pointer_t<const variant_alternative_t<I, variant<UTypes...>>>
861  get_if(const variant<UTypes...>*) noexcept;
862 
863  };
864 
865  //============================================================================
866  // non-member functions : class : variant
867  //============================================================================
868 
869  //----------------------------------------------------------------------------
870  // Comparison
871  //----------------------------------------------------------------------------
872 
873  template <typename...Types>
874  BPSTD_CPP14_CONSTEXPR
875  bool operator==(const variant<Types...>& lhs,
876  const variant<Types...>& rhs) noexcept;
877  template <typename...Types>
878  BPSTD_CPP14_CONSTEXPR
879  bool operator!=(const variant<Types...>& lhs,
880  const variant<Types...>& rhs) noexcept;
881  template <typename...Types>
882  BPSTD_CPP14_CONSTEXPR
883  bool operator<(const variant<Types...>& lhs,
884  const variant<Types...>& rhs) noexcept;
885  template <typename...Types>
886  BPSTD_CPP14_CONSTEXPR
887  bool operator>(const variant<Types...>& lhs,
888  const variant<Types...>& rhs) noexcept;
889  template <typename...Types>
890  BPSTD_CPP14_CONSTEXPR
891  bool operator<=(const variant<Types...>& lhs,
892  const variant<Types...>& rhs) noexcept;
893  template <typename...Types>
894  BPSTD_CPP14_CONSTEXPR
895  bool operator>=(const variant<Types...>& lhs,
896  const variant<Types...>& rhs) noexcept;
897 
898  //----------------------------------------------------------------------------
899  // Utilities
900  //----------------------------------------------------------------------------
901 
906  template <typename...Types>
907  void swap(variant<Types...>& lhs, variant<Types...>& rhs)
908  noexcept(noexcept(lhs.swap(rhs)));
909 
910  //----------------------------------------------------------------------------
911  // Value Access
912  //----------------------------------------------------------------------------
913 
919  template <typename Visitor, typename Variant>
920  BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t<Visitor,Variant>
921  visit(Visitor&& visitor, Variant&& v);
922 
923  // /// \brief Visits the variants \p variant0 and \p variants
924  // ///
925  // /// \param visitor the visitor to visit the active entry of \p v0
926  // /// \param variant0 the first variant to visit
927  // /// \param variants the rest of the variant to visit
928  // /// \return the result of visiting the variants
929  template <typename Visitor, typename Variant0, typename...Variants>
930  BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t<Visitor,Variant0, Variants...>
931  visit(Visitor&& visitor, Variant0&& variant0, Variants&&...variants);
932 
933  //----------------------------------------------------------------------------
934 
941  template <typename T, typename...Types>
942  constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
943 
944  //----------------------------------------------------------------------------
945 
952  template <std::size_t I, typename...Types>
953  BPSTD_CPP14_CONSTEXPR variant_alternative_t<I, variant<Types...>>&
954  get(variant<Types...>& v);
955  template <std::size_t I, typename...Types>
956  BPSTD_CPP14_CONSTEXPR variant_alternative_t<I, variant<Types...>>&&
957  get(variant<Types...>&& v);
958  template <std::size_t I, typename...Types>
959  BPSTD_CPP14_CONSTEXPR const variant_alternative_t<I, variant<Types...>>&
960  get(const variant<Types...>& v);
961  template <std::size_t I, typename...Types>
962  BPSTD_CPP14_CONSTEXPR const variant_alternative_t<I, variant<Types...>>&&
963  get(const variant<Types...>&& v);
965 
966  //----------------------------------------------------------------------------
967 
976  template <typename T, typename...Types>
977  BPSTD_CPP14_CONSTEXPR T& get(variant<Types...>& v);
978  template <typename T, typename...Types>
979  BPSTD_CPP14_CONSTEXPR T&& get(variant<Types...>&& v);
980  template <typename T, typename...Types>
981  BPSTD_CPP14_CONSTEXPR const T& get(const variant<Types...>& v);
982  template <typename T, typename...Types>
983  BPSTD_CPP14_CONSTEXPR const T&& get(const variant<Types...>&& v);
985 
986  //----------------------------------------------------------------------------
987 
1000  template <std::size_t I, typename...Types>
1001  constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
1002  get_if(variant<Types...>* pv) noexcept;
1003  template <std::size_t I, typename...Types>
1004  constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
1005  get_if(const variant<Types...>* pv) noexcept;
1007 
1019  template <typename T, typename...Types>
1020  constexpr add_pointer_t<T> get_if(variant<Types...>* pv) noexcept;
1021  template <typename T, typename...Types>
1022  constexpr add_pointer_t<const T> get_if(const variant<Types...>* pv) noexcept;
1024 
1025 } // namespace bpstd
1026 
1027 //==============================================================================
1028 // struct : monostate
1029 //==============================================================================
1030 
1031 inline BPSTD_INLINE_VISIBILITY constexpr
1032 bool bpstd::operator==(monostate, monostate)
1033  noexcept
1034 {
1035  return true;
1036 }
1037 
1038 inline BPSTD_INLINE_VISIBILITY constexpr
1039 bool bpstd::operator!=(monostate, monostate)
1040  noexcept
1041 {
1042  return false;
1043 }
1044 
1045 inline BPSTD_INLINE_VISIBILITY constexpr
1046 bool bpstd::operator<(monostate, monostate)
1047  noexcept
1048 {
1049  return false;
1050 }
1051 
1052 inline BPSTD_INLINE_VISIBILITY constexpr
1053 bool bpstd::operator>(monostate, monostate)
1054  noexcept
1055 {
1056  return false;
1057 }
1058 
1059 inline BPSTD_INLINE_VISIBILITY constexpr
1060 bool bpstd::operator<=(monostate, monostate)
1061  noexcept
1062 {
1063  return true;
1064 }
1065 
1066 inline BPSTD_INLINE_VISIBILITY constexpr
1067 bool bpstd::operator>=(monostate, monostate)
1068  noexcept
1069 {
1070  return true;
1071 }
1072 
1073 //==============================================================================
1074 // class : bad_variant_access
1075 //==============================================================================
1076 
1077 inline
1079  const noexcept
1080 {
1081  return "bad_variant_access";
1082 }
1083 
1084 //==============================================================================
1085 // class : variant
1086 //==============================================================================
1087 
1088 //------------------------------------------------------------------------------
1089 // Constructors / Assignment
1090 //------------------------------------------------------------------------------
1091 
1092 template <typename...Types>
1093 inline BPSTD_INLINE_VISIBILITY constexpr
1094 bpstd::variant<Types...>::variant(detail::enable_overload_if_t<is_default_constructible,variant_ctor>)
1095  noexcept(std::is_nothrow_default_constructible<first_type>::value)
1096  : base_type{detail::variant_index_tag<0>{}}
1097 {
1098 
1099 }
1100 
1101 template <typename...Types>
1102 inline BPSTD_INLINE_VISIBILITY
1103 bpstd::variant<Types...>::variant(detail::enable_overload_if_t<is_copy_constructible,const variant&> other)
1104  noexcept(bpstd::conjunction<bpstd::is_nothrow_copy_constructible<Types>...>::value)
1105  : base_type{}
1106 {
1107  if (other.valueless_by_exception()) {
1108  return;
1109  }
1110  detail::visit_union(
1111  other.base_type::m_index,
1112  detail::variant_copy_construct_visitor{},
1113  base_type::m_union,
1114  other.base_type::m_union
1115  );
1116  base_type::m_index = other.base_type::m_index;
1117 }
1118 
1119 template <typename...Types>
1120 inline BPSTD_INLINE_VISIBILITY
1121 bpstd::variant<Types...>::variant(detail::enable_overload_if_t<is_move_constructible,variant&&> other)
1122  noexcept(bpstd::conjunction<bpstd::is_nothrow_move_constructible<Types>...>::value)
1123  : base_type{}
1124 {
1125  if (other.valueless_by_exception()) {
1126  return;
1127  }
1128  detail::visit_union(
1129  other.base_type::m_index,
1130  detail::variant_move_construct_visitor{},
1131  base_type::m_union,
1132  bpstd::move(other.base_type::m_union)
1133  );
1134  base_type::m_index = other.base_type::m_index;
1135 }
1136 
1137 template <typename...Types>
1138 template <typename T, typename>
1139 inline BPSTD_INLINE_VISIBILITY constexpr
1141  noexcept(bpstd::is_nothrow_constructible<typename bpstd::variant<Types...>::template T_j<T>,T>::value)
1142  : base_type{
1143  detail::variant_index_tag<detail::index_of_constructible_alternative<T, Types...>::value>{},
1144  bpstd::forward<T>(t)
1145  }
1146 {
1147 
1148 }
1149 
1150 template <typename...Types>
1151 template <typename T, typename... Args, typename>
1152 inline BPSTD_INLINE_VISIBILITY constexpr
1153 bpstd::variant<Types...>::variant(in_place_type_t<T>, Args&&... args)
1154  : base_type{
1155  detail::variant_index_tag<detail::index_from<T, Types...>::value>{},
1156  bpstd::forward<Args>(args)...
1157  }
1158 {
1159 
1160 }
1161 
1162 template <typename...Types>
1163 template <typename T, typename U, typename... Args, typename>
1164 inline BPSTD_INLINE_VISIBILITY constexpr
1165 bpstd::variant<Types...>::variant(in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)
1166  : base_type{
1167  detail::variant_index_tag<detail::index_from<T, Types...>::value>{},
1168  il, bpstd::forward<Args>(args)...
1169  }
1170 {
1171 
1172 }
1173 
1174 template <typename...Types>
1175 template <std::size_t I, typename... Args, typename>
1176 inline BPSTD_INLINE_VISIBILITY constexpr
1177 bpstd::variant<Types...>::variant(in_place_index_t<I>, Args&&... args)
1178  : base_type{
1179  detail::variant_index_tag<I>{},
1180  bpstd::forward<Args>(args)...
1181  }
1182 {
1183 
1184 }
1185 
1186 template <typename...Types>
1187 template <std::size_t I, typename U, typename... Args, typename>
1188 inline BPSTD_INLINE_VISIBILITY constexpr
1189 bpstd::variant<Types...>::variant(in_place_index_t<I>, std::initializer_list<U> il, Args&&... args)
1190  : base_type{
1191  detail::variant_index_tag<I>{},
1192  il, bpstd::forward<Args>(args)...
1193  }
1194 {
1195 
1196 }
1197 
1198 //------------------------------------------------------------------------------
1199 
1200 template <typename...Types>
1201 inline BPSTD_INLINE_VISIBILITY
1202 bpstd::variant<Types...>&
1203  bpstd::variant<Types...>::operator=(detail::enable_overload_if_t<is_copy_assignable,const variant&> other)
1204 {
1205  if (other.valueless_by_exception()) {
1206  base_type::destroy_active_object();
1207  return (*this);
1208  }
1209 
1210  if (other.base_type::m_index == base_type::m_index) {
1211  detail::visit_union(
1212  other.base_type::m_index,
1213  detail::variant_copy_assign_visitor{},
1214  base_type::m_union,
1215  other.base_type::m_union
1216  );
1217  return (*this);
1218  }
1219 
1220  const auto should_copy =
1221  alternative_is_nothrow_copy_constructible(other.index()) ||
1222  !alternative_is_nothrow_move_constructible(other.index());
1223 
1224  if (should_copy) {
1225  base_type::destroy_active_object();
1226  detail::visit_union(
1227  other.base_type::m_index,
1228  detail::variant_copy_construct_visitor{},
1229  base_type::m_union,
1230  other.base_type::m_union
1231  );
1232  base_type::m_index = other.base_type::m_index;
1233  return (*this);
1234  }
1235 
1236  return this->operator=(variant(other));
1237 }
1238 
1239 template <typename...Types>
1240 inline BPSTD_INLINE_VISIBILITY
1241 bpstd::variant<Types...>&
1242  bpstd::variant<Types...>::operator=(detail::enable_overload_if_t<is_move_assignable,variant&&> other)
1243  noexcept(conjunction<std::is_nothrow_move_constructible<Types>...,
1244  std::is_nothrow_move_assignable<Types>...>::value)
1245 {
1246  if (other.valueless_by_exception()) {
1247  base_type::destroy_active_object();
1248  return (*this);
1249  }
1250 
1251  if (other.base_type::m_index == base_type::m_index) {
1252  detail::visit_union(
1253  other.base_type::m_index,
1254  detail::variant_move_assign_visitor{},
1255  base_type::m_union,
1256  bpstd::move(other.base_type::m_union)
1257  );
1258  return (*this);
1259  }
1260 
1261  base_type::destroy_active_object();
1262  detail::visit_union(
1263  other.base_type::m_index,
1264  detail::variant_move_construct_visitor{},
1265  base_type::m_union,
1266  bpstd::move(other.base_type::m_union)
1267  );
1268  base_type::m_index = other.base_type::m_index;
1269 
1270  return (*this);
1271 }
1272 
1273 template <typename...Types>
1274 template <typename T, typename>
1275 inline BPSTD_INLINE_VISIBILITY
1277  noexcept(std::is_nothrow_assignable<typename bpstd::variant<Types...>::template T_j<T>,T>::value &&
1278  std::is_nothrow_constructible<typename bpstd::variant<Types...>::template T_j<T>,T>::value)
1279 {
1280  static constexpr auto index = detail::index_of_constructible_alternative<T,Types...>::value;
1281 
1282  using type = detail::constructible_alternative_t<T,Types...>;
1283 
1284  if (base_type::m_index == index) {
1285  detail::visit_union(
1286  base_type::m_index,
1287  detail::variant_assign_visitor<type,T>{bpstd::forward<T>(t)},
1288  base_type::m_union
1289  );
1290  return (*this);
1291  }
1292 
1293  const auto should_emplace =
1294  alternative_is_nothrow_copy_constructible(index) ||
1295  !alternative_is_nothrow_move_constructible(index);
1296 
1297  if (should_emplace) {
1298  emplace<index>(bpstd::forward<T>(t));
1299  return (*this);
1300  }
1301 
1302  return this->operator=(variant(bpstd::forward<T>(t)));
1303 }
1304 
1305 //------------------------------------------------------------------------------
1306 // Observers
1307 //------------------------------------------------------------------------------
1308 
1309 template <typename...Types>
1310 inline BPSTD_INLINE_VISIBILITY constexpr
1312  const noexcept
1313 {
1314  return base_type::m_index;
1315 }
1316 
1317 template <typename...Types>
1318 inline BPSTD_INLINE_VISIBILITY constexpr
1320  const noexcept
1321 {
1322  return index() == variant_npos;
1323 }
1324 
1325 //------------------------------------------------------------------------------
1326 // Modifiers
1327 //------------------------------------------------------------------------------
1328 
1329 template <typename...Types>
1330 template <typename T, typename...Args, typename>
1331 inline BPSTD_INLINE_VISIBILITY
1332 T& bpstd::variant<Types...>::emplace(Args&&...args)
1333 {
1334  using index_type = detail::index_from<T,Types...>;
1335 
1336  static_assert(index_type::value != variant_npos, "T must be a valid alternative");
1337 
1338  return emplace<index_type::value>(bpstd::forward<Args>(args)...);
1339 }
1340 
1341 template <typename...Types>
1342 template <typename T, typename U, typename...Args, typename>
1343 inline BPSTD_INLINE_VISIBILITY
1344 T& bpstd::variant<Types...>::emplace(std::initializer_list<U> il, Args&&...args)
1345 {
1346  using index_type = detail::index_from<T,Types...>;
1347 
1348  static_assert(index_type::value != variant_npos, "T must be a valid alternative");
1349 
1350  return emplace<index_type::value>(il, bpstd::forward<Args>(args)...);
1351 }
1352 
1353 template <typename...Types>
1354 template <std::size_t I, typename... Args, typename>
1355 inline BPSTD_INLINE_VISIBILITY
1357  bpstd::variant<Types...>::emplace(Args&&...args)
1358 {
1359  using type = detail::nth_type_t<I,Types...>;
1360 
1361  base_type::destroy_active_object();
1362 
1363  using tuple_type = decltype(std::forward_as_tuple(bpstd::forward<Args>(args)...));
1364 
1365  auto visitor = detail::variant_emplace_visitor<type, tuple_type>(
1366  std::forward_as_tuple(bpstd::forward<Args>(args)...)
1367  );
1368 
1369  detail::visit_union(I, visitor, base_type::m_union);
1370  base_type::m_index = I;
1371 
1372  return detail::union_get<I>(base_type::m_union);
1373 }
1374 
1375 
1376 template <typename...Types>
1377 template <std::size_t I, typename U, typename... Args, typename>
1378 inline BPSTD_INLINE_VISIBILITY
1380  bpstd::variant<Types...>::emplace(std::initializer_list<U> il, Args&&... args)
1381 {
1382  using type = detail::nth_type_t<I,Types...>;
1383 
1384  base_type::destroy_active_object();
1385 
1386  using tuple_type = decltype(std::forward_as_tuple(il, bpstd::forward<Args>(args)...));
1387 
1388  auto visitor = detail::variant_emplace_visitor<type, tuple_type>(
1389  std::forward_as_tuple(il, bpstd::forward<Args>(args)...)
1390  );
1391 
1392  detail::visit_union(I, visitor, base_type::m_union);
1393  base_type::m_index = I;
1394 
1395  return detail::union_get<I>(base_type::m_union);
1396 }
1397 
1398 template <typename...Types>
1399 inline BPSTD_INLINE_VISIBILITY
1401  noexcept(bpstd::conjunction<bpstd::is_nothrow_move_constructible<Types>...,
1402  bpstd::is_nothrow_swappable<Types>...>::value)
1403 
1404 {
1405  if (valueless_by_exception() && other.valueless_by_exception()) {
1406  return;
1407  }
1408 
1409  if (base_type::m_index == other.base_type::m_index) {
1410  detail::visit_union(
1411  base_type::m_index,
1412  detail::variant_swap_visitor{},
1413  base_type::m_union,
1414  other.m_union
1415  );
1416  } else {
1417  auto temp = bpstd::move(*this);
1418  *this = bpstd::move(other);
1419  other = bpstd::move(temp);
1420  }
1421 }
1422 
1423 template <typename...Types>
1424 inline BPSTD_INLINE_VISIBILITY
1426  noexcept
1427 {
1428  const bool alternatives[]{bpstd::is_nothrow_copy_constructible<Types>::value...};
1429 
1430  return alternatives[i];
1431 }
1432 
1433 template <typename...Types>
1434 inline BPSTD_INLINE_VISIBILITY
1436  noexcept
1437 {
1438  const bool alternatives[]{bpstd::is_nothrow_move_constructible<Types>::value...};
1439 
1440  return alternatives[i];
1441 }
1442 
1443 //==============================================================================
1444 // non-member functions : class : variant
1445 //==============================================================================
1446 
1447 //------------------------------------------------------------------------------
1448 // Comparisons
1449 //------------------------------------------------------------------------------
1450 
1451 template <typename...Types>
1452 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1453 bool bpstd::operator==(const variant<Types...>& lhs,
1454  const variant<Types...>& rhs)
1455  noexcept
1456 {
1457  if (lhs.index() != rhs.index()) {
1458  return false;
1459  }
1460  if (lhs.valueless_by_exception()) {
1461  return true;
1462  }
1463  return detail::visit_union(lhs.index(), equal_to<>{}, lhs.m_union, rhs.m_union);
1464 }
1465 
1466 template <typename...Types>
1467 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1468 bool bpstd::operator!=(const variant<Types...>& lhs,
1469  const variant<Types...>& rhs)
1470  noexcept
1471 {
1472  if (lhs.index() != rhs.index()) {
1473  return true;
1474  }
1475  if (lhs.valueless_by_exception()) {
1476  return false;
1477  }
1478  return detail::visit_union(lhs.index(), not_equal_to<>{}, lhs.m_union, rhs.m_union);
1479 }
1480 
1481 template <typename...Types>
1482 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1483 bool bpstd::operator<(const variant<Types...>& lhs,
1484  const variant<Types...>& rhs)
1485  noexcept
1486 {
1487  if (rhs.valueless_by_exception()) {
1488  return false;
1489  }
1490  if (lhs.valueless_by_exception()) {
1491  return true;
1492  }
1493  if (lhs.index() < rhs.index()) {
1494  return true;
1495  }
1496  if (lhs.index() > rhs.index()) {
1497  return false;
1498  }
1499  return detail::visit_union(lhs.index(), less<>{}, lhs.m_union, rhs.m_union);
1500 }
1501 
1502 template <typename...Types>
1503 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1504 bool bpstd::operator>(const variant<Types...>& lhs,
1505  const variant<Types...>& rhs)
1506  noexcept
1507 {
1508  if (lhs.valueless_by_exception()) {
1509  return false;
1510  }
1511  if (rhs.valueless_by_exception()) {
1512  return true;
1513  }
1514  if (lhs.index() > rhs.index()) {
1515  return true;
1516  }
1517  if (lhs.index() < rhs.index()) {
1518  return false;
1519  }
1520  return detail::visit_union(lhs.index(), greater<>{}, lhs.m_union, rhs.m_union);
1521 }
1522 
1523 template <typename...Types>
1524 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1525 bool bpstd::operator<=(const variant<Types...>& lhs,
1526  const variant<Types...>& rhs)
1527  noexcept
1528 {
1529  if (lhs.valueless_by_exception()) {
1530  return true;
1531  }
1532  if (rhs.valueless_by_exception()) {
1533  return false;
1534  }
1535  if (lhs.index() < rhs.index()) {
1536  return true;
1537  }
1538  if (lhs.index() > rhs.index()) {
1539  return false;
1540  }
1541  return detail::visit_union(lhs.index(), less_equal<>{}, lhs.m_union, rhs.m_union);
1542 }
1543 
1544 template <typename...Types>
1545 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1546 bool bpstd::operator>=(const variant<Types...>& lhs,
1547  const variant<Types...>& rhs)
1548  noexcept
1549 {
1550  if (rhs.valueless_by_exception()) {
1551  return true;
1552  }
1553  if (lhs.valueless_by_exception()) {
1554  return false;
1555  }
1556  if (lhs.index() > rhs.index()) {
1557  return true;
1558  }
1559  if (lhs.index() < rhs.index()) {
1560  return false;
1561  }
1562  return detail::visit_union(lhs.index(), greater_equal<>{}, lhs.m_union, rhs.m_union);
1563 }
1564 
1565 //------------------------------------------------------------------------------
1566 // Utilities
1567 //------------------------------------------------------------------------------
1568 
1569 template <typename...Types>
1570 inline BPSTD_INLINE_VISIBILITY
1571 void bpstd::swap(variant<Types...>& lhs, variant<Types...>& rhs)
1572  noexcept(noexcept(lhs.swap(rhs)))
1573 {
1574  lhs.swap(rhs);
1575 }
1576 
1577 //------------------------------------------------------------------------------
1578 // Value Access
1579 //------------------------------------------------------------------------------
1580 
1581 template <typename Visitor, typename Variant>
1582 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1583 bpstd::detail::variant_visitor_invoke_result_t<Visitor,Variant>
1584  bpstd::visit(Visitor&& visitor, Variant&& v)
1585 {
1586  using union_type = detail::match_cvref_t<Variant, decltype(v.m_union)>;
1587 
1588  if (v.valueless_by_exception()) {
1589  throw bad_variant_access{};
1590  }
1591 
1592  return detail::visit_union(
1593  v.index(),
1594  bpstd::forward<Visitor>(visitor),
1595  static_cast<union_type>(v.m_union)
1596  );
1597 }
1598 
1599 namespace bpstd { namespace detail {
1600 
1601 template <typename Variant0, typename...Variants>
1602 inline BPSTD_INLINE_VISIBILITY constexpr
1603 bool are_any_valueless_by_exception(const Variant0& v0, const Variants&...vs)
1604 {
1605  return v0.valueless_by_exception() || are_any_valueless_by_exception(vs...);
1606 }
1607 
1608 template <typename Variant0>
1609 inline BPSTD_INLINE_VISIBILITY constexpr
1610 bool are_any_valueless_by_exception(const Variant0& v0)
1611 {
1612  return v0.valueless_by_exception();
1613 }
1614 
1615 template <typename...Args, typename T, std::size_t...Idxs>
1616 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1617 std::tuple<Args&&...,T&&> tuple_push_back_aux(std::tuple<Args...>& args, T&& v, index_sequence<Idxs...>)
1618 {
1619  (void) args;
1620  return std::forward_as_tuple(std::get<Idxs>(bpstd::move(args))..., bpstd::forward<T>(v));
1621 }
1622 
1623 // Appends an element to a forwarding tuple
1624 // Returns with '&&' to reference-collapse returned types
1625 template <typename...Args, typename T>
1626 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1627 std::tuple<Args&&...,T&&> tuple_push_back(std::tuple<Args...>& args, T&& t)
1628 {
1629  static_assert(
1630  conjunction<is_reference<Args>...,true_type>::value,
1631  "'args' must be a forwarding tuple'"
1632  );
1633  // return std::tuple_cat(args, std::forward_as_tuple(std::forward<T>(t)));
1634  return tuple_push_back_aux(args, bpstd::forward<T>(t), index_sequence_for<Args...>{});
1635 }
1636 
1637 template <typename Arg0, typename...Args, std::size_t...Idxs>
1638 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1639 std::tuple<Args...> tuple_pop_front_aux(std::tuple<Arg0,Args...>& args, index_sequence<0, Idxs...>)
1640 {
1641  (void) args;
1642  return std::forward_as_tuple(std::get<Idxs>(bpstd::move(args))...);
1643 }
1644 
1645 // Removes the front element of a forwarding tuple
1646 template <typename Arg0, typename...Args>
1647 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1648 std::tuple<Args...> tuple_pop_front(std::tuple<Arg0,Args...>& args)
1649 {
1650  static_assert(
1651  conjunction<is_reference<Arg0>,is_reference<Args>...>::value,
1652  "'args' must be a forwarding tuple'"
1653  );
1654 
1655  return tuple_pop_front_aux(args, index_sequence_for<Arg0,Args...>{});
1656 }
1657 
1658 template <typename Return, typename Visitor, typename Variants, typename Arguments>
1659 class multi_variant_visitor;
1660 
1661 template <typename T, typename Visitor, typename Variants, typename Arguments>
1662 BPSTD_CPP14_CONSTEXPR
1663 multi_variant_visitor<T, Visitor, remove_cvref_t<Variants>, remove_cvref_t<Arguments>>
1664  make_multi_visitor(Visitor&& vistior, Variants&& variants, Arguments&& args);
1665 
1666 template <typename Return, typename Visitor, typename Variant0, typename...Variants, typename...Args>
1667 class multi_variant_visitor<Return, Visitor, std::tuple<Variant0,Variants...>, std::tuple<Args...>>
1668 {
1669  static_assert(
1670  conjunction<is_reference<Variant0>, is_reference<Variants>...>::value,
1671  "All Variants must be captured by reference"
1672  );
1673  static_assert(
1674  conjunction<is_reference<Args>...,true_type>::value,
1675  "All arguments must be captured by reference"
1676  );
1677 
1678 public:
1679  template <typename UVisitor, typename UVariants, typename Arguments>
1680  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1681  multi_variant_visitor(UVisitor&& visitor, UVariants&& variants, Arguments&& args)
1682  : m_visitor(bpstd::forward<UVisitor>(visitor)),
1683  m_variants(bpstd::forward<UVariants>(variants)),
1684  m_args(bpstd::forward<Arguments>(args))
1685  {
1686 
1687  }
1688 
1689  template <typename T>
1690  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1691  Return operator()(T&& v)
1692  {
1693  // static_assert(is_reference<T>::value, "T should always be a reference type");
1694 
1695  return visit(
1696  detail::make_multi_visitor<Return>(
1697  bpstd::forward<Visitor>(m_visitor),
1698  tuple_pop_front(m_variants),
1699  tuple_push_back(m_args, bpstd::forward<T>(v))
1700  ),
1701  std::get<0>(bpstd::move(m_variants)) // 'move' used for reference collapse
1702  );
1703  }
1704 
1705 private:
1706 
1707  Visitor m_visitor;
1708  std::tuple<Variant0, Variants...> m_variants;
1709  std::tuple<Args...> m_args;
1710 };
1711 
1712 template <typename Return, typename Visitor, typename...Args>
1713 class multi_variant_visitor<Return,Visitor,std::tuple<>,std::tuple<Args...>>
1714 {
1715  static_assert(
1716  conjunction<is_reference<Args>...,true_type>::value,
1717  "All arguments must be captured by reference"
1718  );
1719 
1720 public:
1721  template <typename UVisitor, typename Variants, typename Arguments>
1722  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1723  multi_variant_visitor(UVisitor&& visitor, Variants&&, Arguments&& args)
1724  : m_visitor(bpstd::forward<UVisitor>(visitor)),
1725  m_args(bpstd::forward<Arguments>(args))
1726  {
1727 
1728  }
1729 
1730  template <typename T>
1731  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1732  Return operator()(T&& v)
1733  {
1734  return apply(
1735  bpstd::forward<Visitor>(m_visitor),
1736  tuple_push_back(m_args, bpstd::forward<T>(v))
1737  );
1738  }
1739 
1740 private:
1741 
1742  Visitor m_visitor;
1743  std::tuple<Args...> m_args;
1744 };
1745 
1746 template <typename T, typename Visitor, typename Variants, typename Arguments>
1747 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1748 multi_variant_visitor<T,Visitor, remove_cvref_t<Variants>, remove_cvref_t<Arguments>>
1749  make_multi_visitor(Visitor&& visitor, Variants&& variants, Arguments&& args)
1750 {
1751  return {
1752  bpstd::forward<Visitor>(visitor),
1753  bpstd::forward<Variants>(variants),
1754  bpstd::forward<Arguments>(args)
1755  };
1756 }
1757 
1758 }} // namespace bpstd::detail
1759 
1760 template <typename Visitor, typename Variant0, typename...Variants>
1761 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1762 bpstd::detail::variant_visitor_invoke_result_t<Visitor,Variant0, Variants...>
1763  bpstd::visit(Visitor&& visitor, Variant0&& variant0, Variants&&...variants)
1764 {
1765  using type = bpstd::detail::variant_visitor_invoke_result_t<Visitor,Variant0, Variants...>;
1766 
1767  if (detail::are_any_valueless_by_exception(variant0, variants...)) {
1768  throw bad_variant_access{};
1769  }
1770 
1771  return visit(
1772  detail::make_multi_visitor<type>(
1773  bpstd::forward<Visitor>(visitor),
1774  std::forward_as_tuple(bpstd::forward<Variants>(variants)...),
1775  std::make_tuple()
1776  ),
1777  bpstd::forward<Variant0>(variant0)
1778  );
1779 
1780 }
1781 
1782 
1783 template <typename T, typename...Types>
1784 inline BPSTD_INLINE_VISIBILITY constexpr
1785 bool bpstd::holds_alternative(const variant<Types...>& v)
1786  noexcept
1787 {
1788  return detail::index_from<T,Types...>::value == v.index();
1789 }
1790 
1791 //------------------------------------------------------------------------------
1792 
1793 template <std::size_t I, typename...Types>
1794 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1796  bpstd::get(variant<Types...>& v)
1797 {
1798  static_assert(
1799  I < sizeof...(Types),
1800  "I is not a valid index into the variant"
1801  );
1802 
1803  if (v.index() != I) {
1804  throw bad_variant_access{};
1805  }
1806  return detail::union_get<I>(v.m_union);
1807 }
1808 
1809 template <std::size_t I, typename...Types>
1810 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1812  bpstd::get(variant<Types...>&& v)
1813 {
1814  static_assert(
1815  I < sizeof...(Types),
1816  "I is not a valid index into the variant"
1817  );
1818 
1819  if (v.index() != I) {
1820  throw bad_variant_access{};
1821  }
1822  return bpstd::move(detail::union_get<I>(v.m_union));
1823 }
1824 
1825 template <std::size_t I, typename...Types>
1826 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1827 const bpstd::variant_alternative_t<I, bpstd::variant<Types...>>&
1828  bpstd::get(const variant<Types...>& v)
1829 {
1830  static_assert(
1831  I < sizeof...(Types),
1832  "I is not a valid index into the variant"
1833  );
1834 
1835  if (v.index() != I) {
1836  throw bad_variant_access{};
1837  }
1838  return detail::union_get<I>(v.m_union);
1839 }
1840 
1841 template <std::size_t I, typename...Types>
1842 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1843 const bpstd::variant_alternative_t<I, bpstd::variant<Types...>>&&
1844  bpstd::get(const variant<Types...>&& v)
1845 {
1846  static_assert(
1847  I < sizeof...(Types),
1848  "I is not a valid index into the variant"
1849  );
1850 
1851  if (v.index() != I) {
1852  throw bad_variant_access{};
1853  }
1854  return bpstd::move(detail::union_get<I>(v.m_union));
1855 }
1856 
1857 //------------------------------------------------------------------------------
1858 
1859 template <typename T, typename...Types>
1860 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1861 T& bpstd::get(variant<Types...>& v)
1862 {
1863  using index_type = detail::index_from<T,Types...>;
1864 
1865  return get<index_type::value>(v);
1866 }
1867 
1868 template <typename T, typename...Types>
1869 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1870 T&& bpstd::get(variant<Types...>&& v)
1871 {
1872  using index_type = detail::index_from<T,Types...>;
1873 
1874  return get<index_type::value>(bpstd::move(v));
1875 }
1876 
1877 template <typename T, typename...Types>
1878 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1879 const T& bpstd::get(const variant<Types...>& v)
1880 {
1881  using index_type = detail::index_from<T,Types...>;
1882 
1883  return get<index_type::value>(v);
1884 }
1885 
1886 template <typename T, typename...Types>
1887 inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
1888 const T&& bpstd::get(const variant<Types...>&& v)
1889 {
1890  using index_type = detail::index_from<T,Types...>;
1891 
1892  return get<index_type::value>(bpstd::move(v));
1893 }
1894 
1895 //------------------------------------------------------------------------------
1896 //------------------------------------------------------------------------------
1897 
1898 template <std::size_t I, typename...Types>
1899 inline BPSTD_INLINE_VISIBILITY constexpr
1900 bpstd::add_pointer_t<bpstd::variant_alternative_t<I, bpstd::variant<Types...>>>
1901  bpstd::get_if(variant<Types...>* pv)
1902  noexcept
1903 {
1904  static_assert(
1905  I < sizeof...(Types),
1906  "I is not a valid index into the variant"
1907  );
1908 
1909  return (pv == nullptr || I != pv->index())
1910  ? nullptr
1911  : &detail::union_get<I>(pv->m_union);
1912 }
1913 
1914 template <std::size_t I, typename...Types>
1915 inline BPSTD_INLINE_VISIBILITY constexpr
1916 bpstd::add_pointer_t<const bpstd::variant_alternative_t<I, bpstd::variant<Types...>>>
1917  bpstd::get_if(const variant<Types...>* pv)
1918  noexcept
1919 {
1920  static_assert(
1921  I < sizeof...(Types),
1922  "I is not a valid index into the variant"
1923  );
1924 
1925  return (pv == nullptr || I != pv->index())
1926  ? nullptr
1927  : &detail::union_get<I>(pv->m_union);
1928 }
1929 
1930 //------------------------------------------------------------------------------
1931 
1932 template <typename T, typename...Types>
1933 inline BPSTD_INLINE_VISIBILITY constexpr
1934 bpstd::add_pointer_t<T>
1935  bpstd::get_if(variant<Types...>* pv)
1936  noexcept
1937 {
1938  using index_type = detail::index_from<T,Types...>;
1939 
1940  return get_if<index_type::value>(pv);
1941 }
1942 
1943 template <typename T, typename...Types>
1944 inline BPSTD_INLINE_VISIBILITY constexpr
1945 bpstd::add_pointer_t<const T>
1946  bpstd::get_if(const variant<Types...>* pv)
1947  noexcept
1948 {
1949  using index_type = detail::index_from<T,Types...>;
1950 
1951  return get_if<index_type::value>(pv);
1952 }
1953 
1954 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
1955 
1956 #endif /* BPSTD_VARIANT_HPP */
bpstd::apply
constexpr detail::apply_result_t< Fn, Tuple > apply(Fn &&fn, Tuple &&tuple)
Invokes the function fn using the arguments in tuple.
bpstd::variant_npos
constexpr BPSTD_CPP17_INLINE auto variant_npos
This is a special value equal to the largest value representable by the type std::size_t,...
Definition: variant.hpp:164
bpstd::variant::visit
BPSTD_CPP14_CONSTEXPR friend detail::variant_visitor_invoke_result_t< Visitor, Variant > visit(Visitor &&, Variant &&)
Visits the variant v with the given visitor.
type_traits.hpp
This header provides definitions from the C++ header <type_traits>
bpstd::variant::valueless_by_exception
constexpr bool valueless_by_exception() const noexcept
Returns false if and only if the variant holds a value.
Definition: variant.hpp:1319
tuple.hpp
This header provides definitions from the C++ header <tuple>
bpstd::conjunction
Type trait to determine the bool_constant from a logical AND operation of other bool_constants.
Definition: type_traits.hpp:110
bpstd::bad_variant_access::bad_variant_access
bad_variant_access() noexcept=default
Constructs a new instance of bad_variant_access.
bpstd::get
const BPSTD_CPP14_CONSTEXPR T && get(const variant< Types... > &&v)
Gets the underlying element of the variant with the specified type.
bpstd::bad_variant_access
Exception thrown by variant.
Definition: variant.hpp:179
bpstd::visit
BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t< Visitor, Variant > visit(Visitor &&visitor, Variant &&v)
Visits the variant v with the given visitor.
bpstd::variant::index
constexpr std::size_t index() const noexcept
Returns the zero-based index of the alternative that is currently held by the variant.
Definition: variant.hpp:1311
bpstd::variant
The class template variant represents a type-safe union.
Definition: variant.hpp:76
functional.hpp
This header provides definitions from the C++ header <functional>
bpstd::get_if
constexpr add_pointer_t< const T > get_if(const variant< Types... > *pv) noexcept
Type-based non-throwing accessor.
bpstd::monostate
Definition: variant.hpp:62
bpstd::variant_size
Provides access to the number of alternatives in a possibly cv-qualified variant as a compile-time co...
Definition: variant.hpp:88
bpstd::variant_alternative_t
typename variant_alternative< I, T >::type variant_alternative_t
A helper template for extracting the ::type from variant_alternative.
Definition: variant.hpp:155
bpstd::variant::swap
void swap(variant &rhs) noexcept(bpstd::conjunction< bpstd::is_nothrow_move_constructible< Types >..., bpstd::is_nothrow_swappable< Types >... >::value)
Swaps the contents of this and rhs.
Definition: variant.hpp:1400
bpstd::variant::operator=
variant & operator=(detail::enable_overload_if_t< is_copy_assignable, const variant & > other)
Copy assigns the contents of other to this.
Definition: variant.hpp:1203
bpstd::swap
void swap(variant< Types... > &lhs, variant< Types... > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Swaps the contents of lhs with rhs.
bpstd::variant_alternative
Helper variable template for extracting variant_size<T>::value.
Definition: variant.hpp:128
bpstd::variant::variant
constexpr variant(detail::enable_overload_if_t< is_default_constructible, variant_ctor >={}) noexcept(std::is_nothrow_default_constructible< first_type >::value)
Default constructor.
Definition: variant.hpp:1094
bpstd::variant::emplace
T & emplace(Args &&... args)
Creates a new value in-place.
bpstd::bad_variant_access::what
const char * what() const noexcept override
returns an explanatory string of the exception
Definition: variant.hpp:1078
utility.hpp
This header provides definitions from the C++ header <utility>
bpstd::holds_alternative
constexpr bool holds_alternative(const variant< Types... > &v) noexcept
Checks if the variant v holds the alternative T.