aws-crt-cpp
C++ wrapper around the aws-c-* libraries. Provides Cross-Platform Transport Protocols and SSL/TLS implementations for C++.
Loading...
Searching...
No Matches
Variant.h
Go to the documentation of this file.
1#pragma once
7#include <aws/common/assert.h>
9#include <aws/crt/Utility.h>
10
11#include <algorithm>
12#include <type_traits>
13#include <utility>
14
15namespace 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 {
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 {
50 }
51 } // namespace ParameterPackSize
52
53 namespace Index
54 {
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>
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:
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
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:
181 using FirstAlternative = typename ThisVariantAlternative<0>::type;
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
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(
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);
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(
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));
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(
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)...);
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>
303 {
304 static_assert(
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)...);
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 {
341 T *value = reinterpret_cast<T *>(m_storage);
342 return *value;
343 }
344
345 template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> T *get_if()
346 {
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");
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 {
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 {
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");
408 {
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");
427 {
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 {
527 AlternativeT *value = reinterpret_cast<AlternativeT *>(pThis->m_storage);
528 visitor(*value);
529 }
530 else
531 {
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,
542 {
543 static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
544
545 if (Index == pThis->m_index)
546 {
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,
563 {
564 static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
565
566 if (Index == pThis->m_index)
567 {
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 {
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,
604 {
605 static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
606
607 if (Index == pThis->m_index)
608 {
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,
624 {
625 static_assert(Index < AlternativeCount, "Attempting to visit unknown Index Type");
626
627 if (Index == pThis->m_index)
628 {
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>
716 : m_variant(ipt, std::forward<Args>(args)...)
717 {
718 }
719
720 template <typename T, typename... Args, EnableIfOtherIsThisVariantAlternative<T> = 1>
722 {
723 return m_variant.template emplace<T>(std::forward<Args>(args)...);
724 }
725
726 template <std::size_t Index, typename... Args>
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
CopyableVariant & operator=(const CopyableVariant &)=delete
CopyableVariant(const CopyableVariant &)=delete
CopyableVariant & operator=(CopyableVariant &&)=default
CopyableVariant(const CopyableVariant &other)=default
CopyableVariant & operator=(const CopyableVariant &other)=default
CopyableVariant & operator=(CopyableVariant &&)=default
MovableVariant & operator=(MovableVariant &&)=delete
MovableVariant(const MovableVariant &)=default
MovableVariant & operator=(const MovableVariant &)=default
MovableVariant & operator=(const MovableVariant &)=default
MovableVariant(MovableVariant &&other)=default
MovableVariant(const MovableVariant &)=default
MovableVariant & operator=(MovableVariant &&other)=default
VariantAlternative(const VariantImpl< Ts... > *)
Definition Variant.h:651
VariantAlternative(const VariantImpl< Ts... > &)
Definition Variant.h:649
typename std::tuple_element< Index, std::tuple< Ts... > >::type type
Definition Variant.h:647
Definition Variant.h:171
static constexpr std::size_t AlternativeCount
Definition Variant.h:190
VariantImpl(const VariantImpl &other)
Definition Variant.h:198
typename std::add_pointer< typename ThisVariantAlternative< Index >::type >::type RawAlternativePointerT
Definition Variant.h:402
auto get() -> typename ThisVariantAlternative< Index >::type &
Definition Variant.h:358
T & get()
Definition Variant.h:338
VariantImpl() noexcept(isFirstAlternativeNothrowDefaultConstructible)
Definition Variant.h:192
auto get_if() -> RawAlternativePointerT< Index >
Definition Variant.h:404
void Visit(VisitorT &&visitor)
Definition Variant.h:442
auto get_if() const -> ConstRawAlternativePointerT< Index >
Definition Variant.h:423
const T & get() const
Definition Variant.h:368
VariantImpl & operator=(VariantImpl &&other)
Definition Variant.h:281
VariantImpl & operator=(const VariantImpl &other)
Definition Variant.h:262
auto emplace(Args &&...args) -> typename ThisVariantAlternative< Index >::type &
Definition Variant.h:323
VariantDetail::Index::VariantIndex IndexT
Definition Variant.h:189
VariantImpl(const T &val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition Variant.h:213
bool holds_alternative() const
Definition Variant.h:331
const T * get_if() const
Definition Variant.h:375
T & emplace(Args &&...args)
Definition Variant.h:302
std::size_t index() const
Definition Variant.h:438
typename ThisVariantAlternative< 0 >::type FirstAlternative
Definition Variant.h:181
static constexpr bool isFirstAlternativeNothrowDefaultConstructible
Definition Variant.h:183
VariantImpl(T &&val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition Variant.h:230
T * get_if()
Definition Variant.h:345
static constexpr bool isFirstAlternativeDefaultConstructible
Definition Variant.h:186
auto get() const -> const typename ThisVariantAlternative< Index >::type &
Definition Variant.h:388
typename std::add_pointer< typename std::add_const< typename ThisVariantAlternative< Index >::type >::type >::type ConstRawAlternativePointerT
Definition Variant.h:421
~VariantImpl()
Definition Variant.h:440
VariantImpl(Aws::Crt::InPlaceTypeT< T >, Args &&...args)
Definition Variant.h:247
VariantImpl(VariantImpl &&other)
Definition Variant.h:205
Definition Variant.h:655
Definition Variant.h:668
void Visit(VisitorT &&visitor)
Definition Variant.h:787
auto get() const -> const typename ThisVariantAlternative< Index >::type &
Definition Variant.h:762
Variant(Aws::Crt::InPlaceTypeT< T > ipt, Args &&...args)
Definition Variant.h:715
auto emplace(Args &&...args) -> typename ThisVariantAlternative< Index >::type &
Definition Variant.h:727
auto get_if() const -> ConstRawAlternativePointerT< Index >
Definition Variant.h:780
T * get_if()
Definition Variant.h:742
const T & get() const
Definition Variant.h:752
const T * get_if() const
Definition Variant.h:757
auto get() -> typename ThisVariantAlternative< Index >::type &
Definition Variant.h:747
Variant(const T &val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition Variant.h:702
typename std::add_pointer< typename ThisVariantAlternative< Index >::type >::type RawAlternativePointerT
Definition Variant.h:769
T & emplace(Args &&...args)
Definition Variant.h:721
Variant(T &&val) noexcept(std::is_nothrow_constructible< typename std::decay< T >::type, decltype(val)>::value)
Definition Variant.h:709
T & get()
Definition Variant.h:737
std::size_t index() const
Definition Variant.h:785
auto get_if() -> RawAlternativePointerT< Index >
Definition Variant.h:771
static constexpr std::size_t AlternativeCount
Definition Variant.h:687
typename std::add_pointer< typename std::add_const< typename ThisVariantAlternative< Index >::type >::type >::type ConstRawAlternativePointerT
Definition Variant.h:778
Variant() noexcept(isFirstAlternativeNothrowDefaultConstructible)
Definition Variant.h:692
bool holds_alternative() const
Definition Variant.h:732
VariantDetail::Index::VariantIndex IndexT
Definition Variant.h:686
constexpr bool ContainsType()
Definition Variant.h:73
constexpr VariantIndex GetIndexOf(VariantIndex curIndex=0)
Definition Variant.h:57
short VariantIndex
Definition Variant.h:55
constexpr std::size_t AlignAsPack(std::size_t curMax=0)
Definition Variant.h:41
constexpr std::size_t GetMaxSizeOf(std::size_t curMax=0)
Definition Variant.h:29
constexpr const T & ConstExprMax(const T &a, const T &b)
Definition Variant.h:21
std::unique_ptr< T, std::function< void(T *)> > ScopedResource
Definition Types.h:163
Definition Allocator.h:11
Definition StringView.h:862
static const bool value
Definition Variant.h:91