Fast CDR  Version 2.3.6
Fast CDR
optional.hpp
1 // Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 #ifndef _FASTCDR_XCDR_OPTIONAL_HPP_
16 #define _FASTCDR_XCDR_OPTIONAL_HPP_
17 
18 #include <new>
19 #include <utility>
20 
21 #include "detail/optional.hpp"
22 #include "../exceptions/BadOptionalAccessException.hpp"
23 
24 namespace eprosima {
25 namespace fastcdr {
26 
28 struct nullopt_t
29 {
30  constexpr explicit nullopt_t(
31  int)
32  {
33  }
34 
35 };
36 
40 static constexpr nullopt_t nullopt {0};
41 
45 template<class T>
46 class optional
47 {
48 public:
49 
50  using type = T;
51 
53  optional() = default;
54 
57  const T& val) noexcept
58  {
59  ::new(&storage_.val_)T(val);
60  storage_.engaged_ = true;
61  }
62 
65  T&& val) noexcept
66  {
67  ::new(&storage_.val_)T(std::move(val));
68  storage_.engaged_ = true;
69  }
70 
73  const optional<T>& val) noexcept
74  {
75  if (val.storage_.engaged_)
76  {
77  ::new(&storage_.val_)T(val.storage_.val_);
78  storage_.engaged_ = true;
79  }
80  }
81 
84  optional<T>&& val) noexcept
85  {
86  if (val.storage_.engaged_)
87  {
88  ::new(&storage_.val_)T(std::move(val.storage_.val_));
89  storage_.engaged_ = true;
90  }
91  }
92 
95 #if defined(__GNUC__) && __GNUC__ >= 12
96  __attribute__(
97  (noinline))
98 #endif // if defined(__GNUC__) && __GNUC__ >= 12
99  = default;
100 
106  template<class ... Args> void emplace(
107  Args&&... _args)
108  {
109  reset();
110  storage_.val_.T(std::forward<Args>(_args)...);
111  storage_.engaged_ = true;
112  }
113 
120  void reset(
121  bool initial_engaged = false)
122  {
123  if (storage_.engaged_)
124  {
125  storage_.val_.~T();
126  }
127  storage_.engaged_ = initial_engaged;
128  if (storage_.engaged_)
129  {
130  ::new(&storage_.val_)T();
131  }
132  }
133 
140  T& value()&
141  {
142  if (!storage_.engaged_)
143  {
146  }
147 
148  return storage_.val_;
149  }
150 
157  const T& value() const&
158  {
159  if (!storage_.engaged_)
160  {
163  }
164 
165  return storage_.val_;
166  }
167 
174  T&& value() &&
175  {
176  if (!storage_.engaged_)
177  {
180  }
181 
182  return std::move(storage_.val_);
183  }
184 
191  const T&& value() const&&
192  {
193  if (!storage_.engaged_)
194  {
197  }
198 
199  return std::move(storage_.val_);
200  }
201 
207  bool has_value() const
208  {
209  return storage_.engaged_;
210  }
211 
214  const optional& opt)
215 #if defined(__GNUC__) && __GNUC__ >= 12
216  __attribute__(
217  (noinline))
218 #endif // if defined(__GNUC__) && __GNUC__ >= 12
219  {
220  reset();
221  storage_.engaged_ = opt.storage_.engaged_;
222  if (opt.storage_.engaged_)
223  {
224  ::new(&storage_.val_)T(opt.storage_.val_);
225  }
226  return *this;
227  }
228 
231  optional&& opt)
232 #if defined(__GNUC__) && __GNUC__ >= 12
233  __attribute__(
234  (noinline))
235 #endif // if defined(__GNUC__) && __GNUC__ >= 12
236  {
237  reset();
238  storage_.engaged_ = opt.storage_.engaged_;
239  if (opt.storage_.engaged_)
240  {
241  ::new(&storage_.val_)T(std::move(opt.storage_.val_));
242  }
243  return *this;
244  }
245 
248  const T& val)
249  {
250  reset();
251  ::new(&storage_.val_)T(val);
252  storage_.engaged_ = true;
253  return *this;
254  }
255 
258  T&& val)
259  {
260  reset();
261  ::new(&storage_.val_)T(std::move(val));
262  storage_.engaged_ = true;
263  return *this;
264  }
265 
268  nullopt_t) noexcept
269  {
270  reset();
271  return *this;
272  }
273 
276  const optional& opt_val) const
277  {
278  return opt_val.storage_.engaged_ == storage_.engaged_ &&
279  (storage_.engaged_ ? opt_val.storage_.val_ == storage_.val_ : true);
280  }
281 
284  const optional& opt_val) const
285  {
286  return !operator ==(opt_val);
287  }
288 
296  T& operator *() & noexcept
297  {
298  return storage_.val_;
299  }
300 
308  const T& operator *() const& noexcept
309  {
310  return storage_.val_;
311  }
312 
320  T && operator *() && noexcept
321  {
322  return std::move(storage_.val_);
323  }
324 
332  const T && operator*() const && noexcept
333  {
334  return std::move(storage_.val_);
335  }
336 
344  T* operator ->() noexcept
345  {
346  return std::addressof(storage_.val_);
347  }
348 
356  const T* operator ->() const noexcept
357  {
358  return std::addressof(storage_.val_);
359  }
360 
362  explicit operator bool() const noexcept
363  {
364  return storage_.engaged_;
365  }
366 
367 private:
368 
370 };
371 
372 } // namespace fastcdr
373 } // namespace eprosima
374 
375 #endif //_FASTCDR_XCDR_OPTIONAL_HPP_
This class is thrown as an exception when accessing the value of a null optional.
Definition: BadOptionalAccessException.hpp:28
static const char *const BAD_OPTIONAL_ACCESS_MESSAGE_DEFAULT
Default message used in the library.
Definition: BadOptionalAccessException.hpp:78
This class template manages an optional contained value, i.e.
Definition: optional.hpp:47
bool operator!=(const optional &opt_val) const
Compares optional values.
Definition: optional.hpp:283
void reset(bool initial_engaged=false)
Reset the state of the optional.
Definition: optional.hpp:120
optional()=default
Default constructor.
const T && value() const &&
Returns the contained value.
Definition: optional.hpp:191
optional(optional< T > &&val) noexcept
Move constructor.
Definition: optional.hpp:83
optional & operator=(const optional &opt)
Assigns content from an optional.
Definition: optional.hpp:213
optional(const optional< T > &val) noexcept
Copy constructor.
Definition: optional.hpp:72
const T && operator*() const &&noexcept
Accesses the contained value.
Definition: optional.hpp:332
bool has_value() const
Checks whether the optional contains a value.
Definition: optional.hpp:207
T && value() &&
Returns the contained value.
Definition: optional.hpp:174
T type
Definition: optional.hpp:50
optional(const T &val) noexcept
Copy constructor from an instance of the templated class.
Definition: optional.hpp:56
const T & value() const &
Returns the contained value.
Definition: optional.hpp:157
T & operator*() &noexcept
Accesses the contained value.
Definition: optional.hpp:296
bool operator==(const optional &opt_val) const
Compares optional values.
Definition: optional.hpp:275
T & value() &
Returns the contained value.
Definition: optional.hpp:140
T * operator->() noexcept
Accesses the contained value.
Definition: optional.hpp:344
void emplace(Args &&... _args)
Constructs the contained value in-place.
Definition: optional.hpp:106
~optional()=default
Destructor.
optional(T &&val) noexcept
Move constructor from an instance of the templated class.
Definition: optional.hpp:64
static constexpr nullopt_t nullopt
nullopt is a constant of type nullopt_t that is used to indicate optional type with uninitialized sta...
Definition: optional.hpp:40
Definition: fixed_size_string.hpp:32
An empty class type used to indicate optional type with uninitialized state.
Definition: optional.hpp:29
constexpr nullopt_t(int)
Definition: optional.hpp:30