AWS IoT Device SDK C++ v2  1.41.0
AWS IoT Device SDK C++ v2
Variant.h
Go to the documentation of this file.
1 #pragma once
2 
7 #include <aws/common/assert.h>
8 #include <aws/crt/TypeTraits.h>
9 #include <aws/crt/Utility.h>
10 
11 #include <algorithm>
12 #include <type_traits>
13 #include <utility>
14 
15 namespace Aws
16 {
17  namespace Crt
18  {
19  namespace VariantDetail
20  {
21  template <typename T> constexpr const T &ConstExprMax(const T &a, const T &b)
22  {
23  return (a < b) ? b : a;
24  }
25 
26  namespace ParameterPackSize
27  {
28  // Returns a max of sizeof(T) over all T in a template parameter pack
29  template <typename Last> constexpr std::size_t GetMaxSizeOf(std::size_t curMax = 0)
30  {
31  return ConstExprMax(curMax, sizeof(Last));
32  }
33 
34  template <typename First, typename Second, typename... Rest>
35  constexpr std::size_t GetMaxSizeOf(std::size_t curMax = 0)
36  {
37  return ConstExprMax(curMax, GetMaxSizeOf<Second, Rest...>(ConstExprMax(curMax, sizeof(First))));
38  }
39 
40  // some old gcc versions does not work with alignas(Ts..)
41  template <typename Last> constexpr std::size_t AlignAsPack(std::size_t curMax = 0)
42  {
43  return ConstExprMax(curMax, alignof(Last));
44  }
45 
46  template <typename First, typename Second, typename... Rest>
47  constexpr std::size_t AlignAsPack(std::size_t curMax = 0)
48  {
49  return ConstExprMax(curMax, AlignAsPack<Second, Rest...>(ConstExprMax(curMax, alignof(First))));
50  }
51  } // namespace ParameterPackSize
52 
53  namespace Index
54  {
55  using VariantIndex = short;
56 
57  template <typename T, typename Last> constexpr VariantIndex GetIndexOf(VariantIndex curIndex = 0)
58  {
59  return std::is_same<T, Last>::value ? curIndex : -1;
60  }
61 
62  template <typename T, typename First, typename Second, typename... Rest>
63  constexpr VariantIndex GetIndexOf(VariantIndex curIndex = 0)
64  {
65  return std::is_same<T, First>::value ? curIndex : GetIndexOf<T, Second, Rest...>(++curIndex);
66  }
67  } // namespace Index
68 
69  namespace Checker
70  {
71  // Returns True if the template parameter pack Ts has a type T, i.e. ContainsType<T, Ts>() == true if T
72  // is in the list of Ts
73  template <typename T, typename Last> constexpr bool ContainsType()
74  {
75  return std::is_same<T, Last>::value;
76  }
77 
78  template <typename T, typename First, typename Second, typename... Rest> constexpr bool ContainsType()
79  {
80  return std::is_same<T, First>::value || ContainsType<T, Second, Rest...>();
81  }
82 
83  // a case when the template parameter pack is empty (i.e. VariantImpl<>)
84  template <typename T> constexpr bool ContainsType()
85  {
86  return false;
87  }
88 
89  template <typename T, typename... Ts> struct HasType
90  {
91  static const bool value = ContainsType<T, Ts...>();
92  };
93  } // namespace Checker
94 #if defined(AWS_CRT_ENABLE_VARIANT_DEBUG)
95  namespace VariantDebug
96  {
97  template <typename... Ts> class VariantDebugBrowser
98  {
99  public:
100  VariantDebugBrowser(char *storage) { InitTuple<0, Ts...>(storage); }
101  std::tuple<typename std::add_pointer<Ts>::type...> as_tuple;
102 
103  private:
104  template <IndexT Index, typename First, typename Second, typename... Rest>
105  void InitTuple(char *storage)
106  {
107  First *value = reinterpret_cast<First *>(storage);
108  std::get<Index>(as_tuple) = value;
109  InitTuple<Index + 1, Second, Rest...>(storage);
110  }
111 
112  template <IndexT Index, typename Last> void InitTuple(char *storage)
113  {
114  Last *value = reinterpret_cast<Last *>(storage);
115  std::get<Index>(as_tuple) = value;
116  }
117  };
118  } // namespace VariantDebug
119 #endif /* defined(AWS_CRT_ENABLE_VARIANT_DEBUG) */
120 
121  /* Depending on the Variant types, this struct either deletes special move members or defaults them. */
122  template <bool> class MovableVariant;
123 
124  template <> class MovableVariant<true>
125  {
126  public:
127  MovableVariant() = default;
128  MovableVariant(const MovableVariant &) = default;
130  MovableVariant(MovableVariant &&other) = default;
132  };
133  template <> class MovableVariant<false>
134  {
135  public:
136  MovableVariant() = default;
137  MovableVariant(const MovableVariant &) = default;
141  };
142 
143  /* Depending on the Variant types, this struct either deletes special copy members or defaults them. */
144  template <bool> class CopyableVariant;
145 
146  template <> class CopyableVariant<true>
147  {
148  public:
149  CopyableVariant() = default;
150  CopyableVariant(const CopyableVariant &other) = default;
151  CopyableVariant &operator=(const CopyableVariant &other) = default;
154  };
155 
156  template <> class CopyableVariant<false>
157  {
158  public:
159  CopyableVariant() = default;
160 
161  CopyableVariant(const CopyableVariant &) = delete;
163 
166  };
167 
168  template <std::size_t Index, typename... Ts> class VariantAlternative;
169 
170  template <typename... Ts> class VariantImpl
171  {
172  private:
173  template <std::size_t Index> using ThisVariantAlternative = VariantAlternative<Index, Ts...>;
174 
175  template <typename OtherT>
176  using EnableIfOtherIsThisVariantAlternative = typename std::enable_if<
178  int>::type;
179 
180  public:
182 
184  std::is_nothrow_default_constructible<FirstAlternative>::value;
185 
187  std::is_nothrow_constructible<FirstAlternative>::value;
188 
190  static constexpr std::size_t AlternativeCount = sizeof...(Ts);
191 
193  {
194  new (m_storage) FirstAlternative();
195  m_index = 0;
196  }
197 
198  VariantImpl(const VariantImpl &other)
199  {
200  AWS_FATAL_ASSERT(other.m_index != -1);
201  m_index = other.m_index;
202  VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveConstructor());
203  }
204 
206  {
207  AWS_FATAL_ASSERT(other.m_index != -1);
208  m_index = other.m_index;
209  VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveConstructor());
210  }
211 
212  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
213  VariantImpl(const T &val) noexcept(
214  std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
215  {
216  static_assert(
217  VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
218  "This variant does not have such alternative T.");
219  static_assert(
220  sizeof(T) <= STORAGE_SIZE,
221  "Attempting to instantiate a Variant with a type bigger than all alternatives.");
222 
223  using PlainT = typename std::decay<T>::type;
224  new (m_storage) PlainT(val);
225  m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>();
226  AWS_ASSERT(m_index != -1);
227  }
228 
229  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
230  VariantImpl(T &&val) noexcept(
231  std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
232  {
233  static_assert(
234  VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
235  "This variant does not have such alternative T.");
236  static_assert(
237  sizeof(T) <= STORAGE_SIZE,
238  "Attempting to instantiate a Variant with a type bigger than all alternatives.");
239 
240  using PlainT = typename std::decay<T>::type;
241  new (m_storage) PlainT(std::forward<T>(val));
242  m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>();
243  AWS_ASSERT(m_index != -1);
244  }
245 
246  // An overload to initialize with an Alternative T in-place
247  template <typename T, typename... Args> explicit VariantImpl(Aws::Crt::InPlaceTypeT<T>, Args &&...args)
248  {
249  static_assert(
250  VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
251  "This variant does not have such alternative T.");
252  static_assert(
253  sizeof(T) <= STORAGE_SIZE,
254  "Attempting to instantiate a Variant with a type bigger than all alternatives.");
255 
256  using PlainT = typename std::decay<T>::type;
257  new (m_storage) PlainT(std::forward<Args>(args)...);
258  m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>();
259  AWS_ASSERT(m_index != -1);
260  }
261 
263  {
264  if (this != &other)
265  {
266  AWS_FATAL_ASSERT(other.m_index != -1);
267  if (m_index != other.m_index)
268  {
269  Destroy();
270  m_index = other.m_index;
271  VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveConstructor());
272  }
273  else
274  {
275  VisitorUtil<0, Ts...>::VisitBinary(this, other, CopyMoveAssigner());
276  }
277  }
278  return *this;
279  }
280 
282  {
283  if (this != &other)
284  {
285  AWS_FATAL_ASSERT(other.m_index != -1);
286  if (m_index != other.m_index)
287  {
288  Destroy();
289  m_index = other.m_index;
290  VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveConstructor());
291  }
292  else
293  {
294  VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveAssigner());
295  }
296  }
297  return *this;
298  }
299 
300  /* emplace */
301  template <typename T, typename... Args, EnableIfOtherIsThisVariantAlternative<T> = 1>
302  T &emplace(Args &&...args)
303  {
304  static_assert(
305  VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
306  "This variant does not have such alternative T.");
307  static_assert(
308  sizeof(T) <= STORAGE_SIZE,
309  "Attempting to instantiate a Variant with a type bigger than all alternatives.");
310 
311  Destroy();
312 
313  using PlainT = typename std::decay<T>::type;
314  new (m_storage) PlainT(std::forward<Args>(args)...);
315  m_index = VariantDetail::Index::GetIndexOf<PlainT, Ts...>();
316  AWS_ASSERT(m_index != -1);
317 
318  T *value = reinterpret_cast<T *>(m_storage);
319  return *value;
320  }
321 
322  template <std::size_t Index, typename... Args>
323  auto emplace(Args &&...args) -> typename ThisVariantAlternative<Index>::type &
324  {
325  static_assert(Index < AlternativeCount, "Unknown alternative index to emplace");
326  using AlternativeT = typename ThisVariantAlternative<Index>::type;
327 
328  return emplace<AlternativeT, Args...>(std::forward<Args>(args)...);
329  }
330 
331  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> bool holds_alternative() const
332  {
333  AWS_ASSERT(m_index != -1);
334  return m_index == VariantDetail::Index::GetIndexOf<T, Ts...>();
335  }
336 
337  /* non-const get */
338  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T &get()
339  {
340  AWS_FATAL_ASSERT(holds_alternative<T>());
341  T *value = reinterpret_cast<T *>(m_storage);
342  return *value;
343  }
344 
345  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T *get_if()
346  {
347  if (holds_alternative<T>())
348  {
349  T *value = reinterpret_cast<T *>(m_storage);
350  return value;
351  }
352  else
353  {
354  return nullptr;
355  }
356  }
357 
358  template <std::size_t Index> auto get() -> typename ThisVariantAlternative<Index>::type &
359  {
360  static_assert(Index < AlternativeCount, "Unknown alternative index to get");
361  AWS_FATAL_ASSERT(holds_alternative<Index>());
362  using AlternativeT = typename ThisVariantAlternative<Index>::type;
363  AlternativeT *ret = reinterpret_cast<AlternativeT *>(m_storage);
364  return *ret;
365  }
366 
367  /* const get */
368  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T &get() const
369  {
370  AWS_FATAL_ASSERT(holds_alternative<T>());
371  const T *value = reinterpret_cast<const T *>(m_storage);
372  return *value;
373  }
374 
375  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T *get_if() const
376  {
377  if (holds_alternative<T>())
378  {
379  T *value = reinterpret_cast<T *>(m_storage);
380  return value;
381  }
382  else
383  {
384  return nullptr;
385  }
386  }
387 
388  template <std::size_t Index> auto get() const -> const typename ThisVariantAlternative<Index>::type &
389  {
390  static_assert(Index < AlternativeCount, "Unknown alternative index to get");
391  AWS_ASSERT(Index == m_index);
392  using AlternativeT = typename ThisVariantAlternative<Index>::type;
393  const AlternativeT *ret = reinterpret_cast<const AlternativeT *>(m_storage);
394  return *ret;
395  }
396 
397  /* This is just a templated way to say
398  * "int*" for
399  * a VariantAlternative<0, VariantImpl<int, char, long>()>*/
400  template <std::size_t Index>
402  typename std::add_pointer<typename ThisVariantAlternative<Index>::type>::type;
403 
404  template <std::size_t Index> auto get_if() -> RawAlternativePointerT<Index>
405  {
406  static_assert(Index < AlternativeCount, "Unknown alternative index to get");
407  if (holds_alternative<Index>())
408  {
409  using AlternativePtrT = RawAlternativePointerT<Index>;
410  AlternativePtrT value = reinterpret_cast<AlternativePtrT>(m_storage);
411  return value;
412  }
413  else
414  {
415  return nullptr;
416  }
417  }
418 
419  template <std::size_t Index>
420  using ConstRawAlternativePointerT = typename std::add_pointer<
421  typename std::add_const<typename ThisVariantAlternative<Index>::type>::type>::type;
422 
423  template <std::size_t Index> auto get_if() const -> ConstRawAlternativePointerT<Index>
424  {
425  static_assert(Index < AlternativeCount, "Unknown alternative index to get");
426  if (holds_alternative<Index>())
427  {
428  using AlternativePtrT = ConstRawAlternativePointerT<Index>;
429  AlternativePtrT value = reinterpret_cast<AlternativePtrT>(m_storage);
430  return value;
431  }
432  else
433  {
434  return nullptr;
435  }
436  }
437 
438  std::size_t index() const { return m_index; }
439 
440  ~VariantImpl() { Destroy(); }
441 
442  template <typename VisitorT> void Visit(VisitorT &&visitor)
443  {
444  return VisitorUtil<0, Ts...>::Visit(this, std::forward<VisitorT>(visitor));
445  }
446 
447  private:
448  static constexpr std::size_t STORAGE_SIZE = VariantDetail::ParameterPackSize::GetMaxSizeOf<Ts...>();
449 
450  alignas(VariantDetail::ParameterPackSize::AlignAsPack<Ts...>()) char m_storage[STORAGE_SIZE];
451  IndexT m_index = -1;
452 #if defined(AWS_CRT_ENABLE_VARIANT_DEBUG)
453  VariantDetail::VariantDebug::VariantDebugBrowser<Ts...> browser = m_storage;
454 #endif /* defined(AWS_CRT_ENABLE_VARIANT_DEBUG) */
455 
456  template <size_t Index> constexpr bool holds_alternative() const { return Index == m_index; }
457 
458  struct Destroyer
459  {
460  template <typename AlternativeT> void operator()(AlternativeT &&value) const
461  {
462  (void)value;
463  using PlaintT = typename std::remove_reference<AlternativeT>::type;
464  value.~PlaintT();
465  }
466  };
467 
468  void Destroy()
469  {
470  AWS_FATAL_ASSERT(m_index != -1);
471  Visit(Destroyer());
472 
473  m_index = -1;
474  }
475 
476  struct CopyMoveConstructor
477  {
478  template <typename AlternativeT> void operator()(AlternativeT &&value, AlternativeT &&other) const
479  {
480  using PlaintT = typename std::remove_reference<AlternativeT>::type;
481  new (&value) PlaintT(std::move<AlternativeT>(other));
482  }
483 
484  template <typename AlternativeT, typename ConstAlternativeT>
485  void operator()(AlternativeT &&value, ConstAlternativeT &other) const
486  {
487  using PlaintT = typename std::remove_reference<AlternativeT>::type;
488  using PlaintOtherT =
489  typename std::remove_const<typename std::remove_reference<AlternativeT>::type>::type;
490  static_assert(std::is_same<PlaintT, PlaintOtherT>::value, "Incompatible types");
491 
492  new (&value) PlaintT(other);
493  }
494  };
495 
496  struct CopyMoveAssigner
497  {
498  template <typename AlternativeT> void operator()(AlternativeT &&value, AlternativeT &&other) const
499  {
500  value = std::move(other);
501  }
502 
503  template <typename AlternativeT, typename ConstAlternativeT>
504  void operator()(AlternativeT &&value, ConstAlternativeT &other) const
505  {
506  using PlaintT = typename std::remove_reference<AlternativeT>::type;
507  using PlaintOtherT =
508  typename std::remove_const<typename std::remove_reference<AlternativeT>::type>::type;
509  static_assert(std::is_same<PlaintT, PlaintOtherT>::value, "Incompatible types");
510 
511  value = other;
512  }
513  };
514 
515  template <IndexT Index, typename... Args> struct VisitorUtil;
516 
517  template <IndexT Index, typename First, typename Second, typename... Rest>
518  struct VisitorUtil<Index, First, Second, Rest...>
519  {
520  template <typename VisitorStruct> static void Visit(VariantImpl *pThis, VisitorStruct &&visitor)
521  {
522  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
523 
524  if (Index == pThis->m_index)
525  {
526  using AlternativeT = typename ThisVariantAlternative<Index>::type;
527  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
528  visitor(*value);
529  }
530  else
531  {
532  VisitorUtil<static_cast<IndexT>(Index + 1), Second, Rest...>::Visit(
533  pThis, std::forward<VisitorStruct>(visitor));
534  }
535  }
536 
537  template <typename VisitorStruct>
538  static void VisitBinary(
539  VariantImpl<Ts...> *pThis,
540  VariantImpl<Ts...> &&other,
541  VisitorStruct &&visitor)
542  {
543  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
544 
545  if (Index == pThis->m_index)
546  {
547  using AlternativeT = typename ThisVariantAlternative<Index>::type;
548  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
549  visitor(*value, other.get<AlternativeT>());
550  }
551  else
552  {
553  VisitorUtil<static_cast<IndexT>(Index + 1), Second, Rest...>::VisitBinary(
554  pThis, std::forward<VariantImpl<Ts...>>(other), std::forward<VisitorStruct>(visitor));
555  }
556  }
557 
558  template <typename VisitorStruct>
559  static void VisitBinary(
560  VariantImpl<Ts...> *pThis,
561  const VariantImpl<Ts...> &other,
562  VisitorStruct &&visitor)
563  {
564  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
565 
566  if (Index == pThis->m_index)
567  {
568  using AlternativeT = typename ThisVariantAlternative<Index>::type;
569  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
570  const AlternativeT &otherValue = other.get<AlternativeT>();
571  visitor(*value, otherValue);
572  }
573  else
574  {
575  VisitorUtil<static_cast<IndexT>(Index + 1), Second, Rest...>::VisitBinary(
576  pThis, other, std::forward<VisitorStruct>(visitor));
577  }
578  }
579  };
580 
581  template <IndexT Index, typename Last> struct VisitorUtil<Index, Last>
582  {
583  template <typename VisitorStruct> static void Visit(VariantImpl *pThis, VisitorStruct &&visitor)
584  {
585  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
586 
587  if (Index == pThis->m_index)
588  {
589  using AlternativeT = typename ThisVariantAlternative<Index>::type;
590  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
591  visitor(*value);
592  }
593  else
594  {
595  AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!");
596  }
597  }
598 
599  template <typename VisitorStruct>
600  static void VisitBinary(
601  VariantImpl<Ts...> *pThis,
602  VariantImpl<Ts...> &&other,
603  VisitorStruct &&visitor)
604  {
605  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
606 
607  if (Index == pThis->m_index)
608  {
609  using AlternativeT = typename ThisVariantAlternative<Index>::type;
610  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
611  visitor(*value, other.get<AlternativeT>());
612  }
613  else
614  {
615  AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!");
616  }
617  }
618 
619  template <typename VisitorStruct>
620  static void VisitBinary(
621  VariantImpl<Ts...> *pThis,
622  const VariantImpl<Ts...> &other,
623  VisitorStruct &&visitor)
624  {
625  static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
626 
627  if (Index == pThis->m_index)
628  {
629  using AlternativeT = typename ThisVariantAlternative<Index>::type;
630  AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
631  const AlternativeT &otherValue = other.get<AlternativeT>();
632  visitor(*value, otherValue);
633  }
634  else
635  {
636  AWS_FATAL_ASSERT(!"Unknown variant alternative to visit!");
637  }
638  }
639  };
640  };
641 
642  /* Helper template to get an actual type from an Index */
643  template <std::size_t Index, typename... Ts> class VariantAlternative
644  {
645  public:
646  // uses std::tuple as a helper struct to provide index-based access of a parameter pack
647  using type = typename std::tuple_element<Index, std::tuple<Ts...>>::type;
648 
650 
652  };
653 
654  template <typename T> class VariantSize
655  {
656  constexpr static const std::size_t Value = T::AlternativeCount;
657  };
658 
659  } // namespace VariantDetail
660 
665  template <typename... Ts>
666  class Variant : public VariantDetail::MovableVariant<Conjunction<std::is_move_constructible<Ts>...>::value>,
667  public VariantDetail::CopyableVariant<Conjunction<std::is_copy_constructible<Ts>...>::value>
668  {
669  /* Copyability and Movability depend only on constructors (copy and move correspondingly) of the
670  * underlying types. This means that a class with move constructor but with no move assignment operator
671  * might cause compilation issues. If such a type ever needs to be supported, additional base class needs
672  * to be introduced: MoveAssignable. For now, it'll be overengineering.
673  * The same applies to copy constructor and copy assignment operator. */
674 
675  private:
676  template <std::size_t Index> using ThisVariantAlternative = VariantDetail::VariantAlternative<Index, Ts...>;
677 
678  template <typename OtherT>
679  using EnableIfOtherIsThisVariantAlternative = typename std::
680  enable_if<VariantDetail::Checker::HasType<typename std::decay<OtherT>::type, Ts...>::value, int>::type;
681 
682  static constexpr bool isFirstAlternativeNothrowDefaultConstructible =
683  VariantDetail::VariantImpl<Ts...>::isFirstAlternativeNothrowDefaultConstructible;
684 
685  public:
687  static constexpr std::size_t AlternativeCount = sizeof...(Ts);
688 
689  template <
690  typename T = typename VariantDetail::VariantImpl<Ts...>::FirstAlternative,
691  typename std::enable_if<std::is_default_constructible<T>::value, bool>::type = true>
692  Variant() noexcept(isFirstAlternativeNothrowDefaultConstructible)
693  {
694  }
695 
696  template <
697  typename T = typename VariantDetail::VariantImpl<Ts...>::FirstAlternative,
698  typename std::enable_if<!std::is_default_constructible<T>::value, bool>::type = true>
699  Variant() = delete;
700 
701  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
702  Variant(const T &val) noexcept(
703  std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
704  : m_variant(val)
705  {
706  }
707 
708  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
709  Variant(T &&val) noexcept(std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
710  : m_variant(std::forward<T>(val))
711  {
712  }
713 
714  template <typename T, typename... Args>
715  explicit Variant(Aws::Crt::InPlaceTypeT<T> ipt, Args &&...args)
716  : m_variant(ipt, std::forward<Args>(args)...)
717  {
718  }
719 
720  template <typename T, typename... Args, EnableIfOtherIsThisVariantAlternative<T> = 1>
721  T &emplace(Args &&...args)
722  {
723  return m_variant.template emplace<T>(std::forward<Args>(args)...);
724  }
725 
726  template <std::size_t Index, typename... Args>
727  auto emplace(Args &&...args) -> typename ThisVariantAlternative<Index>::type &
728  {
729  return m_variant.template emplace<Index>(std::forward<Args>(args)...);
730  }
731 
732  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> bool holds_alternative() const
733  {
734  return m_variant.template holds_alternative<T>();
735  }
736 
737  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T &get()
738  {
739  return m_variant.template get<T>();
740  }
741 
742  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T *get_if()
743  {
744  return m_variant.template get_if<T>();
745  }
746 
747  template <std::size_t Index> auto get() -> typename ThisVariantAlternative<Index>::type &
748  {
749  return m_variant.template get<Index>();
750  }
751 
752  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T &get() const
753  {
754  return m_variant.template get<T>();
755  }
756 
757  template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> const T *get_if() const
758  {
759  return m_variant.template get_if<T>();
760  }
761 
762  template <std::size_t Index> auto get() const -> const typename ThisVariantAlternative<Index>::type &
763  {
764  return m_variant.template get<Index>();
765  }
766 
767  template <std::size_t Index>
769  typename std::add_pointer<typename ThisVariantAlternative<Index>::type>::type;
770 
771  template <std::size_t Index> auto get_if() -> RawAlternativePointerT<Index>
772  {
773  return m_variant.template get_if<Index>();
774  }
775 
776  template <std::size_t Index>
777  using ConstRawAlternativePointerT = typename std::add_pointer<
778  typename std::add_const<typename ThisVariantAlternative<Index>::type>::type>::type;
779 
780  template <std::size_t Index> auto get_if() const -> ConstRawAlternativePointerT<Index>
781  {
782  return m_variant.template get_if<Index>();
783  }
784 
785  std::size_t index() const { return m_variant.index(); }
786 
787  template <typename VisitorT> void Visit(VisitorT &&visitor)
788  {
789  m_variant.Visit(std::forward<VisitorT>(visitor));
790  }
791 
792  private:
793  VariantDetail::VariantImpl<Ts...> m_variant;
794  };
795 
796  } // namespace Crt
797 } // namespace Aws
Aws::Crt::VariantDetail::VariantImpl::emplace
auto emplace(Args &&...args) -> typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:323
Aws::Crt::VariantDetail::VariantImpl::operator=
VariantImpl & operator=(const VariantImpl &other)
Definition: Variant.h:262
Aws::Crt::InPlaceTypeT
Definition: Utility.h:21
Aws::Crt::VariantDetail::ParameterPackSize::GetMaxSizeOf
constexpr std::size_t GetMaxSizeOf(std::size_t curMax=0)
Definition: Variant.h:29
Aws::Crt::VariantDetail::CopyableVariant< true >::operator=
CopyableVariant & operator=(const CopyableVariant &other)=default
Aws::Crt::VariantDetail::CopyableVariant
Definition: Variant.h:144
Aws::Crt::VariantDetail::VariantAlternative::VariantAlternative
VariantAlternative(const VariantImpl< Ts... > &)
Definition: Variant.h:649
Aws::Crt::VariantDetail::VariantImpl::get
auto get() -> typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:358
Aws::Crt::VariantDetail::VariantImpl
Definition: Variant.h:171
Aws::Crt::Variant::get_if
T * get_if()
Definition: Variant.h:742
Aws::Crt::Variant::AlternativeCount
static constexpr std::size_t AlternativeCount
Definition: Variant.h:687
Aws::Crt::VariantDetail::VariantImpl::get
T & get()
Definition: Variant.h:338
Aws::Crt::VariantDetail::MovableVariant< true >::operator=
MovableVariant & operator=(const MovableVariant &)=default
Aws::Crt::VariantDetail::VariantImpl::AlternativeCount
static constexpr std::size_t AlternativeCount
Definition: Variant.h:190
Aws::Crt::VariantDetail::VariantImpl::get
const T & get() const
Definition: Variant.h:368
Aws::Crt::VariantDetail::VariantAlternative
Definition: Variant.h:644
Aws::Crt::Variant::get_if
auto get_if() const -> ConstRawAlternativePointerT< Index >
Definition: Variant.h:780
Aws::Crt::VariantDetail::CopyableVariant< true >::CopyableVariant
CopyableVariant(CopyableVariant &&)=default
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl(const VariantImpl &other)
Definition: Variant.h:198
Aws::Crt::Variant::Variant
Variant() noexcept(isFirstAlternativeNothrowDefaultConstructible)
Definition: Variant.h:692
Aws::Crt::Variant< R, E >::IndexT
VariantDetail::Index::VariantIndex IndexT
Definition: Variant.h:686
Aws::Crt::VariantDetail::MovableVariant< false >::MovableVariant
MovableVariant(MovableVariant &&)=delete
Aws::Crt::VariantDetail::VariantImpl::emplace
T & emplace(Args &&...args)
Definition: Variant.h:302
Aws::Crt::VariantDetail::VariantImpl::isFirstAlternativeNothrowDefaultConstructible
static constexpr bool isFirstAlternativeNothrowDefaultConstructible
Definition: Variant.h:183
Aws::Crt::Variant::Variant
Variant(const T &val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition: Variant.h:702
Aws::Crt::VariantDetail::VariantImpl< Ts... >::IndexT
VariantDetail::Index::VariantIndex IndexT
Definition: Variant.h:189
Aws::Crt::VariantDetail::VariantImpl::holds_alternative
bool holds_alternative() const
Definition: Variant.h:331
Aws::Crt::VariantDetail::VariantAlternative::type
typename std::tuple_element< Index, std::tuple< Ts... > >::type type
Definition: Variant.h:647
Aws::Crt::Variant::Variant
Variant(T &&val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition: Variant.h:709
Aws::Crt::VariantDetail::CopyableVariant< false >::operator=
CopyableVariant & operator=(const CopyableVariant &)=delete
Aws::Crt::Variant::get
auto get() const -> const typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:762
Aws::Crt::VariantDetail::VariantSize
Definition: Variant.h:655
Aws::Crt::VariantDetail::CopyableVariant< true >::CopyableVariant
CopyableVariant(const CopyableVariant &other)=default
Aws::Crt::Variant< R, E >::ConstRawAlternativePointerT
typename std::add_pointer< typename std::add_const< typename ThisVariantAlternative< Index >::type >::type >::type ConstRawAlternativePointerT
Definition: Variant.h:778
Aws::Crt::Variant::get_if
auto get_if() -> RawAlternativePointerT< Index >
Definition: Variant.h:771
Aws::Crt::Variant::holds_alternative
bool holds_alternative() const
Definition: Variant.h:732
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl(const T &val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition: Variant.h:213
Aws::Crt::VariantDetail::MovableVariant< false >::MovableVariant
MovableVariant()=default
Aws::Crt::Variant::Variant
Variant(Aws::Crt::InPlaceTypeT< T > ipt, Args &&...args)
Definition: Variant.h:715
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl(VariantImpl &&other)
Definition: Variant.h:205
Aws::Crt::Variant< R, E >::RawAlternativePointerT
typename std::add_pointer< typename ThisVariantAlternative< Index >::type >::type RawAlternativePointerT
Definition: Variant.h:769
Aws::Crt::VariantDetail::Checker::ContainsType
constexpr bool ContainsType()
Definition: Variant.h:73
Aws::Crt::Variant::emplace
auto emplace(Args &&...args) -> typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:727
Aws::Crt::VariantDetail::MovableVariant< true >::MovableVariant
MovableVariant(const MovableVariant &)=default
Aws::Crt::Variant
Definition: Variant.h:668
TypeTraits.h
Aws::Crt::VariantDetail::CopyableVariant< false >::operator=
CopyableVariant & operator=(CopyableVariant &&)=default
Aws::Crt::VariantDetail::ParameterPackSize::AlignAsPack
constexpr std::size_t AlignAsPack(std::size_t curMax=0)
Definition: Variant.h:41
Aws::Crt::Variant::get
T & get()
Definition: Variant.h:737
Aws::Crt::Variant::get
auto get() -> typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:747
Aws::Crt::VariantDetail::VariantAlternative::VariantAlternative
VariantAlternative(const VariantImpl< Ts... > *)
Definition: Variant.h:651
Aws::Crt::VariantDetail::VariantImpl::get_if
auto get_if() const -> ConstRawAlternativePointerT< Index >
Definition: Variant.h:423
Aws::Crt::VariantDetail::VariantImpl::get_if
T * get_if()
Definition: Variant.h:345
Aws::Crt::VariantDetail::VariantImpl< Ts... >::RawAlternativePointerT
typename std::add_pointer< typename ThisVariantAlternative< Index >::type >::type RawAlternativePointerT
Definition: Variant.h:402
Aws::Crt::VariantDetail::VariantImpl< Ts... >::FirstAlternative
typename ThisVariantAlternative< 0 >::type FirstAlternative
Definition: Variant.h:181
Aws::Crt::VariantDetail::MovableVariant< true >::operator=
MovableVariant & operator=(MovableVariant &&other)=default
Aws::Crt::VariantDetail::VariantImpl::get_if
auto get_if() -> RawAlternativePointerT< Index >
Definition: Variant.h:404
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl() noexcept(isFirstAlternativeNothrowDefaultConstructible)
Definition: Variant.h:192
Aws::Crt::Variant::get
const T & get() const
Definition: Variant.h:752
Aws::Crt::VariantDetail::VariantImpl::isFirstAlternativeDefaultConstructible
static constexpr bool isFirstAlternativeDefaultConstructible
Definition: Variant.h:186
Aws::Crt::VariantDetail::VariantImpl< Ts... >::ConstRawAlternativePointerT
typename std::add_pointer< typename std::add_const< typename ThisVariantAlternative< Index >::type >::type >::type ConstRawAlternativePointerT
Definition: Variant.h:421
Aws::Crt::VariantDetail::Index::GetIndexOf
constexpr VariantIndex GetIndexOf(VariantIndex curIndex=0)
Definition: Variant.h:57
Aws::Crt::VariantDetail::CopyableVariant< false >::CopyableVariant
CopyableVariant(const CopyableVariant &)=delete
Aws::Crt::VariantDetail::CopyableVariant< true >::operator=
CopyableVariant & operator=(CopyableVariant &&)=default
Aws::Crt::Variant::Variant
Variant()=delete
std
Definition: StringView.h:862
Aws::Crt::VariantDetail::MovableVariant
Definition: Variant.h:122
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl(Aws::Crt::InPlaceTypeT< T >, Args &&...args)
Definition: Variant.h:247
Aws
Definition: Allocator.h:11
Aws::Crt::VariantDetail::Checker::HasType::value
static const bool value
Definition: Variant.h:91
Aws::Crt::VariantDetail::MovableVariant< false >::operator=
MovableVariant & operator=(MovableVariant &&)=delete
Aws::Crt::VariantDetail::MovableVariant< true >::MovableVariant
MovableVariant()=default
Aws::Crt::VariantDetail::MovableVariant< false >::operator=
MovableVariant & operator=(const MovableVariant &)=default
Aws::Crt::VariantDetail::VariantImpl::get
auto get() const -> const typename ThisVariantAlternative< Index >::type &
Definition: Variant.h:388
Aws::Crt::VariantDetail::VariantImpl::operator=
VariantImpl & operator=(VariantImpl &&other)
Definition: Variant.h:281
Aws::Crt::VariantDetail::VariantImpl::VariantImpl
VariantImpl(T &&val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition: Variant.h:230
Aws::Crt::VariantDetail::ConstExprMax
constexpr const T & ConstExprMax(const T &a, const T &b)
Definition: Variant.h:21
Aws::Crt::Variant::get_if
const T * get_if() const
Definition: Variant.h:757
Aws::Crt::Variant::Visit
void Visit(VisitorT &&visitor)
Definition: Variant.h:787
Aws::Crt::VariantDetail::VariantImpl::~VariantImpl
~VariantImpl()
Definition: Variant.h:440
Aws::Crt::Variant::emplace
T & emplace(Args &&...args)
Definition: Variant.h:721
Aws::Crt::VariantDetail::Index::VariantIndex
short VariantIndex
Definition: Variant.h:55
Aws::Crt::VariantDetail::Checker::HasType
Definition: Variant.h:90
Aws::Crt::VariantDetail::VariantImpl::Visit
void Visit(VisitorT &&visitor)
Definition: Variant.h:442
Aws::Crt::VariantDetail::CopyableVariant< false >::CopyableVariant
CopyableVariant()=default
Aws::Crt::VariantDetail::CopyableVariant< true >::CopyableVariant
CopyableVariant()=default
Aws::Crt::VariantDetail::MovableVariant< true >::MovableVariant
MovableVariant(MovableVariant &&other)=default
Aws::Crt::VariantDetail::CopyableVariant< false >::CopyableVariant
CopyableVariant(CopyableVariant &&)=default
Utility.h
Aws::Crt::Variant::index
std::size_t index() const
Definition: Variant.h:785
Aws::Crt::VariantDetail::MovableVariant< false >::MovableVariant
MovableVariant(const MovableVariant &)=default
Aws::Crt::VariantDetail::VariantImpl::get_if
const T * get_if() const
Definition: Variant.h:375
Aws::Crt::VariantDetail::VariantImpl::index
std::size_t index() const
Definition: Variant.h:438