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