General Utility Library for C++14  2.9
variant.h
Go to the documentation of this file.
1 
19 #ifndef GUL14_VARIANT_H_
20 #define GUL14_VARIANT_H_
21 
22 #include <cstddef>
23 #include <exception>
24 #include <functional>
25 #include <initializer_list>
26 #include <limits>
27 #include <new>
28 #include <type_traits>
29 #include <utility>
30 
31 #include "gul14/internal.h"
32 #include "gul14/traits.h"
33 #include "gul14/utility.h" // in_place*, monostate
34 
35 namespace gul14 {
36 
48 class bad_variant_access : public std::exception
49 {
50 public:
51  virtual const char* what() const noexcept override
52  {
53  return "bad_variant_access";
54  }
55 };
56 
70 template <typename... Ts>
71 class variant;
72 
89 template <typename Visitor, typename... Variants>
90 inline constexpr decltype(auto) visit(Visitor&& visitor_fct, Variants&&... variants);
91 
103 template <typename Fct1, typename... Fcts>
104 struct OverloadSet : Fct1, OverloadSet<Fcts...>
105 {
106  using Fct1::operator();
108 
109  OverloadSet(Fct1 f1, Fcts... fs)
110  : Fct1(f1), OverloadSet<Fcts...>(fs...)
111  {}
112 };
113 
115 template <typename Fct1>
116 struct OverloadSet<Fct1> : Fct1
117 {
118  using Fct1::operator();
119  OverloadSet(Fct1 f1) : Fct1(f1) {}
120 };
121 
137 template <typename... Fct>
138 auto make_overload_set(Fct... f)
139 {
140  return OverloadSet<Fct...>(f...);
141 }
142 
143 } // namespace gul14
144 
146 
147 namespace gul14 {
148 
149 #ifndef __has_attribute
150 #define __has_attribute(x) 0
151 #endif
152 
153 #ifndef __has_builtin
154 #define __has_builtin(x) 0
155 #endif
156 
157 #if __has_attribute(always_inline) || defined(__GNUC__)
158 #define GUL14_ALWAYS_INLINE __attribute__((__always_inline__)) inline
159 #elif defined(_MSC_VER)
160 #define GUL14_ALWAYS_INLINE __forceinline
161 #else
162 #define GUL14_ALWAYS_INLINE inline
163 #endif
164 
165 #if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
166 #define GUL14_BUILTIN_UNREACHABLE __builtin_unreachable()
167 #elif defined(_MSC_VER)
168 #define GUL14_BUILTIN_UNREACHABLE __assume(false)
169 #else
170 #define GUL14_BUILTIN_UNREACHABLE
171 #endif
172 
173 #define GUL14_RETURN(...) \
174  noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
175 
176 
177 namespace detail_variant {
178 
179 template <std::size_t I, typename T>
180 struct indexed_type : std::integral_constant<std::size_t, I> { using type = T; };
181 
182 template <typename T, std::size_t N>
183 struct array {
184  constexpr const T &operator[](std::size_t index) const { return data[index]; }
185  T data[N == 0 ? 1 : N];
186 };
187 
188 template <typename T, bool>
189 struct dependent_type : T {};
190 
191 template <typename Is, std::size_t J>
192 struct push_back;
193 
194 template <typename Is, std::size_t J>
195 using push_back_t = typename push_back<Is, J>::type;
196 
197 template <std::size_t... Is, std::size_t J>
198 struct push_back<std::index_sequence<Is...>, J> {
199  using type = std::index_sequence<Is..., J>;
200 };
201 
202 #if __has_builtin(__type_pack_element) && !(defined(__ICC))
203  template <std::size_t I, typename... Ts>
204  using type_pack_element_t = __type_pack_element<I, Ts...>;
205 #else
206  template <std::size_t I, typename... Ts>
207  struct type_pack_element_impl {
208  private:
209  template <typename>
210  struct set;
211 
212  template <std::size_t... Is>
213  struct set<std::index_sequence<Is...>> : indexed_type<Is, Ts>... {};
214 
215  template <typename T>
216  inline static std::enable_if<true, T> impl(indexed_type<I, T>);
217 
218  inline static std::enable_if<false> impl(...);
219 
220  public:
221  using type = decltype(impl(set<std::index_sequence_for<Ts...>>{}));
222  };
223 
224  template <std::size_t I, typename... Ts>
225  using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
226 
227  template <std::size_t I, typename... Ts>
228  using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
229 #endif
230 
231 template <typename T>
232 struct identity { using type = T; };
233 
234 template <bool... Bs>
235 using all = std::is_same<std::integer_sequence<bool, true, Bs...>,
236  std::integer_sequence<bool, Bs..., true>>;
237 
238 template <typename T>
239 struct is_reference_wrapper : std::false_type {};
240 
241 template <typename T>
242 struct is_reference_wrapper<std::reference_wrapper<T>>
243  : std::true_type {};
244 
245 
246 // invoke, invoke_result, invoke_result_t, is_invocable, is_invocable_r
247 
248 #if __cplusplus >= 201703L
249 
250 using std::invoke;
251 using std::invoke_result;
252 using std::invoke_result_t;
253 using std::is_invocable;
254 using std::is_invocable_r;
255 
256 #else
257 
258 namespace detail_invoke {
259 
260 template <bool, int>
261 struct Invoke;
262 
263 template <>
264 struct Invoke<true /* pmf */, 0 /* is_base_of */> {
265  template <typename R, typename T, typename Arg, typename... Args>
266  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
267  GUL14_RETURN((std::forward<Arg>(arg).*pmf)(std::forward<Args>(args)...))
268 };
269 
270 template <>
271 struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
272  template <typename R, typename T, typename Arg, typename... Args>
273  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
274  GUL14_RETURN((std::forward<Arg>(arg).get().*pmf)(std::forward<Args>(args)...))
275 };
276 
277 template <>
278 struct Invoke<true /* pmf */, 2 /* otherwise */> {
279  template <typename R, typename T, typename Arg, typename... Args>
280  inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
281  GUL14_RETURN(((*std::forward<Arg>(arg)).*pmf)(std::forward<Args>(args)...))
282 };
283 
284 template <>
285 struct Invoke<false /* pmo */, 0 /* is_base_of */> {
286  template <typename R, typename T, typename Arg>
287  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
288  GUL14_RETURN(std::forward<Arg>(arg).*pmo)
289 };
290 
291 template <>
292 struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
293  template <typename R, typename T, typename Arg>
294  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
295  GUL14_RETURN(std::forward<Arg>(arg).get().*pmo)
296 };
297 
298 template <>
299 struct Invoke<false /* pmo */, 2 /* otherwise */> {
300  template <typename R, typename T, typename Arg>
301  inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
302  GUL14_RETURN((*std::forward<Arg>(arg)).*pmo)
303 };
304 
305 template <typename R, typename T, typename Arg, typename... Args>
306 inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
307  GUL14_RETURN(
308  Invoke<std::is_function<R>::value,
309  (std::is_base_of<T, std::decay_t<Arg>>::value
310  ? 0
311  : is_reference_wrapper<std::decay_t<Arg>>::value
312  ? 1
313  : 2)>::invoke(f,
314  std::forward<Arg>(arg),
315  std::forward<Args>(args)...))
316 
317 #ifdef _MSC_VER
318 #pragma warning(push)
319 #pragma warning(disable : 4100)
320 #endif
321 template <typename F, typename... Args>
322 inline constexpr auto invoke(F &&f, Args &&... args)
323  GUL14_RETURN(std::forward<F>(f)(std::forward<Args>(args)...))
324 #ifdef _MSC_VER
325 #pragma warning(pop)
326 #endif
327 
328 } // namespace detail_invoke
329 
330 template <typename F, typename... Args>
331 inline constexpr auto invoke(F &&f, Args &&... args)
332 GUL14_RETURN(detail_invoke::invoke(std::forward<F>(f), std::forward<Args>(args)...))
333 
334 
335 namespace detail_invoke_result {
336 
337 template <typename Void, typename, typename...>
338 struct invoke_result {};
339 
340 template <typename F, typename... Args>
341 struct invoke_result<void_t<decltype(invoke(
342  std::declval<F>(), std::declval<Args>()...))>,
343  F,
344  Args...>
345  : identity<decltype(
346  invoke(std::declval<F>(), std::declval<Args>()...))> {};
347 
348 } // namespace detail_invoke_result
349 
350 template <typename F, typename... Args>
351 using invoke_result = detail_invoke_result::invoke_result<void, F, Args...>;
352 
353 template <typename F, typename... Args>
354 using invoke_result_t = typename invoke_result<F, Args...>::type;
355 
356 
357 namespace detail_invocable {
358 
359 template <typename Void, typename, typename...>
360 struct is_invocable : std::false_type {};
361 
362 template <typename F, typename... Args>
363 struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
364  : std::true_type {};
365 
366 template <typename Void, typename, typename, typename...>
367 struct is_invocable_r : std::false_type {};
368 
369 template <typename R, typename F, typename... Args>
370 struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
371  R,
372  F,
373  Args...>
374  : std::is_convertible<invoke_result_t<F, Args...>, R> {};
375 
376 } // namespace detail_invocable
377 
378 template <typename F, typename... Args>
379 using is_invocable = detail_invocable::is_invocable<void, F, Args...>;
380 
381 template <typename R, typename F, typename... Args>
382 using is_invocable_r = detail_invocable::is_invocable_r<void, R, F, Args...>;
383 
384 #endif // __cplusplus < 201703L
385 
386 
387 namespace detail_swappable {
388 
389 using std::swap;
390 
391 template <typename T>
392 struct is_swappable {
393 private:
394 template <typename U,
395  typename = decltype(swap(std::declval<U &>(),
396  std::declval<U &>()))>
397 inline static std::true_type test(int);
398 
399 template <typename U>
400 inline static std::false_type test(...);
401 
402 public:
403 static constexpr bool value = decltype(test<T>(0))::value;
404 };
405 
406 template <bool IsSwappable, typename T>
407 struct is_nothrow_swappable {
408 static constexpr bool value =
409  noexcept(swap(std::declval<T &>(), std::declval<T &>()));
410 };
411 
412 template <typename T>
413 struct is_nothrow_swappable<false, T> : std::false_type {};
414 
415 } // namespace detail_swappable
416 
417 using detail_swappable::is_swappable;
418 
419 template <typename T>
420 using is_nothrow_swappable =
421  detail_swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
422 
423 } // namespace detail_variant
424 
425 #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
426 
427 [[noreturn]] inline void throw_bad_variant_access() {
428  throw bad_variant_access{};
429 }
430 
431  template <typename T>
432  struct variant_size;
433 
434  template <typename T>
435  constexpr std::size_t variant_size_v = variant_size<T>::value;
436 
437  template <typename T>
438  struct variant_size<const T> : variant_size<T> {};
439 
440  template <typename T>
441  struct variant_size<volatile T> : variant_size<T> {};
442 
443  template <typename T>
444  struct variant_size<const volatile T> : variant_size<T> {};
445 
446  template <typename... Ts>
447  struct variant_size<variant<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {};
448 
449  template <std::size_t I, typename T>
450  struct variant_alternative;
451 
452  template <std::size_t I, typename T>
453  using variant_alternative_t = typename variant_alternative<I, T>::type;
454 
455  template <std::size_t I, typename T>
456  struct variant_alternative<I, const T>
457  : std::add_const<variant_alternative_t<I, T>> {};
458 
459  template <std::size_t I, typename T>
460  struct variant_alternative<I, volatile T>
461  : std::add_volatile<variant_alternative_t<I, T>> {};
462 
463  template <std::size_t I, typename T>
464  struct variant_alternative<I, const volatile T>
465  : std::add_cv<variant_alternative_t<I, T>> {};
466 
467  template <std::size_t I, typename... Ts>
468  struct variant_alternative<I, variant<Ts...>> {
469  static_assert(I < sizeof...(Ts),
470  "index out of bounds in `std::variant_alternative<>`");
471  using type = typename detail_variant::type_pack_element_t<I, Ts...>;
472  };
473 
474  constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
475 
476  namespace detail_variant {
477 
478  constexpr std::size_t not_found = static_cast<std::size_t>(-1);
479  constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);
480 
481  template <typename T, typename... Ts>
482  inline constexpr std::size_t find_index() {
483  constexpr detail_variant::array<bool, sizeof...(Ts)> matches = {
484  {std::is_same<T, Ts>::value...}
485  };
486  std::size_t result = not_found;
487  for (std::size_t i = 0; i < sizeof...(Ts); ++i) {
488  if (matches[i]) {
489  if (result != not_found) {
490  return ambiguous;
491  }
492  result = i;
493  }
494  }
495  return result;
496  }
497 
498  template <std::size_t I>
499  using find_index_sfinae_impl =
500  std::enable_if_t<I != not_found && I != ambiguous,
501  std::integral_constant<std::size_t, I>>;
502 
503  template <typename T, typename... Ts>
504  using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
505 
506  template <std::size_t I>
507  struct find_index_checked_impl : std::integral_constant<std::size_t, I> {
508  static_assert(I != not_found, "the specified type is not found.");
509  static_assert(I != ambiguous, "the specified type is ambiguous.");
510  };
511 
512  template <typename T, typename... Ts>
513  using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
514 
515  struct valueless_t {};
516 
517  enum class Trait { TriviallyAvailable, Available, Unavailable };
518 
519  template <typename T,
520  template <typename> class IsTriviallyAvailable,
521  template <typename> class IsAvailable>
522  inline constexpr Trait trait() {
523  return IsTriviallyAvailable<T>::value
524  ? Trait::TriviallyAvailable
525  : IsAvailable<T>::value ? Trait::Available
526  : Trait::Unavailable;
527  }
528 
529  template <typename... Traits>
530  inline constexpr Trait common_trait(Traits... traits_) {
531  Trait result = Trait::TriviallyAvailable;
532  detail_variant::array<Trait, sizeof...(Traits)> traits = {{traits_...}};
533  for (std::size_t i = 0; i < sizeof...(Traits); ++i) {
534  Trait t = traits[i];
535  if (static_cast<int>(t) > static_cast<int>(result)) {
536  result = t;
537  }
538  }
539  return result;
540  }
541 
542  template <typename... Ts>
543  struct traits {
544  static constexpr Trait copy_constructible_trait =
545  common_trait(trait<Ts,
546  std::is_trivially_copy_constructible,
547  std::is_copy_constructible>()...);
548 
549  static constexpr Trait move_constructible_trait =
550  common_trait(trait<Ts,
551  std::is_trivially_move_constructible,
552  std::is_move_constructible>()...);
553 
554  static constexpr Trait copy_assignable_trait =
555  common_trait(copy_constructible_trait,
556  trait<Ts,
557  std::is_trivially_copy_assignable,
558  std::is_copy_assignable>()...);
559 
560  static constexpr Trait move_assignable_trait =
561  common_trait(move_constructible_trait,
562  trait<Ts,
563  std::is_trivially_move_assignable,
564  std::is_move_assignable>()...);
565 
566  static constexpr Trait destructible_trait =
567  common_trait(trait<Ts,
568  std::is_trivially_destructible,
569  std::is_destructible>()...);
570  };
571 
572  namespace access {
573 
574  struct recursive_union {
575  template <typename V>
576  inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {
577  return std::forward<V>(v).head_;
578  }
579 
580  template <typename V, std::size_t I>
581  inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {
582  return get_alt(std::forward<V>(v).tail_, in_place_index_t<I - 1>{});
583  }
584  };
585 
586  struct base {
587  template <std::size_t I, typename V>
588  inline static constexpr auto&& get_alt(V &&v)
589 #ifdef _MSC_VER
590  AUTO_REFREF_RETURN(recursive_union::get_alt(
591  std::forward<V>(v).data_, in_place_index_t<I>{}))
592 #else
593  AUTO_REFREF_RETURN(recursive_union::get_alt(
594  data(std::forward<V>(v)), in_place_index_t<I>{}))
595 #endif
596  };
597 
598  struct variant {
599  template <std::size_t I, typename V>
600  inline static constexpr auto&& get_alt(V &&v)
601  AUTO_REFREF_RETURN(base::get_alt<I>(std::forward<V>(v).impl_))
602  };
603 
604  } // namespace access
605 
606  namespace visitation {
607 
608 #if !defined(_MSC_VER)
609 #define GUL14_VARIANT_SWITCH_VISIT
610 #endif
611 
612  struct base {
613  template <typename Visitor, typename... Vs>
614  using dispatch_result_t = decltype(
615  invoke(std::declval<Visitor>(),
616  access::base::get_alt<0>(std::declval<Vs>())...));
617 
618  template <typename Expected>
619  struct expected {
620  template <typename Actual>
621  inline static constexpr bool but_got() {
622  return std::is_same<Expected, Actual>::value;
623  }
624  };
625 
626  template <typename Expected, typename Actual>
627  struct visit_return_type_check {
628  static_assert(
629  expected<Expected>::template but_got<Actual>(),
630  "`visit` requires the visitor to have a single return type");
631 
632  template <typename Visitor, typename... Alts>
633  inline static constexpr decltype(auto)
634  invoke(Visitor &&visitor, Alts &&... alts)
635  {
636  return ::gul14::detail_variant::invoke(
637  std::forward<Visitor>(visitor), std::forward<Alts>(alts)...);
638  }
639  };
640 
641 #ifdef GUL14_VARIANT_SWITCH_VISIT
642  template <bool B, typename R, typename... ITs>
643  struct dispatcher;
644 
645  template <typename R, typename... ITs>
646  struct dispatcher<false, R, ITs...> {
647  template <std::size_t B, typename F, typename... Vs>
648  GUL14_ALWAYS_INLINE static constexpr R dispatch(
649  F &&, typename ITs::type &&..., Vs &&...) {
650  GUL14_BUILTIN_UNREACHABLE;
651  }
652 
653  template <std::size_t I, typename F, typename... Vs>
654  GUL14_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) {
655  GUL14_BUILTIN_UNREACHABLE;
656  }
657 
658  template <std::size_t B, typename F, typename... Vs>
659  GUL14_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t,
660  F &&,
661  Vs &&...) {
662  GUL14_BUILTIN_UNREACHABLE;
663  }
664  };
665 
666  template <typename R, typename... ITs>
667  struct dispatcher<true, R, ITs...> {
668  template <std::size_t B, typename F>
669  GUL14_ALWAYS_INLINE static constexpr R dispatch(
670  F &&f, typename ITs::type &&... visited_vs) {
671  using Expected = R;
672  using Actual = decltype(invoke(
673  std::forward<F>(f),
674  access::base::get_alt<ITs::value>(
675  std::forward<typename ITs::type>(visited_vs))...));
676  return visit_return_type_check<Expected, Actual>::invoke(
677  std::forward<F>(f),
678  access::base::get_alt<ITs::value>(
679  std::forward<typename ITs::type>(visited_vs))...);
680  }
681 
682  template <std::size_t B, typename F, typename V, typename... Vs>
683  GUL14_ALWAYS_INLINE static constexpr R dispatch(
684  F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
685 #define GUL14_DISPATCH(I) \
686  dispatcher<(I < std::decay_t<V>::size()), \
687  R, \
688  ITs..., \
689  detail_variant::indexed_type<I, V>>:: \
690  template dispatch<0>(std::forward<F>(f), \
691  std::forward<typename ITs::type>(visited_vs)..., \
692  std::forward<V>(v), \
693  std::forward<Vs>(vs)...)
694 
695 #define GUL14_DEFAULT(I) \
696  dispatcher<(I < std::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
697  std::forward<F>(f), \
698  std::forward<typename ITs::type>(visited_vs)..., \
699  std::forward<V>(v), \
700  std::forward<Vs>(vs)...)
701 
702  switch (v.index()) {
703  case B + 0: return GUL14_DISPATCH(B + 0);
704  case B + 1: return GUL14_DISPATCH(B + 1);
705  case B + 2: return GUL14_DISPATCH(B + 2);
706  case B + 3: return GUL14_DISPATCH(B + 3);
707  case B + 4: return GUL14_DISPATCH(B + 4);
708  case B + 5: return GUL14_DISPATCH(B + 5);
709  case B + 6: return GUL14_DISPATCH(B + 6);
710  case B + 7: return GUL14_DISPATCH(B + 7);
711  case B + 8: return GUL14_DISPATCH(B + 8);
712  case B + 9: return GUL14_DISPATCH(B + 9);
713  case B + 10: return GUL14_DISPATCH(B + 10);
714  case B + 11: return GUL14_DISPATCH(B + 11);
715  case B + 12: return GUL14_DISPATCH(B + 12);
716  case B + 13: return GUL14_DISPATCH(B + 13);
717  case B + 14: return GUL14_DISPATCH(B + 14);
718  case B + 15: return GUL14_DISPATCH(B + 15);
719  case B + 16: return GUL14_DISPATCH(B + 16);
720  case B + 17: return GUL14_DISPATCH(B + 17);
721  case B + 18: return GUL14_DISPATCH(B + 18);
722  case B + 19: return GUL14_DISPATCH(B + 19);
723  case B + 20: return GUL14_DISPATCH(B + 20);
724  case B + 21: return GUL14_DISPATCH(B + 21);
725  case B + 22: return GUL14_DISPATCH(B + 22);
726  case B + 23: return GUL14_DISPATCH(B + 23);
727  case B + 24: return GUL14_DISPATCH(B + 24);
728  case B + 25: return GUL14_DISPATCH(B + 25);
729  case B + 26: return GUL14_DISPATCH(B + 26);
730  case B + 27: return GUL14_DISPATCH(B + 27);
731  case B + 28: return GUL14_DISPATCH(B + 28);
732  case B + 29: return GUL14_DISPATCH(B + 29);
733  case B + 30: return GUL14_DISPATCH(B + 30);
734  case B + 31: return GUL14_DISPATCH(B + 31);
735  default: return GUL14_DEFAULT(B + 32);
736  }
737 
738 #undef GUL14_DEFAULT
739 #undef GUL14_DISPATCH
740  }
741 
742  template <std::size_t I, typename F, typename... Vs>
743  GUL14_ALWAYS_INLINE static constexpr R dispatch_case(F &&f,
744  Vs &&... vs) {
745  using Expected = R;
746  using Actual = decltype(
747  invoke(std::forward<F>(f),
748  access::base::get_alt<I>(std::forward<Vs>(vs))...));
749  return visit_return_type_check<Expected, Actual>::invoke(
750  std::forward<F>(f),
751  access::base::get_alt<I>(std::forward<Vs>(vs))...);
752  }
753 
754  template <std::size_t B, typename F, typename V, typename... Vs>
755  GUL14_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index,
756  F &&f,
757  V &&v,
758  Vs &&... vs) {
759  static_assert(detail_variant::all<(std::decay_t<V>::size() ==
760  std::decay_t<Vs>::size())...>::value,
761  "all of the variants must be the same size.");
762 #define GUL14_DISPATCH_AT(I) \
763  dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_case<I>( \
764  std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
765 
766 #define GUL14_DEFAULT(I) \
767  dispatcher<(I < std::decay_t<V>::size()), R>::template dispatch_at<I>( \
768  index, std::forward<F>(f), std::forward<V>(v), std::forward<Vs>(vs)...)
769 
770  switch (index) {
771  case B + 0: return GUL14_DISPATCH_AT(B + 0);
772  case B + 1: return GUL14_DISPATCH_AT(B + 1);
773  case B + 2: return GUL14_DISPATCH_AT(B + 2);
774  case B + 3: return GUL14_DISPATCH_AT(B + 3);
775  case B + 4: return GUL14_DISPATCH_AT(B + 4);
776  case B + 5: return GUL14_DISPATCH_AT(B + 5);
777  case B + 6: return GUL14_DISPATCH_AT(B + 6);
778  case B + 7: return GUL14_DISPATCH_AT(B + 7);
779  case B + 8: return GUL14_DISPATCH_AT(B + 8);
780  case B + 9: return GUL14_DISPATCH_AT(B + 9);
781  case B + 10: return GUL14_DISPATCH_AT(B + 10);
782  case B + 11: return GUL14_DISPATCH_AT(B + 11);
783  case B + 12: return GUL14_DISPATCH_AT(B + 12);
784  case B + 13: return GUL14_DISPATCH_AT(B + 13);
785  case B + 14: return GUL14_DISPATCH_AT(B + 14);
786  case B + 15: return GUL14_DISPATCH_AT(B + 15);
787  case B + 16: return GUL14_DISPATCH_AT(B + 16);
788  case B + 17: return GUL14_DISPATCH_AT(B + 17);
789  case B + 18: return GUL14_DISPATCH_AT(B + 18);
790  case B + 19: return GUL14_DISPATCH_AT(B + 19);
791  case B + 20: return GUL14_DISPATCH_AT(B + 20);
792  case B + 21: return GUL14_DISPATCH_AT(B + 21);
793  case B + 22: return GUL14_DISPATCH_AT(B + 22);
794  case B + 23: return GUL14_DISPATCH_AT(B + 23);
795  case B + 24: return GUL14_DISPATCH_AT(B + 24);
796  case B + 25: return GUL14_DISPATCH_AT(B + 25);
797  case B + 26: return GUL14_DISPATCH_AT(B + 26);
798  case B + 27: return GUL14_DISPATCH_AT(B + 27);
799  case B + 28: return GUL14_DISPATCH_AT(B + 28);
800  case B + 29: return GUL14_DISPATCH_AT(B + 29);
801  case B + 30: return GUL14_DISPATCH_AT(B + 30);
802  case B + 31: return GUL14_DISPATCH_AT(B + 31);
803  default: return GUL14_DEFAULT(B + 32);
804  }
805 
806 #undef GUL14_DEFAULT
807 #undef GUL14_DISPATCH_AT
808  }
809  };
810 #else
811  template <typename T>
812  inline static constexpr const T &at(const T &elem) noexcept {
813  return elem;
814  }
815 
816  template <typename T, std::size_t N, typename... Is>
817  inline static constexpr const std::remove_all_extents_t<T> &at(
818  const detail_variant::array<T, N> &elems, std::size_t i, Is... is) noexcept {
819  return at(elems[i], is...);
820  }
821 
822  template <typename F, typename... Fs>
823  inline static constexpr detail_variant::array<std::decay_t<F>, sizeof...(Fs) + 1>
824  make_farray(F &&f, Fs &&... fs) {
825  return {{std::forward<F>(f), std::forward<Fs>(fs)...}};
826  }
827 
828  template <typename F, typename... Vs>
829  struct make_fmatrix_impl {
830 
831  template <std::size_t... Is>
832  inline static constexpr dispatch_result_t<F, Vs...> dispatch(
833  F &&f, Vs &&... vs) {
834  using Expected = dispatch_result_t<F, Vs...>;
835  using Actual = decltype(invoke(
836  std::forward<F>(f),
837  access::base::get_alt<Is>(std::forward<Vs>(vs))...));
838  return visit_return_type_check<Expected, Actual>::invoke(
839  std::forward<F>(f),
840  access::base::get_alt<Is>(std::forward<Vs>(vs))...);
841  }
842 
843  template <std::size_t... Is>
844  inline static constexpr auto impl(std::index_sequence<Is...>) {
845  return &dispatch<Is...>;
846  }
847 
848  template <typename Is, std::size_t... Js, typename... Ls>
849  inline static constexpr auto impl(Is,
850  std::index_sequence<Js...>,
851  Ls... ls) {
852  return make_farray(impl(detail_variant::push_back_t<Is, Js>{}, ls...)...);
853  }
854  };
855 
856  template <typename F, typename... Vs>
857  inline static constexpr auto make_fmatrix() {
858  return make_fmatrix_impl<F, Vs...>::impl(
859  std::index_sequence<>{},
860  std::make_index_sequence<std::decay_t<Vs>::size()>{}...);
861  }
862 
863  template <typename F, typename... Vs>
864  struct make_fdiagonal_impl {
865  template <std::size_t I>
866  inline static constexpr dispatch_result_t<F, Vs...> dispatch(
867  F &&f, Vs &&... vs) {
868  using Expected = dispatch_result_t<F, Vs...>;
869  using Actual = decltype(
870  invoke(std::forward<F>(f),
871  access::base::get_alt<I>(std::forward<Vs>(vs))...));
872  return visit_return_type_check<Expected, Actual>::invoke(
873  std::forward<F>(f),
874  access::base::get_alt<I>(std::forward<Vs>(vs))...);
875  }
876 
877  template <std::size_t... Is>
878  inline static constexpr auto impl(std::index_sequence<Is...>) {
879  return make_farray(&dispatch<Is>...);
880  }
881  };
882 
883  template <typename F, typename V, typename... Vs>
884  inline static constexpr auto make_fdiagonal()
885  -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(
886  std::make_index_sequence<std::decay_t<V>::size()>{})) {
887  static_assert(detail_variant::all<(std::decay_t<V>::size() ==
888  std::decay_t<Vs>::size())...>::value,
889  "all of the variants must be the same size.");
890  return make_fdiagonal_impl<F, V, Vs...>::impl(
891  std::make_index_sequence<std::decay_t<V>::size()>{});
892  }
893 #endif
894  };
895 
896 #if !defined(GUL14_VARIANT_SWITCH_VISIT) && \
897  (!defined(_MSC_VER) || _MSC_VER >= 1910)
898  template <typename F, typename... Vs>
899  using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
900 
901  template <typename F, typename... Vs>
902  struct fmatrix {
903  static constexpr fmatrix_t<F, Vs...> value =
904  base::make_fmatrix<F, Vs...>();
905  };
906 
907  template <typename F, typename... Vs>
908  constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;
909 
910  template <typename F, typename... Vs>
911  using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
912 
913  template <typename F, typename... Vs>
914  struct fdiagonal {
915  static constexpr fdiagonal_t<F, Vs...> value =
916  base::make_fdiagonal<F, Vs...>();
917  };
918 
919  template <typename F, typename... Vs>
920  constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;
921 #endif
922 
923  struct alt {
924  template <typename Visitor, typename... Vs>
925  inline static constexpr decltype(auto) visit_alt(Visitor &&visitor,
926  Vs &&... vs)
927 #ifdef GUL14_VARIANT_SWITCH_VISIT
928  {
929  return base::dispatcher<
930  true,
931  base::dispatch_result_t<Visitor,
932  decltype(as_base(
933  std::forward<Vs>(vs)))...>>::
934  template dispatch<0>(std::forward<Visitor>(visitor),
935  as_base(std::forward<Vs>(vs))...);
936  }
937 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
938  {
939  return base::at(
940  fmatrix<Visitor &&,
941  decltype(as_base(std::forward<Vs>(vs)))...>::value,
942  vs.index()...)(std::forward<Visitor>(visitor),
943  as_base(std::forward<Vs>(vs))...);
944  }
945 #else
946  {
947  return base::at(
948  base::make_fmatrix<Visitor &&,
949  decltype(as_base(std::forward<Vs>(vs)))...>(),
950  vs.index()...)(std::forward<Visitor>(visitor),
951  as_base(std::forward<Vs>(vs))...);
952  }
953 #endif
954 
955  template <typename Visitor, typename... Vs>
956  inline static constexpr decltype(auto) visit_alt_at(std::size_t index,
957  Visitor &&visitor,
958  Vs &&... vs)
959 #ifdef GUL14_VARIANT_SWITCH_VISIT
960  {
961  return base::dispatcher<
962  true,
963  base::dispatch_result_t<Visitor,
964  decltype(as_base(
965  std::forward<Vs>(vs)))...>>::
966  template dispatch_at<0>(index,
967  std::forward<Visitor>(visitor),
968  as_base(std::forward<Vs>(vs))...);
969  }
970 #elif !defined(_MSC_VER) || _MSC_VER >= 1910
971  {
972  return base::at(
973  fdiagonal<Visitor &&,
974  decltype(as_base(std::forward<Vs>(vs)))...>::value,
975  index)(std::forward<Visitor>(visitor),
976  as_base(std::forward<Vs>(vs))...);
977  }
978 #else
979  {
980  return base::at(
981  base::make_fdiagonal<Visitor &&,
982  decltype(as_base(std::forward<Vs>(vs)))...>(),
983  index)(std::forward<Visitor>(visitor),
984  as_base(std::forward<Vs>(vs))...);
985  }
986 #endif
987  };
988 
989  struct variant {
990  private:
991  template <typename Visitor>
992  struct visitor {
993  template <typename... Values>
994  inline static constexpr bool does_not_handle() {
995  return detail_variant::is_invocable<Visitor, Values...>::value;
996  }
997  };
998 
999  template <typename Visitor, typename... Values>
1000  struct visit_exhaustiveness_check {
1001  static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
1002  "`visit` requires the visitor to be exhaustive.");
1003 
1004  inline static constexpr decltype(auto)
1005  invoke(Visitor &&visitor, Values &&... values)
1006  {
1007  return detail_variant::invoke(std::forward<Visitor>(visitor),
1008  std::forward<Values>(values)...);
1009  }
1010  };
1011 
1012  template <typename Visitor>
1013  struct value_visitor {
1014  Visitor &&visitor_;
1015 
1016  template <typename... Alts>
1017  inline constexpr decltype(auto) operator()(Alts &&... alts) const
1018  {
1019  return visit_exhaustiveness_check<
1020  Visitor,
1021  decltype((std::forward<Alts>(alts).value))...>::
1022  invoke(std::forward<Visitor>(visitor_),
1023  std::forward<Alts>(alts).value...);
1024  }
1025  };
1026 
1027  template <typename Visitor>
1028  inline static constexpr auto make_value_visitor(Visitor &&visitor) {
1029  return value_visitor<Visitor>{std::forward<Visitor>(visitor)};
1030  }
1031 
1032  public:
1033  template <typename Visitor, typename... Vs>
1034  inline static constexpr decltype(auto) visit_alt(Visitor &&visitor, Vs &&... vs)
1035  {
1036  return alt::visit_alt(std::forward<Visitor>(visitor),
1037  std::forward<Vs>(vs).impl_...);
1038  }
1039 
1040  template <typename Visitor, typename... Vs>
1041  inline static constexpr decltype(auto) visit_alt_at(std::size_t index,
1042  Visitor &&visitor,
1043  Vs &&... vs)
1044  {
1045  return alt::visit_alt_at(index, std::forward<Visitor>(visitor),
1046  std::forward<Vs>(vs).impl_...);
1047  }
1048 
1049  template <typename Visitor, typename... Vs>
1050  inline static constexpr decltype(auto) visit_value(Visitor &&visitor,
1051  Vs &&... vs)
1052  {
1053  return visit_alt(make_value_visitor(std::forward<Visitor>(visitor)),
1054  std::forward<Vs>(vs)...);
1055  }
1056 
1057  template <typename Visitor, typename... Vs>
1058  inline static constexpr decltype(auto) visit_value_at(std::size_t index,
1059  Visitor &&visitor,
1060  Vs &&... vs)
1061  {
1062  return visit_alt_at(index, make_value_visitor(std::forward<Visitor>(visitor)),
1063  std::forward<Vs>(vs)...);
1064  }
1065  };
1066 
1067  } // namespace visitation
1068 
1069  template <std::size_t Index, typename T>
1070  struct alt {
1071  using value_type = T;
1072 
1073 #ifdef _MSC_VER
1074 #pragma warning(push)
1075 #pragma warning(disable : 4244)
1076 #endif
1077  template <typename... Args>
1078  inline explicit constexpr alt(in_place_t, Args &&... args)
1079  : value(std::forward<Args>(args)...) {}
1080 #ifdef _MSC_VER
1081 #pragma warning(pop)
1082 #endif
1083 
1084  T value;
1085  };
1086 
1087  template <Trait DestructibleTrait, std::size_t Index, typename... Ts>
1088  union recursive_union;
1089 
1090  template <Trait DestructibleTrait, std::size_t Index>
1091  union recursive_union<DestructibleTrait, Index> {};
1092 
1093 #define GUL14_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
1094  template <std::size_t Index, typename T, typename... Ts> \
1095  union recursive_union<destructible_trait, Index, T, Ts...> { \
1096  public: \
1097  inline explicit constexpr recursive_union(valueless_t) noexcept \
1098  : dummy_{} {} \
1099  \
1100  template <typename... Args> \
1101  inline explicit constexpr recursive_union(in_place_index_t<0>, \
1102  Args &&... args) \
1103  : head_(in_place_t{}, std::forward<Args>(args)...) {} \
1104  \
1105  template <std::size_t I, typename... Args> \
1106  inline explicit constexpr recursive_union(in_place_index_t<I>, \
1107  Args &&... args) \
1108  : tail_(in_place_index_t<I - 1>{}, std::forward<Args>(args)...) {} \
1109  \
1110  recursive_union(const recursive_union &) = default; \
1111  recursive_union(recursive_union &&) = default; \
1112  \
1113  destructor \
1114  \
1115  recursive_union &operator=(const recursive_union &) = default; \
1116  recursive_union &operator=(recursive_union &&) = default; \
1117  \
1118  private: \
1119  char dummy_; \
1120  alt<Index, T> head_; \
1121  recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
1122  \
1123  friend struct access::recursive_union; \
1124  }
1125 
1126  GUL14_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
1127  ~recursive_union() = default;);
1128  GUL14_VARIANT_RECURSIVE_UNION(Trait::Available,
1129  ~recursive_union() {});
1130  GUL14_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
1131  ~recursive_union() = delete;);
1132 
1133 #undef GUL14_VARIANT_RECURSIVE_UNION
1134 
1135  template <typename... Ts>
1136  using index_t = typename std::conditional<
1137  sizeof...(Ts) < (std::numeric_limits<unsigned char>::max)(),
1138  unsigned char,
1139  typename std::conditional<
1140  sizeof...(Ts) < (std::numeric_limits<unsigned short>::max)(),
1141  unsigned short,
1142  unsigned int>::type
1143  >::type;
1144 
1145  template <Trait DestructibleTrait, typename... Ts>
1146  class base {
1147  public:
1148  inline explicit constexpr base(valueless_t tag) noexcept
1149  : data_(tag), index_(static_cast<index_t<Ts...>>(-1)) {}
1150 
1151  template <std::size_t I, typename... Args>
1152  inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
1153  : data_(in_place_index_t<I>{}, std::forward<Args>(args)...),
1154  index_(I) {}
1155 
1156  inline constexpr bool valueless_by_exception() const noexcept {
1157  return index_ == static_cast<index_t<Ts...>>(-1);
1158  }
1159 
1160  inline constexpr std::size_t index() const noexcept {
1161  return valueless_by_exception() ? variant_npos : index_;
1162  }
1163 
1164  protected:
1165  using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
1166 
1167  friend inline constexpr base &as_base(base &b) { return b; }
1168  friend inline constexpr const base &as_base(const base &b) { return b; }
1169  friend inline constexpr base &&as_base(base &&b) { return std::move(b); }
1170  friend inline constexpr const base &&as_base(const base &&b) { return std::move(b); }
1171 
1172  friend inline constexpr data_t &data(base &b) { return b.data_; }
1173  friend inline constexpr const data_t &data(const base &b) { return b.data_; }
1174  friend inline constexpr data_t &&data(base &&b) { return std::move(b).data_; }
1175  friend inline constexpr const data_t &&data(const base &&b) { return std::move(b).data_; }
1176 
1177  inline static constexpr std::size_t size() { return sizeof...(Ts); }
1178 
1179  data_t data_;
1180  index_t<Ts...> index_;
1181 
1182  friend struct access::base;
1183  friend struct visitation::base;
1184  };
1185 
1186  struct dtor {
1187 #ifdef _MSC_VER
1188 #pragma warning(push)
1189 #pragma warning(disable : 4100)
1190 #endif
1191  template <typename Alt>
1192  inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }
1193 #ifdef _MSC_VER
1194 #pragma warning(pop)
1195 #endif
1196  };
1197 
1198 #if !defined(_MSC_VER) || _MSC_VER >= 1910
1199 #define GUL14_INHERITING_CTOR(type, base) using base::base;
1200 #else
1201 #define GUL14_INHERITING_CTOR(type, base) \
1202  template <typename... Args> \
1203  inline explicit constexpr type(Args &&... args) \
1204  : base(std::forward<Args>(args)...) {}
1205 #endif
1206 
1207  template <typename Traits, Trait = Traits::destructible_trait>
1208  class destructor;
1209 
1210 #define GUL14_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
1211  template <typename... Ts> \
1212  class destructor<traits<Ts...>, destructible_trait> \
1213  : public base<destructible_trait, Ts...> { \
1214  using super = base<destructible_trait, Ts...>; \
1215  \
1216  public: \
1217  GUL14_INHERITING_CTOR(destructor, super) \
1218  using super::operator=; \
1219  \
1220  destructor(const destructor &) = default; \
1221  destructor(destructor &&) = default; \
1222  definition \
1223  destructor &operator=(const destructor &) = default; \
1224  destructor &operator=(destructor &&) = default; \
1225  \
1226  protected: \
1227  destroy \
1228  }
1229 
1230  GUL14_VARIANT_DESTRUCTOR(
1231  Trait::TriviallyAvailable,
1232  ~destructor() = default;,
1233  inline void destroy() noexcept {
1234  this->index_ = static_cast<index_t<Ts...>>(-1);
1235  });
1236 
1237  GUL14_VARIANT_DESTRUCTOR(
1238  Trait::Available,
1239  ~destructor() { destroy(); },
1240  inline void destroy() noexcept {
1241  if (!this->valueless_by_exception()) {
1242  visitation::alt::visit_alt(dtor{}, *this);
1243  }
1244  this->index_ = static_cast<index_t<Ts...>>(-1);
1245  });
1246 
1247  GUL14_VARIANT_DESTRUCTOR(
1248  Trait::Unavailable,
1249  ~destructor() = delete;,
1250  inline void destroy() noexcept = delete;);
1251 
1252 #undef GUL14_VARIANT_DESTRUCTOR
1253 
1254  template <typename Traits>
1255  class constructor : public destructor<Traits> {
1256  using super = destructor<Traits>;
1257 
1258  public:
1259  GUL14_INHERITING_CTOR(constructor, super)
1260  using super::operator=;
1261 
1262  protected:
1263  template <std::size_t I, typename T, typename... Args>
1264  inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
1265  auto *result = ::new (static_cast<void *>(std::addressof(a)))
1266  alt<I, T>(in_place_t{}, std::forward<Args>(args)...);
1267  return result->value;
1268  }
1269 
1270  template <typename Rhs>
1271  inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
1272  lhs.destroy();
1273  if (!rhs.valueless_by_exception()) {
1274  visitation::alt::visit_alt_at(
1275  rhs.index(),
1276  [](auto &lhs_alt, auto &&rhs_alt) {
1277  constructor::construct_alt(
1278  lhs_alt, std::forward<decltype(rhs_alt)>(rhs_alt).value);
1279  }
1280  ,
1281  lhs,
1282  std::forward<Rhs>(rhs));
1283  lhs.index_ = rhs.index_;
1284  }
1285  }
1286  };
1287 
1288  template <typename Traits, Trait = Traits::move_constructible_trait>
1289  class move_constructor;
1290 
1291 #define GUL14_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
1292  template <typename... Ts> \
1293  class move_constructor<traits<Ts...>, move_constructible_trait> \
1294  : public constructor<traits<Ts...>> { \
1295  using super = constructor<traits<Ts...>>; \
1296  \
1297  public: \
1298  GUL14_INHERITING_CTOR(move_constructor, super) \
1299  using super::operator=; \
1300  \
1301  move_constructor(const move_constructor &) = default; \
1302  definition \
1303  ~move_constructor() = default; \
1304  move_constructor &operator=(const move_constructor &) = default; \
1305  move_constructor &operator=(move_constructor &&) = default; \
1306  }
1307 
1308  GUL14_VARIANT_MOVE_CONSTRUCTOR(
1309  Trait::TriviallyAvailable,
1310  move_constructor(move_constructor &&that) = default;);
1311 
1312  GUL14_VARIANT_MOVE_CONSTRUCTOR(
1313  Trait::Available,
1314  move_constructor(move_constructor &&that) noexcept(
1315  detail_variant::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
1316  : move_constructor(valueless_t{}) {
1317  this->generic_construct(*this, std::move(that));
1318  });
1319 
1320  GUL14_VARIANT_MOVE_CONSTRUCTOR(
1321  Trait::Unavailable,
1322  move_constructor(move_constructor &&) = delete;);
1323 
1324 #undef GUL14_VARIANT_MOVE_CONSTRUCTOR
1325 
1326  template <typename Traits, Trait = Traits::copy_constructible_trait>
1327  class copy_constructor;
1328 
1329 #define GUL14_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
1330  template <typename... Ts> \
1331  class copy_constructor<traits<Ts...>, copy_constructible_trait> \
1332  : public move_constructor<traits<Ts...>> { \
1333  using super = move_constructor<traits<Ts...>>; \
1334  \
1335  public: \
1336  GUL14_INHERITING_CTOR(copy_constructor, super) \
1337  using super::operator=; \
1338  \
1339  definition \
1340  copy_constructor(copy_constructor &&) = default; \
1341  ~copy_constructor() = default; \
1342  copy_constructor &operator=(const copy_constructor &) = default; \
1343  copy_constructor &operator=(copy_constructor &&) = default; \
1344  }
1345 
1346  GUL14_VARIANT_COPY_CONSTRUCTOR(
1347  Trait::TriviallyAvailable,
1348  copy_constructor(const copy_constructor &that) = default;);
1349 
1350  GUL14_VARIANT_COPY_CONSTRUCTOR(
1351  Trait::Available,
1352  copy_constructor(const copy_constructor &that)
1353  : copy_constructor(valueless_t{}) {
1354  this->generic_construct(*this, that);
1355  });
1356 
1357  GUL14_VARIANT_COPY_CONSTRUCTOR(
1358  Trait::Unavailable,
1359  copy_constructor(const copy_constructor &) = delete;);
1360 
1361 #undef GUL14_VARIANT_COPY_CONSTRUCTOR
1362 
1363  template <typename Traits>
1364  class assignment : public copy_constructor<Traits> {
1365  using super = copy_constructor<Traits>;
1366 
1367  public:
1368  GUL14_INHERITING_CTOR(assignment, super)
1369  using super::operator=;
1370 
1371  template <std::size_t I, typename... Args>
1372  inline /* auto & */ auto emplace(Args &&... args)
1373  -> decltype(this->construct_alt(access::base::get_alt<I>(*this),
1374  std::forward<Args>(args)...)) {
1375  this->destroy();
1376  auto &result = this->construct_alt(access::base::get_alt<I>(*this),
1377  std::forward<Args>(args)...);
1378  this->index_ = I;
1379  return result;
1380  }
1381 
1382  protected:
1383  template <std::size_t I, typename T, typename Arg>
1384  inline void assign_alt(alt<I, T> &a, Arg &&arg) {
1385  if (this->index() == I) {
1386 #ifdef _MSC_VER
1387 #pragma warning(push)
1388 #pragma warning(disable : 4244)
1389 #endif
1390  a.value = std::forward<Arg>(arg);
1391 #ifdef _MSC_VER
1392 #pragma warning(pop)
1393 #endif
1394  } else {
1395  struct {
1396  void operator()(std::true_type) const {
1397  this_->emplace<I>(std::forward<Arg>(arg_));
1398  }
1399  void operator()(std::false_type) const {
1400  this_->emplace<I>(T(std::forward<Arg>(arg_)));
1401  }
1402  assignment *this_;
1403  Arg &&arg_;
1404  } impl{this, std::forward<Arg>(arg)};
1405  impl(std::integral_constant<bool,
1406  std::is_nothrow_constructible<T, Arg>::value ||
1407  !std::is_nothrow_move_constructible<T>::value>{});
1408  }
1409  }
1410 
1411  template <typename That>
1412  inline void generic_assign(That &&that) {
1413  if (this->valueless_by_exception() && that.valueless_by_exception()) {
1414  // do nothing.
1415  } else if (that.valueless_by_exception()) {
1416  this->destroy();
1417  } else {
1418  visitation::alt::visit_alt_at(
1419  that.index(),
1420  [this](auto &this_alt, auto &&that_alt) {
1421  this->assign_alt(
1422  this_alt, std::forward<decltype(that_alt)>(that_alt).value);
1423  },
1424  *this,
1425  std::forward<That>(that));
1426  }
1427  }
1428  };
1429 
1430  template <typename Traits, Trait = Traits::move_assignable_trait>
1431  class move_assignment;
1432 
1433 #define GUL14_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
1434  template <typename... Ts> \
1435  class move_assignment<traits<Ts...>, move_assignable_trait> \
1436  : public assignment<traits<Ts...>> { \
1437  using super = assignment<traits<Ts...>>; \
1438  \
1439  public: \
1440  GUL14_INHERITING_CTOR(move_assignment, super) \
1441  using super::operator=; \
1442  \
1443  move_assignment(const move_assignment &) = default; \
1444  move_assignment(move_assignment &&) = default; \
1445  ~move_assignment() = default; \
1446  move_assignment &operator=(const move_assignment &) = default; \
1447  definition \
1448  }
1449 
1450  GUL14_VARIANT_MOVE_ASSIGNMENT(
1451  Trait::TriviallyAvailable,
1452  move_assignment &operator=(move_assignment &&that) = default;);
1453 
1454  GUL14_VARIANT_MOVE_ASSIGNMENT(
1455  Trait::Available,
1456  move_assignment &
1457  operator=(move_assignment &&that) noexcept(
1458  detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1459  std::is_nothrow_move_assignable<Ts>::value)...>::value) {
1460  this->generic_assign(std::move(that));
1461  return *this;
1462  });
1463 
1464  GUL14_VARIANT_MOVE_ASSIGNMENT(
1465  Trait::Unavailable,
1466  move_assignment &operator=(move_assignment &&) = delete;);
1467 
1468 #undef GUL14_VARIANT_MOVE_ASSIGNMENT
1469 
1470  template <typename Traits, Trait = Traits::copy_assignable_trait>
1471  class copy_assignment;
1472 
1473 #define GUL14_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
1474  template <typename... Ts> \
1475  class copy_assignment<traits<Ts...>, copy_assignable_trait> \
1476  : public move_assignment<traits<Ts...>> { \
1477  using super = move_assignment<traits<Ts...>>; \
1478  \
1479  public: \
1480  GUL14_INHERITING_CTOR(copy_assignment, super) \
1481  using super::operator=; \
1482  \
1483  copy_assignment(const copy_assignment &) = default; \
1484  copy_assignment(copy_assignment &&) = default; \
1485  ~copy_assignment() = default; \
1486  definition \
1487  copy_assignment &operator=(copy_assignment &&) = default; \
1488  }
1489 
1490  GUL14_VARIANT_COPY_ASSIGNMENT(
1491  Trait::TriviallyAvailable,
1492  copy_assignment &operator=(const copy_assignment &that) = default;);
1493 
1494  GUL14_VARIANT_COPY_ASSIGNMENT(
1495  Trait::Available,
1496  copy_assignment &operator=(const copy_assignment &that) {
1497  this->generic_assign(that);
1498  return *this;
1499  });
1500 
1501  GUL14_VARIANT_COPY_ASSIGNMENT(
1502  Trait::Unavailable,
1503  copy_assignment &operator=(const copy_assignment &) = delete;);
1504 
1505 #undef GUL14_VARIANT_COPY_ASSIGNMENT
1506 
1507  template <typename... Ts>
1508  class impl : public copy_assignment<traits<Ts...>> {
1509  using super = copy_assignment<traits<Ts...>>;
1510 
1511  public:
1512  GUL14_INHERITING_CTOR(impl, super)
1513  using super::operator=;
1514 
1515  impl(const impl&) = default;
1516  impl(impl&&) = default;
1517  ~impl() = default;
1518  impl &operator=(const impl &) = default;
1519  impl &operator=(impl &&) = default;
1520 
1521  template <std::size_t I, typename Arg>
1522  inline void assign(Arg &&arg) {
1523  this->assign_alt(access::base::get_alt<I>(*this),
1524  std::forward<Arg>(arg));
1525  }
1526 
1527  inline void swap(impl &that) {
1528  if (this->valueless_by_exception() && that.valueless_by_exception()) {
1529  // do nothing.
1530  } else if (this->index() == that.index()) {
1531  visitation::alt::visit_alt_at(this->index(),
1532  [](auto &this_alt, auto &that_alt) {
1533  using std::swap;
1534  swap(this_alt.value,
1535  that_alt.value);
1536  },
1537  *this,
1538  that);
1539  } else {
1540  impl *lhs = this;
1541  impl *rhs = std::addressof(that);
1542  if (lhs->move_nothrow() && !rhs->move_nothrow()) {
1543  std::swap(lhs, rhs);
1544  }
1545  impl tmp(std::move(*rhs));
1546  // EXTENSION: When the move construction of `lhs` into `rhs` throws
1547  // and `tmp` is nothrow move constructible then we move `tmp` back
1548  // into `rhs` and provide the strong exception safety guarantee.
1549  try {
1550  this->generic_construct(*rhs, std::move(*lhs));
1551  } catch (...) {
1552  if (tmp.move_nothrow()) {
1553  this->generic_construct(*rhs, std::move(tmp));
1554  }
1555  throw;
1556  }
1557  this->generic_construct(*lhs, std::move(tmp));
1558  }
1559  }
1560 
1561  private:
1562  inline constexpr bool move_nothrow() const {
1563  return this->valueless_by_exception() ||
1564  detail_variant::array<bool, sizeof...(Ts)>{
1565  {std::is_nothrow_move_constructible<Ts>::value...}
1566  }[this->index()];
1567  }
1568  };
1569 
1570 #undef GUL14_INHERITING_CTOR
1571 
1572  template <typename From, typename To>
1573  struct is_non_narrowing_convertible {
1574  template <typename T>
1575  static std::true_type test(T(&&)[1]);
1576 
1577  template <typename T>
1578  static auto impl(int) -> decltype(test<T>({std::declval<From>()}));
1579 
1580  template <typename>
1581  static auto impl(...) -> std::false_type;
1582 
1583  static constexpr bool value = decltype(impl<To>(0))::value;
1584  };
1585 
1586  template <typename Arg,
1587  std::size_t I,
1588  typename T,
1589  bool = std::is_arithmetic<T>::value,
1590  typename = void>
1591  struct overload_leaf {};
1592 
1593  template <typename Arg, std::size_t I, typename T>
1594  struct overload_leaf<Arg, I, T, false> {
1595  using impl = std::integral_constant<std::size_t, I> (*)(T);
1596  operator impl() const { return nullptr; };
1597  };
1598 
1599  template <typename Arg, std::size_t I, typename T>
1600  struct overload_leaf<
1601  Arg,
1602  I,
1603  T,
1604  true
1605 #if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
1606  ,
1607  std::enable_if_t<
1608  std::is_same<remove_cvref_t<T>, bool>::value
1609  ? std::is_same<remove_cvref_t<Arg>, bool>::value
1610  : is_non_narrowing_convertible<Arg, T>::value>
1611 #endif
1612  > {
1613  using impl = std::integral_constant<std::size_t, I> (*)(T);
1614  operator impl() const { return nullptr; };
1615  };
1616 
1617  template <typename Arg, typename... Ts>
1618  struct overload_impl {
1619  private:
1620  template <typename>
1621  struct impl;
1622 
1623  template <std::size_t... Is>
1624  struct impl<std::index_sequence<Is...>> : overload_leaf<Arg, Is, Ts>... {};
1625 
1626  public:
1627  using type = impl<std::index_sequence_for<Ts...>>;
1628  };
1629 
1630  template <typename Arg, typename... Ts>
1631  using overload = typename overload_impl<Arg, Ts...>::type;
1632 
1633  template <typename Arg, typename... Ts>
1634  using best_match = invoke_result_t<overload<Arg, Ts...>, Arg>;
1635 
1636  template <typename T>
1637  struct is_in_place_index : std::false_type {};
1638 
1639  template <std::size_t I>
1640  struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
1641 
1642  template <typename T>
1643  struct is_in_place_type : std::false_type {};
1644 
1645  template <typename T>
1646  struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
1647 
1648  } // detail_variant
1649 
1650  template <typename... Ts>
1651  class variant {
1652  static_assert(0 < sizeof...(Ts),
1653  "variant must consist of at least one alternative.");
1654 
1655  static_assert(detail_variant::all<!std::is_array<Ts>::value...>::value,
1656  "variant can not have an array type as an alternative.");
1657 
1658  static_assert(detail_variant::all<!std::is_reference<Ts>::value...>::value,
1659  "variant can not have a reference type as an alternative.");
1660 
1661  static_assert(detail_variant::all<!std::is_void<Ts>::value...>::value,
1662  "variant can not have a void type as an alternative.");
1663 
1664  public:
1665  template <
1666  typename Front = detail_variant::type_pack_element_t<0, Ts...>,
1667  std::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>
1668  inline constexpr variant() noexcept(
1669  std::is_nothrow_default_constructible<Front>::value)
1670  : impl_(in_place_index_t<0>{}) {}
1671 
1672  variant(const variant &) = default;
1673  variant(variant &&) = default;
1674 
1675  template <
1676  typename Arg,
1677  typename Decayed = std::decay_t<Arg>,
1678  std::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,
1679  std::enable_if_t<!detail_variant::is_in_place_index<Decayed>::value, int> = 0,
1680  std::enable_if_t<!detail_variant::is_in_place_type<Decayed>::value, int> = 0,
1681  std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1682  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1683  std::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>
1684  inline constexpr variant(Arg &&arg) noexcept(
1685  std::is_nothrow_constructible<T, Arg>::value)
1686  : impl_(in_place_index_t<I>{}, std::forward<Arg>(arg)) {}
1687 
1688  template <
1689  std::size_t I,
1690  typename... Args,
1691  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1692  std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
1693  inline explicit constexpr variant(
1694  in_place_index_t<I>,
1695  Args &&... args) noexcept(std::is_nothrow_constructible<T,
1696  Args...>::value)
1697  : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1698 
1699  template <
1700  std::size_t I,
1701  typename Up,
1702  typename... Args,
1703  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1704  std::enable_if_t<std::is_constructible<T,
1705  std::initializer_list<Up> &,
1706  Args...>::value,
1707  int> = 0>
1708  inline explicit constexpr variant(
1709  in_place_index_t<I>,
1710  std::initializer_list<Up> il,
1711  Args &&... args) noexcept(std::
1712  is_nothrow_constructible<
1713  T,
1714  std::initializer_list<Up> &,
1715  Args...>::value)
1716  : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1717 
1718  template <
1719  typename T,
1720  typename... Args,
1721  std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1722  std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
1723  inline explicit constexpr variant(
1724  in_place_type_t<T>,
1725  Args &&... args) noexcept(std::is_nothrow_constructible<T,
1726  Args...>::value)
1727  : impl_(in_place_index_t<I>{}, std::forward<Args>(args)...) {}
1728 
1729  template <
1730  typename T,
1731  typename Up,
1732  typename... Args,
1733  std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1734  std::enable_if_t<std::is_constructible<T,
1735  std::initializer_list<Up> &,
1736  Args...>::value,
1737  int> = 0>
1738  inline explicit constexpr variant(
1739  in_place_type_t<T>,
1740  std::initializer_list<Up> il,
1741  Args &&... args) noexcept(std::
1742  is_nothrow_constructible<
1743  T,
1744  std::initializer_list<Up> &,
1745  Args...>::value)
1746  : impl_(in_place_index_t<I>{}, il, std::forward<Args>(args)...) {}
1747 
1748  ~variant() = default;
1749 
1750  variant &operator=(const variant &) = default;
1751  variant &operator=(variant &&) = default;
1752 
1753  template <typename Arg,
1754  std::enable_if_t<!std::is_same<std::decay_t<Arg>, variant>::value,
1755  int> = 0,
1756  std::size_t I = detail_variant::best_match<Arg, Ts...>::value,
1757  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1758  std::enable_if_t<(std::is_assignable<T &, Arg>::value &&
1759  std::is_constructible<T, Arg>::value),
1760  int> = 0>
1761  inline variant &operator=(Arg &&arg) noexcept(
1762  (std::is_nothrow_assignable<T &, Arg>::value &&
1763  std::is_nothrow_constructible<T, Arg>::value)) {
1764  impl_.template assign<I>(std::forward<Arg>(arg));
1765  return *this;
1766  }
1767 
1768  template <
1769  std::size_t I,
1770  typename... Args,
1771  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1772  std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
1773  inline T &emplace(Args &&... args) {
1774  return impl_.template emplace<I>(std::forward<Args>(args)...);
1775  }
1776 
1777  template <
1778  std::size_t I,
1779  typename Up,
1780  typename... Args,
1781  typename T = detail_variant::type_pack_element_t<I, Ts...>,
1782  std::enable_if_t<std::is_constructible<T,
1783  std::initializer_list<Up> &,
1784  Args...>::value,
1785  int> = 0>
1786  inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1787  return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1788  }
1789 
1790  template <
1791  typename T,
1792  typename... Args,
1793  std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1794  std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
1795  inline T &emplace(Args &&... args) {
1796  return impl_.template emplace<I>(std::forward<Args>(args)...);
1797  }
1798 
1799  template <
1800  typename T,
1801  typename Up,
1802  typename... Args,
1803  std::size_t I = detail_variant::find_index_sfinae<T, Ts...>::value,
1804  std::enable_if_t<std::is_constructible<T,
1805  std::initializer_list<Up> &,
1806  Args...>::value,
1807  int> = 0>
1808  inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
1809  return impl_.template emplace<I>(il, std::forward<Args>(args)...);
1810  }
1811 
1812  inline constexpr bool valueless_by_exception() const noexcept {
1813  return impl_.valueless_by_exception();
1814  }
1815 
1816  inline constexpr std::size_t index() const noexcept {
1817  return impl_.index();
1818  }
1819 
1820  template <bool Dummy = true,
1821  std::enable_if_t<
1822  detail_variant::all<Dummy,
1823  (detail_variant::dependent_type<std::is_move_constructible<Ts>,
1824  Dummy>::value &&
1825  detail_variant::dependent_type<detail_variant::is_swappable<Ts>,
1826  Dummy>::value)...>::value,
1827  int> = 0>
1828  inline void swap(variant &that) noexcept(
1829  detail_variant::all<(std::is_nothrow_move_constructible<Ts>::value &&
1830  detail_variant::is_nothrow_swappable<Ts>::value)...>::value) {
1831  impl_.swap(that.impl_);
1832  }
1833 
1834  private:
1835  detail_variant::impl<Ts...> impl_;
1836 
1837  friend struct detail_variant::access::variant;
1838  friend struct detail_variant::visitation::variant;
1839  };
1840 
1841  template <std::size_t I, typename... Ts>
1842  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
1843  return v.index() == I;
1844  }
1845 
1846  template <typename T, typename... Ts>
1847  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
1848  return holds_alternative<detail_variant::find_index_checked<T, Ts...>::value>(v);
1849  }
1850 
1851  namespace detail_variant {
1852  template <std::size_t I, typename V>
1853  struct generic_get_impl {
1854  constexpr generic_get_impl(int) noexcept {}
1855 
1856  constexpr auto&& operator()(V &&v) const
1857  AUTO_REFREF_RETURN(
1858  access::variant::get_alt<I>(std::forward<V>(v)).value)
1859  };
1860 
1861  template <std::size_t I, typename V>
1862  inline constexpr auto&& generic_get(V &&v)
1863  AUTO_REFREF_RETURN(generic_get_impl<I, V>(
1864  holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
1865  std::forward<V>(v)))
1866  } // namespace detail_variant
1867 
1868  template <std::size_t I, typename... Ts>
1869  inline constexpr variant_alternative_t<I, variant<Ts...>> &get(
1870  variant<Ts...> &v) {
1871  return detail_variant::generic_get<I>(v);
1872  }
1873 
1874  template <std::size_t I, typename... Ts>
1875  inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(
1876  variant<Ts...> &&v) {
1877  return detail_variant::generic_get<I>(std::move(v));
1878  }
1879 
1880  template <std::size_t I, typename... Ts>
1881  inline constexpr const variant_alternative_t<I, variant<Ts...>> &get(
1882  const variant<Ts...> &v) {
1883  return detail_variant::generic_get<I>(v);
1884  }
1885 
1886  template <std::size_t I, typename... Ts>
1887  inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get(
1888  const variant<Ts...> &&v) {
1889  return detail_variant::generic_get<I>(std::move(v));
1890  }
1891 
1892  template <typename T, typename... Ts>
1893  inline constexpr T &get(variant<Ts...> &v) {
1894  return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1895  }
1896 
1897  template <typename T, typename... Ts>
1898  inline constexpr T &&get(variant<Ts...> &&v) {
1899  return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1900  }
1901 
1902  template <typename T, typename... Ts>
1903  inline constexpr const T &get(const variant<Ts...> &v) {
1904  return get<detail_variant::find_index_checked<T, Ts...>::value>(v);
1905  }
1906 
1907  template <typename T, typename... Ts>
1908  inline constexpr const T &&get(const variant<Ts...> &&v) {
1909  return get<detail_variant::find_index_checked<T, Ts...>::value>(std::move(v));
1910  }
1911 
1912  namespace detail_variant {
1913 
1914  template <std::size_t I, typename V>
1915  inline constexpr auto* generic_get_if(V* v) noexcept {
1916  return v && holds_alternative<I>(*v)
1917  ? std::addressof(access::variant::get_alt<I>(*v).value)
1918  : nullptr;
1919  }
1920 
1921  } // namespace detail_variant
1922 
1923  template <std::size_t I, typename... Ts>
1924  inline constexpr std::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
1925  get_if(variant<Ts...> *v) noexcept {
1926  return detail_variant::generic_get_if<I>(v);
1927  }
1928 
1929  template <std::size_t I, typename... Ts>
1930  inline constexpr std::add_pointer_t<
1931  const variant_alternative_t<I, variant<Ts...>>>
1932  get_if(const variant<Ts...> *v) noexcept {
1933  return detail_variant::generic_get_if<I>(v);
1934  }
1935 
1936  template <typename T, typename... Ts>
1937  inline constexpr std::add_pointer_t<T>
1938  get_if(variant<Ts...> *v) noexcept {
1939  return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1940  }
1941 
1942  template <typename T, typename... Ts>
1943  inline constexpr std::add_pointer_t<const T>
1944  get_if(const variant<Ts...> *v) noexcept {
1945  return get_if<detail_variant::find_index_checked<T, Ts...>::value>(v);
1946  }
1947 
1948  namespace detail_variant {
1949  template <typename RelOp>
1950  struct convert_to_bool {
1951  template <typename Lhs, typename Rhs>
1952  inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const {
1953  static_assert(std::is_convertible<invoke_result_t<RelOp, Lhs, Rhs>,
1954  bool>::value,
1955  "relational operators must return a type"
1956  " implicitly convertible to bool");
1957  return invoke(
1958  RelOp{}, std::forward<Lhs>(lhs), std::forward<Rhs>(rhs));
1959  }
1960  };
1961  } // namespace detail_variant
1962 
1963  template <typename... Ts>
1964  inline constexpr bool operator==(const variant<Ts...> &lhs,
1965  const variant<Ts...> &rhs) {
1966  using detail_variant::visitation::variant;
1967  using equal_to = detail_variant::convert_to_bool<std::equal_to<>>;
1968  if (lhs.index() != rhs.index()) return false;
1969  if (lhs.valueless_by_exception()) return true;
1970  return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
1971  }
1972 
1973  template <typename... Ts>
1974  inline constexpr bool operator!=(const variant<Ts...> &lhs,
1975  const variant<Ts...> &rhs) {
1976  using detail_variant::visitation::variant;
1977  using not_equal_to = detail_variant::convert_to_bool<std::not_equal_to<>>;
1978  if (lhs.index() != rhs.index()) return true;
1979  if (lhs.valueless_by_exception()) return false;
1980  return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
1981  }
1982 
1983  template <typename... Ts>
1984  inline constexpr bool operator<(const variant<Ts...> &lhs,
1985  const variant<Ts...> &rhs) {
1986  using detail_variant::visitation::variant;
1987  using less = detail_variant::convert_to_bool<std::less<>>;
1988  if (rhs.valueless_by_exception()) return false;
1989  if (lhs.valueless_by_exception()) return true;
1990  if (lhs.index() < rhs.index()) return true;
1991  if (lhs.index() > rhs.index()) return false;
1992  return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
1993  }
1994 
1995  template <typename... Ts>
1996  inline constexpr bool operator>(const variant<Ts...> &lhs,
1997  const variant<Ts...> &rhs) {
1998  using detail_variant::visitation::variant;
1999  using greater = detail_variant::convert_to_bool<std::greater<>>;
2000  if (lhs.valueless_by_exception()) return false;
2001  if (rhs.valueless_by_exception()) return true;
2002  if (lhs.index() > rhs.index()) return true;
2003  if (lhs.index() < rhs.index()) return false;
2004  return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
2005  }
2006 
2007  template <typename... Ts>
2008  inline constexpr bool operator<=(const variant<Ts...> &lhs,
2009  const variant<Ts...> &rhs) {
2010  using detail_variant::visitation::variant;
2011  using less_equal = detail_variant::convert_to_bool<std::less_equal<>>;
2012  if (lhs.valueless_by_exception()) return true;
2013  if (rhs.valueless_by_exception()) return false;
2014  if (lhs.index() < rhs.index()) return true;
2015  if (lhs.index() > rhs.index()) return false;
2016  return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
2017  }
2018 
2019  template <typename... Ts>
2020  inline constexpr bool operator>=(const variant<Ts...> &lhs,
2021  const variant<Ts...> &rhs) {
2022  using detail_variant::visitation::variant;
2023  using greater_equal = detail_variant::convert_to_bool<std::greater_equal<>>;
2024  if (rhs.valueless_by_exception()) return true;
2025  if (lhs.valueless_by_exception()) return false;
2026  if (lhs.index() > rhs.index()) return true;
2027  if (lhs.index() < rhs.index()) return false;
2028  return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
2029  }
2030 
2031  namespace detail_variant {
2032 
2033  inline constexpr bool any(std::initializer_list<bool> bs) {
2034  for (bool b : bs) {
2035  if (b) {
2036  return true;
2037  }
2038  }
2039  return false;
2040  }
2041 
2042  } // namespace detail_variant
2043 
2044  template <typename Visitor, typename... Vs>
2045  inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
2046  return (!detail_variant::any({vs.valueless_by_exception()...})
2047  ? (void)0
2048  : throw_bad_variant_access()),
2049  detail_variant::visitation::variant::visit_value(
2050  std::forward<Visitor>(visitor), std::forward<Vs>(vs)...);
2051  }
2052 
2053  template <typename... Ts>
2054  inline auto swap(variant<Ts...> &lhs,
2055  variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
2056  -> decltype(lhs.swap(rhs)) {
2057  lhs.swap(rhs);
2058  }
2059 
2060  namespace detail_variant {
2061 
2062  template <typename T, typename...>
2063  using enabled_type = T;
2064 
2065  namespace hash {
2066 
2067  template <typename H, typename K>
2068  constexpr bool meets_requirements() noexcept {
2069  return std::is_copy_constructible<H>::value &&
2070  std::is_move_constructible<H>::value &&
2071  detail_variant::is_invocable_r<std::size_t, H, const K &>::value;
2072  }
2073 
2074  template <typename K>
2075  constexpr bool is_enabled() noexcept {
2076  using H = std::hash<K>;
2077  return meets_requirements<H, K>() &&
2078  std::is_default_constructible<H>::value &&
2079  std::is_copy_assignable<H>::value &&
2080  std::is_move_assignable<H>::value;
2081  }
2082 
2083  } // namespace hash
2084 
2085  } // namespace detail_variant
2086 
2087 #undef AUTO_REFREF_RETURN
2088 #undef GUL14_RETURN
2089 
2090 } // namespace gul14
2091 
2092 namespace std {
2093 
2094 template <typename... Ts>
2095 struct hash<gul14::detail_variant::enabled_type<
2096  gul14::variant<Ts...>,
2097  std::enable_if_t<gul14::detail_variant::all<gul14::detail_variant::hash::is_enabled<
2098  std::remove_const_t<Ts>>()...>::value>>> {
2099  using argument_type = gul14::variant<Ts...>;
2100  using result_type = std::size_t;
2101 
2102  inline result_type operator()(const argument_type &v) const {
2103  using gul14::detail_variant::visitation::variant;
2104  std::size_t result =
2105  v.valueless_by_exception()
2106  ? 299792458 // Random value chosen by the universe upon creation
2107  : variant::visit_alt(
2108  [](const auto &alt) {
2109  using alt_type = std::decay_t<decltype(alt)>;
2110  using value_type = std::remove_const_t<
2111  typename alt_type::value_type>;
2112  return hash<value_type>{}(alt.value);
2113  },
2114  v);
2115  return hash_combine(result, hash<std::size_t>{}(v.index()));
2116  }
2117 
2118  private:
2119  static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
2120  return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
2121  }
2122 };
2123 
2125 
2126 } // namespace std
2127 
2129 
2130 #endif
The exception thrown if the wrong type is accessed on a gul14::variant.
Definition: variant.h:49
A "type-safe union".
Definition: variant.h:71
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition: SmallVector.h:1656
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
void void_t
A type mapping an arbitrary list of types to void (for SFINAE).
Definition: traits.h:98
constexpr decltype(auto) visit(Visitor &&visitor_fct, Variants &&... variants)
Call a visitor function with the actual objects stored in the given variants.
auto make_overload_set(Fct... f)
Create an OverloadSet from an arbitrary number of function objects.
Definition: variant.h:138
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
A function object that works like an overload set of functions.
Definition: variant.h:105
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.