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
Optional.h
Go to the documentation of this file.
1#pragma once
7#include <aws/crt/Utility.h>
8#include <utility>
9
10namespace 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
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
Definition Optional.h:19
const T & operator*() const &
Definition Optional.h:116
Optional(const T &val)
Definition Optional.h:24
Optional< T > & operator=(const Optional &other)
Definition Optional.h:98
T ValueType
Definition Optional.h:21
Optional & operator=(U &&u)
Definition Optional.h:52
const T & value() const &
Definition Optional.h:125
Optional()
Definition Optional.h:23
T & emplace(Args &&...args)
Definition Optional.h:104
bool has_value() const noexcept
Definition Optional.h:122
void reset()
Definition Optional.h:130
Optional(const Optional< T > &other)
Definition Optional.h:66
T && operator*() &&
Definition Optional.h:119
const T && operator*() const &&
Definition Optional.h:118
Optional(Aws::Crt::InPlaceT, Args &&...args)
Definition Optional.h:92
Optional(Optional< T > &&other)
Definition Optional.h:79
Optional< T > & operator=(const Optional< U > &other)
Definition Optional.h:100
Optional(T &&val)
Definition Optional.h:30
T & operator*() &
Definition Optional.h:117
Optional< T > & operator=(Optional< U > &&other)
Definition Optional.h:102
T && value() &&
Definition Optional.h:127
const T * operator->() const
Definition Optional.h:114
T & value() &
Definition Optional.h:124
~Optional()
Definition Optional.h:36
T * operator->()
Definition Optional.h:115
const T && value() const &&
Definition Optional.h:128
std::unique_ptr< T, std::function< void(T *)> > ScopedResource
Definition Types.h:163
Definition Allocator.h:11
Definition Utility.h:15