OnixS ICE iMpact Multicast Price Feed Handler C++ library 8.20.0
Users' manual and API documentation
Loading...
Searching...
No Matches
Optional.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Onix Solutions Limited. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable ONIXS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19
20#pragma once
21
22#include "Compiler.h"
23#include "Export.h"
24
25#include <new>
26#include <ostream>
27
28namespace OnixS { namespace ICE { namespace iMpact { namespace MarketData {
29
30template <typename T>
32{
33public:
36 : init_(false)
37 {
38 }
39
41 Optional(const T& val)
42 : init_(true)
43 {
44 construct(val);
45 }
46
53 : init_(opt.init_)
54 {
55 if (init_)
56 {
57 construct(opt.get());
58 }
59 }
60
63 {
64 // Self-assignment has to be caught before `destruct()`, which would
65 // otherwise destroy the very value `construct()` is about to read.
66 if (this == &opt)
67 {
68 return *this;
69 }
70
71 destruct();
72
73 if (opt.init_)
74 {
75 // `init_` is raised only once the value is there. `destruct()` has
76 // already cleared it, so a throwing copy constructor leaves this
77 // object empty rather than leaving the destructor to run `~T()`
78 // over storage no object was ever built in.
79 construct(opt.get());
80
81 init_ = true;
82 }
83
84 return *this;
85 }
86
88 Optional& operator=(const T& val)
89 {
90 // `val` may be the contained value itself -- `opt = *opt`, or
91 // `opt = opt.value()`. Destroying first would leave `construct()`
92 // copying from an object that no longer exists.
93 if (init_ && &val == &get())
94 {
95 return *this;
96 }
97
98 destruct();
99
100 // Raised after the value is there, for the reason given above.
101 construct(val);
102
103 init_ = true;
104
105 return *this;
106 }
107
110 {
111 destruct();
112 }
113
115 operator bool() const
116 {
117 return init_;
118 }
119
122 {
123 return get(); // undefined if not initialized
124 }
125
127 const T& operator*() const
128 {
129 return get(); // undefined if not initialized
130 }
131
133 T& value()
134 {
135 return **this;
136 }
137
139 const T& value() const
140 {
141 return **this;
142 }
143
145 void reset()
146 {
147 destruct();
148
149 init_ = false;
150 }
151
152protected:
153 void* storage()
154 {
155 return data_;
156 }
157
158 const void* storage() const
159 {
160 return data_;
161 }
162
163 // Placement `new` starts the lifetime of a `T` inside `data_`, but a pointer
164 // produced by casting the storage is not by itself a pointer to that object.
165 // Laundering it is what makes it one.
166 T& get()
167 {
168 return *ONIXS_ICEMDH_LAUNDER(static_cast<T*>(storage()));
169 }
170
171 const T& get() const
172 {
173 return *ONIXS_ICEMDH_LAUNDER(static_cast<const T*>(storage()));
174 }
175
176 void destruct()
177 {
178 if (init_)
179 {
180 get().~T();
181 }
182 init_ = false;
183 }
184
185 void construct(const T& data)
186 {
187 new(storage()) T(data);
188 }
189
190 // `alignas` is what keeps the contained value properly aligned: a bare
191 // `char` array has an alignment of 1, which makes every access to the value
192 // constructed inside it a misaligned one, and so undefined behaviour.
193 alignas(T) char data_[sizeof(T)];
194 bool init_;
195};
196
198template <typename T>
199std::ostream& operator<<(std::ostream& os, const Optional<T>& value)
200{
201 if (!value)
202 {
203 return os << "null";
204 }
205
206 return os << *value;
207}
208
209}}}} // namespace OnixS::ICE::iMpact::MarketData
#define ONIXS_ICEMDH_LAUNDER(ptr)
Definition Compiler.h:43
const T & operator*() const
Returns a const reference to the contained value.
Definition Optional.h:127
Optional & operator=(const Optional< T > &opt)
Assigns contents.
Definition Optional.h:62
T & operator*()
Returns a reference to the contained value.
Definition Optional.h:121
Optional(const T &val)
Constructs the optional object.
Definition Optional.h:41
Optional()
Uninitialized instance.
Definition Optional.h:35
Optional(const Optional< T > &opt)
Definition Optional.h:52
T & value()
A reference to the contained value.
Definition Optional.h:133
const T & value() const
A const reference to the contained value.
Definition Optional.h:139
Optional & operator=(const T &val)
Assigns contents.
Definition Optional.h:88
~Optional()
If engaged, destroys the contained value.
Definition Optional.h:109
void reset()
Reset stored value and set state to Uninitialized.
Definition Optional.h:145
ONIXS_ICEMDH_EXPORT std::ostream & operator<<(std::ostream &, const Error &)
Make it printable to formatted C++ I/O streams.