AWS IoT Device SDK C++ v2  1.36.0
AWS IoT Device SDK C++ v2
Optional.h
Go to the documentation of this file.
1 #pragma once
2 
6 #include <aws/crt/TypeTraits.h>
7 #include <aws/crt/Utility.h>
8 #include <utility>
9 
10 namespace Aws
11 {
12  namespace Crt
13  {
18  template <typename T> class Optional
19  {
20  public:
21  using ValueType = T;
22 
23  Optional() : m_value(nullptr) {}
24  Optional(const T &val)
25  {
26  new (m_storage) T(val);
27  m_value = reinterpret_cast<T *>(m_storage);
28  }
29 
30  Optional(T &&val)
31  {
32  new (m_storage) T(std::forward<T>(val));
33  m_value = reinterpret_cast<T *>(m_storage);
34  }
35 
37  {
38  if (m_value)
39  {
40  m_value->~T();
41  }
42  }
43 
47  template <
48  typename U = T,
49  typename std::enable_if<
51  bool>::type = true>
53  {
54  if (m_value)
55  {
56  *m_value = std::forward<U>(u);
57  return *this;
58  }
59 
60  new (m_storage) T(std::forward<U>(u));
61  m_value = reinterpret_cast<T *>(m_storage);
62 
63  return *this;
64  }
65 
66  Optional(const Optional<T> &other)
67  {
68  if (other.m_value)
69  {
70  new (m_storage) T(*other.m_value);
71  m_value = reinterpret_cast<T *>(m_storage);
72  }
73  else
74  {
75  m_value = nullptr;
76  }
77  }
78 
80  {
81  if (other.m_value)
82  {
83  new (m_storage) T(std::forward<T>(*other.m_value));
84  m_value = reinterpret_cast<T *>(m_storage);
85  }
86  else
87  {
88  m_value = nullptr;
89  }
90  }
91 
92  template <typename... Args> explicit Optional(Aws::Crt::InPlaceT, Args &&...args)
93  {
94  new (m_storage) T(std::forward<Args>(args)...);
95  m_value = reinterpret_cast<T *>(m_storage);
96  }
97 
98  Optional<T> &operator=(const Optional &other) { return assign(other); }
99 
100  template <typename U = T> Optional<T> &operator=(const Optional<U> &other) { return assign(other); }
101 
102  template <typename U = T> Optional<T> &operator=(Optional<U> &&other) { return assign(std::move(other)); }
103 
104  template <typename... Args> T &emplace(Args &&...args)
105  {
106  reset();
107 
108  new (m_storage) T(std::forward<Args>(args)...);
109  m_value = reinterpret_cast<T *>(m_storage);
110 
111  return *m_value;
112  }
113 
114  const T *operator->() const { return m_value; }
115  T *operator->() { return m_value; }
116  const T &operator*() const & { return *m_value; }
117  T &operator*() & { return *m_value; }
118  const T &&operator*() const && { return std::move(*m_value); }
119  T &&operator*() && { return std::move(*m_value); }
120 
121  explicit operator bool() const noexcept { return m_value != nullptr; }
122  bool has_value() const noexcept { return m_value != nullptr; }
123 
124  T &value() & { return *m_value; }
125  const T &value() const & { return *m_value; }
126 
127  T &&value() && { return std::move(*m_value); }
128  const T &&value() const && { return std::move(*m_value); }
129 
130  void reset()
131  {
132  if (m_value)
133  {
134  m_value->~T();
135  m_value = nullptr;
136  }
137  }
138 
139  private:
140  template <typename Op> Optional &assign(Op &&other)
141  {
142  // U is an underlying type of the Optional type passed to this function. Depending on constness of Op,
143  // U will be either value or const ref.
144  // NOTE: std::is_const<const C&> == false, that's why std::remove_reference is needed here.
145  using U = typename std::conditional<
146  std::is_const<typename std::remove_reference<Op>::type>::value,
147  const typename std::decay<Op>::type::ValueType &,
148  typename std::decay<Op>::type::ValueType>::type;
149 
150  if ((void *)this == (void *)&other)
151  {
152  return *this;
153  }
154 
155  if (m_value)
156  {
157  // Optional<U> is a completely different class from the C++ specifics pov. So, we can use only
158  // public members of `other`.
159  if (other.has_value())
160  {
161  *m_value = std::forward<U>(other.value());
162  }
163  else
164  {
165  m_value->~T();
166  m_value = nullptr;
167  }
168 
169  return *this;
170  }
171 
172  if (other.has_value())
173  {
174  new (m_storage) T(std::forward<U>(other.value()));
175  m_value = reinterpret_cast<T *>(m_storage);
176  }
177 
178  return *this;
179  }
180 
181  alignas(T) char m_storage[sizeof(T)];
182  T *m_value;
183  };
184  } // namespace Crt
185 } // namespace Aws
Aws::Crt::Optional::operator*
const T && operator*() const &&
Definition: Optional.h:118
Aws::Crt::Optional::Optional
Optional(const T &val)
Definition: Optional.h:24
Aws::Crt::InPlaceT
Definition: Utility.h:15
Aws::Crt::Optional::emplace
T & emplace(Args &&...args)
Definition: Optional.h:104
Aws::Crt::Optional::operator*
const T & operator*() const &
Definition: Optional.h:116
Aws::Crt::Optional::Optional
Optional(T &&val)
Definition: Optional.h:30
Aws::Crt::Optional::operator=
Optional< T > & operator=(Optional< U > &&other)
Definition: Optional.h:102
Aws::Crt::Optional::has_value
bool has_value() const noexcept
Definition: Optional.h:122
Aws::Crt::Optional
Definition: Optional.h:19
TypeTraits.h
Aws::Crt::Optional::value
T & value() &
Definition: Optional.h:124
Aws::Crt::Optional::~Optional
~Optional()
Definition: Optional.h:36
Aws::Crt::DateTime
Definition: DateTime.h:53
Aws
Definition: Allocator.h:11
Aws::Crt::Optional::operator=
Optional & operator=(U &&u)
Definition: Optional.h:52
Aws::Crt::Optional::operator*
T & operator*() &
Definition: Optional.h:117
Aws::Crt::Optional::value
const T & value() const &
Definition: Optional.h:125
Aws::Crt::Optional::operator=
Optional< T > & operator=(const Optional &other)
Definition: Optional.h:98
Aws::Crt::Optional::operator=
Optional< T > & operator=(const Optional< U > &other)
Definition: Optional.h:100
Aws::Crt::Optional::value
const T && value() const &&
Definition: Optional.h:128
Aws::Crt::Optional::operator*
T && operator*() &&
Definition: Optional.h:119
Aws::Crt::Optional::value
T && value() &&
Definition: Optional.h:127
Aws::Crt::Optional::Optional
Optional(Optional< T > &&other)
Definition: Optional.h:79
Aws::Crt::Optional::Optional
Optional()
Definition: Optional.h:23
Utility.h
Aws::Crt::Optional::Optional
Optional(const Optional< T > &other)
Definition: Optional.h:66
Aws::Crt::IsSpecializationOf
Definition: TypeTraits.h:20
Aws::Crt::Optional::operator->
T * operator->()
Definition: Optional.h:115
Aws::Crt::Optional::operator->
const T * operator->() const
Definition: Optional.h:114
Aws::Crt::Optional::reset
void reset()
Definition: Optional.h:130
Aws::Crt::Optional::Optional
Optional(Aws::Crt::InPlaceT, Args &&...args)
Definition: Optional.h:92