LMMS
Loading...
Searching...
No Matches
juce_Optional.h
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26namespace detail
27{
28namespace adlSwap
29{
30using std::swap;
31
32template <typename T>
33constexpr auto isNothrowSwappable = noexcept (swap (std::declval<T&>(), std::declval<T&>()));
34} // namespace adlSwap
35} // namespace detail
36
40struct Nullopt
41{
42 explicit constexpr Nullopt (int) {}
43};
44
48constexpr Nullopt nullopt { 0 };
49
50// Without this, our tests can emit "unreachable code" warnings during
51// link time code generation.
53
54
72template <typename Value>
74{
75 template <typename T, typename U>
77 {
78 static constexpr auto value = ! std::is_constructible<T, Optional<U>&>::value
79 && ! std::is_constructible<T, const Optional<U>&>::value
80 && ! std::is_constructible<T, Optional<U>&&>::value
81 && ! std::is_constructible<T, const Optional<U>&&>::value
82 && ! std::is_convertible<Optional<U>&, T>::value
83 && ! std::is_convertible<const Optional<U>&, T>::value
84 && ! std::is_convertible<Optional<U>&&, T>::value
85 && ! std::is_convertible<const Optional<U>&&, T>::value;
86 };
87
88 template <typename T, typename U>
89 using OptionalCopyConstructorEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value && NotConstructibleFromSimilarType<T, U>::value>;
90
91 template <typename T, typename U>
92 using OptionalMoveConstructorEnabled = std::enable_if_t<std::is_constructible<T, U&&>::value && NotConstructibleFromSimilarType<T, U>::value>;
93
94 template <typename T, typename U>
96 && ! std::is_assignable<T&, Optional<U>&>::value
97 && ! std::is_assignable<T&, const Optional<U>&>::value
98 && ! std::is_assignable<T&, Optional<U>&&>::value
99 && ! std::is_assignable<T&, const Optional<U>&&>::value;
100
101 template <typename T, typename U>
102 using OptionalCopyAssignmentEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value
103 && std::is_assignable<T&, const U&>::value
105
106 template <typename T, typename U>
107 using OptionalMoveAssignmentEnabled = std::enable_if_t<std::is_constructible<T, U>::value
108 && std::is_nothrow_assignable<T&, U>::value
110
111public:
113
115
116 template <typename U = Value,
117 typename = std::enable_if_t<std::is_constructible<Value, U&&>::value
118 && ! std::is_same<std::decay_t<U>, Optional>::value>>
119 Optional (U&& value) noexcept (noexcept (Value (std::forward<U> (value))))
120 : storage (std::forward<U> (value)), valid (true)
121 {
122 }
123
124 Optional (Optional&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))
125 : placeholder()
126 {
127 constructFrom (other);
128 }
129
130 Optional (const Optional& other)
131 : placeholder(), valid (other.valid)
132 {
133 if (valid)
134 new (&storage) Value (*other);
135 }
136
137 template <typename Other, typename = OptionalMoveConstructorEnabled<Value, Other>>
138 Optional (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))
139 : placeholder()
140 {
141 constructFrom (other);
142 }
143
144 template <typename Other, typename = OptionalCopyConstructorEnabled<Value, Other>>
146 : placeholder(), valid (other.hasValue())
147 {
148 if (valid)
149 new (&storage) Value (*other);
150 }
151
152 Optional& operator= (Nullopt) noexcept
153 {
154 reset();
155 return *this;
156 }
157
158 template <typename U = Value,
159 typename = std::enable_if_t<std::is_nothrow_move_constructible<U>::value
160 && std::is_nothrow_move_assignable<U>::value>>
161 Optional& operator= (Optional&& other) noexcept (noexcept (std::declval<Optional>().assign (std::declval<Optional&>())))
162 {
163 assign (other);
164 return *this;
165 }
166
167 template <typename U = Value,
168 typename = std::enable_if_t<! std::is_same<std::decay_t<U>, Optional>::value
169 && std::is_constructible<Value, U>::value
170 && std::is_assignable<Value&, U>::value
171 && (! std::is_scalar<Value>::value || ! std::is_same<std::decay_t<U>, Value>::value)>>
172 Optional& operator= (U&& value)
173 {
174 if (valid)
175 **this = std::forward<U> (value);
176 else
177 new (&storage) Value (std::forward<U> (value));
178
179 valid = true;
180 return *this;
181 }
182
184 Optional& operator= (const Optional& other)
185 {
186 auto copy = other;
187 assign (copy);
188 return *this;
189 }
190
191 template <typename Other, typename = OptionalMoveAssignmentEnabled<Value, Other>>
192 Optional& operator= (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().assign (other)))
193 {
194 assign (other);
195 return *this;
196 }
197
199 template <typename Other, typename = OptionalCopyAssignmentEnabled<Value, Other>>
200 Optional& operator= (const Optional<Other>& other)
201 {
202 auto copy = other;
203 assign (copy);
204 return *this;
205 }
206
208 {
209 reset();
210 }
211
212 Value* operator->() noexcept { return reinterpret_cast< Value*> (&storage); }
213 const Value* operator->() const noexcept { return reinterpret_cast<const Value*> (&storage); }
214
216 const Value& operator*() const noexcept { return *operator->(); }
217
218 explicit operator bool() const noexcept { return valid; }
219 bool hasValue() const noexcept { return valid; }
220
221 void reset()
222 {
223 if (std::exchange (valid, false))
224 operator*().~Value();
225 }
226
228 template <typename U>
229 Value orFallback (U&& fallback) const { return *this ? **this : std::forward<U> (fallback); }
230
231 template <typename... Args>
232 Value& emplace (Args&&... args)
233 {
234 reset();
235 new (&storage) Value (std::forward<Args> (args)...);
236 valid = true;
237 return **this;
238 }
239
240 void swap (Optional& other) noexcept (std::is_nothrow_move_constructible<Value>::value
242 {
243 if (hasValue() && other.hasValue())
244 {
245 using std::swap;
246 swap (**this, *other);
247 }
248 else if (hasValue() || other.hasValue())
249 {
250 (hasValue() ? other : *this).constructFrom (hasValue() ? *this : other);
251 }
252 }
253
254private:
255 template <typename Other>
256 void constructFrom (Optional<Other>& other) noexcept (noexcept (Value (std::move (*other))))
257 {
258 if (! other.hasValue())
259 return;
260
261 new (&storage) Value (std::move (*other));
262 valid = true;
263 other.reset();
264 }
265
266 template <typename Other>
267 void assign (Optional<Other>& other) noexcept (noexcept (std::declval<Value&>() = std::move (*other)) && noexcept (std::declval<Optional>().constructFrom (other)))
268 {
269 if (valid)
270 {
271 if (other.hasValue())
272 {
273 **this = std::move (*other);
274 other.reset();
275 }
276 else
277 {
278 reset();
279 }
280 }
281 else
282 {
283 constructFrom (other);
284 }
285 }
286
287 union
288 {
291 };
292 bool valid = false;
293};
294
296
297template <typename Value>
299{
300 return std::forward<Value> (v);
301}
302
303template <class T, class U>
304bool operator== (const Optional<T>& lhs, const Optional<U>& rhs)
305{
306 if (lhs.hasValue() != rhs.hasValue()) return false;
307 if (! lhs.hasValue()) return true;
308 return *lhs == *rhs;
309}
310
311template <class T, class U>
312bool operator!= (const Optional<T>& lhs, const Optional<U>& rhs)
313{
314 if (lhs.hasValue() != rhs.hasValue()) return true;
315 if (! lhs.hasValue()) return false;
316 return *lhs != *rhs;
317}
318
319template <class T, class U>
320bool operator< (const Optional<T>& lhs, const Optional<U>& rhs)
321{
322 if (! rhs.hasValue()) return false;
323 if (! lhs.hasValue()) return true;
324 return *lhs < *rhs;
325}
326
327template <class T, class U>
328bool operator<= (const Optional<T>& lhs, const Optional<U>& rhs)
329{
330 if (! lhs.hasValue()) return true;
331 if (! rhs.hasValue()) return false;
332 return *lhs <= *rhs;
333}
334
335template <class T, class U>
336bool operator> (const Optional<T>& lhs, const Optional<U>& rhs)
337{
338 if (! lhs.hasValue()) return false;
339 if (! rhs.hasValue()) return true;
340 return *lhs > *rhs;
341}
342
343template <class T, class U>
344bool operator>= (const Optional<T>& lhs, const Optional<U>& rhs)
345{
346 if (! rhs.hasValue()) return true;
347 if (! lhs.hasValue()) return false;
348 return *lhs >= *rhs;
349}
350
351template <class T>
352bool operator== (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }
353template <class T>
354bool operator== (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }
355template <class T>
356bool operator!= (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }
357template <class T>
358bool operator!= (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }
359template <class T>
360bool operator< (const Optional<T>&, Nullopt) noexcept { return false; }
361template <class T>
362bool operator< (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }
363template <class T>
364bool operator<= (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }
365template <class T>
366bool operator<= (Nullopt, const Optional<T>&) noexcept { return true; }
367template <class T>
368bool operator> (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }
369template <class T>
370bool operator> (Nullopt, const Optional<T>&) noexcept { return false; }
371template <class T>
372bool operator>= (const Optional<T>&, Nullopt) noexcept { return true; }
373template <class T>
374bool operator>= (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }
375
376template <class T, class U>
377bool operator== (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt == value : false; }
378template <class T, class U>
379bool operator== (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value == *opt : false; }
380template <class T, class U>
381bool operator!= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt != value : true; }
382template <class T, class U>
383bool operator!= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value != *opt : true; }
384template <class T, class U>
385bool operator< (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt < value : true; }
386template <class T, class U>
387bool operator< (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value < *opt : false; }
388template <class T, class U>
389bool operator<= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt <= value : true; }
390template <class T, class U>
391bool operator<= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value <= *opt : false; }
392template <class T, class U>
393bool operator> (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt > value : false; }
394template <class T, class U>
395bool operator> (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value > *opt : true; }
396template <class T, class U>
397bool operator>= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt >= value : false; }
398template <class T, class U>
399bool operator>= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value >= *opt : true; }
400
401} // namespace juce
#define copy(x)
Definition ADnoteParameters.cpp:1011
#define noexcept
Definition DistrhoDefines.h:72
Definition juce_Optional.h:74
Optional(Nullopt) noexcept
Definition juce_Optional.h:114
~Optional() noexcept
Definition juce_Optional.h:207
Value orFallback(U &&fallback) const
Definition juce_Optional.h:229
Optional(Optional< Other > &&other) noexcept(noexcept(std::declval< Optional >().constructFrom(other)))
Definition juce_Optional.h:138
Value & operator*() noexcept
Definition juce_Optional.h:215
const Value * operator->() const noexcept
Definition juce_Optional.h:213
bool valid
Definition juce_Optional.h:292
const Value & operator*() const noexcept
Definition juce_Optional.h:216
Optional(Optional &&other) noexcept(noexcept(std::declval< Optional >().constructFrom(other)))
Definition juce_Optional.h:124
Optional(U &&value) noexcept(noexcept(Value(std::forward< U >(value))))
Definition juce_Optional.h:119
void reset()
Definition juce_Optional.h:221
Optional(const Optional &other)
Definition juce_Optional.h:130
void swap(Optional &other) noexcept(std::is_nothrow_move_constructible< Value >::value &&detail::adlSwap::isNothrowSwappable< Value >)
Definition juce_Optional.h:240
char placeholder
Definition juce_Optional.h:289
Value storage
Definition juce_Optional.h:290
static auto notAssignableFromSimilarType
Definition juce_Optional.h:95
Optional(const Optional< Other > &other)
Definition juce_Optional.h:145
Value * operator->() noexcept
Definition juce_Optional.h:212
std::enable_if_t< std::is_constructible< T, U && >::value &&NotConstructibleFromSimilarType< T, U >::value > OptionalMoveConstructorEnabled
Definition juce_Optional.h:92
void constructFrom(Optional< Other > &other) noexcept(noexcept(Value(std::move(*other))))
Definition juce_Optional.h:256
Optional()
Definition juce_Optional.h:112
std::enable_if_t< std::is_constructible< T, const U & >::value &&std::is_assignable< T &, const U & >::value &&NotConstructibleFromSimilarType< T, U >::value > OptionalCopyAssignmentEnabled
Definition juce_Optional.h:102
std::enable_if_t< std::is_constructible< T, const U & >::value &&NotConstructibleFromSimilarType< T, U >::value > OptionalCopyConstructorEnabled
Definition juce_Optional.h:89
Value & emplace(Args &&... args)
Definition juce_Optional.h:232
bool hasValue() const noexcept
Definition juce_Optional.h:219
std::enable_if_t< std::is_constructible< T, U >::value &&std::is_nothrow_assignable< T &, U >::value &&NotConstructibleFromSimilarType< T, U >::value > OptionalMoveAssignmentEnabled
Definition juce_Optional.h:107
void assign(Optional< Other > &other) noexcept(noexcept(std::declval< Value & >()=std::move(*other)) &&noexcept(std::declval< Optional >().constructFrom(other)))
Definition juce_Optional.h:267
Definition juce_Value.h:51
unsigned v[N_MAX]
Definition inflate.c:1584
#define U(x)
Definition fmopl.c:132
static PuglViewHint int value
Definition pugl.h:1708
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
Definition juce_Optional.h:29
constexpr auto isNothrowSwappable
Definition juce_Optional.h:33
Definition juce_FloatVectorOperations.h:143
Definition carla_juce.cpp:31
static void swap(ThrowOnMoveOrSwap &, ThrowOnMoveOrSwap &)
Definition juce_Optional_test.cpp:32
JUCE_END_IGNORE_WARNINGS_MSVC Optional< std::decay_t< Value > > makeOptional(Value &&v)
Definition juce_Optional.h:298
constexpr Nullopt nullopt
Definition juce_Optional.h:48
Definition juce_Uuid.h:141
#define true
Definition ordinals.h:82
Definition juce_Optional.h:41
constexpr Nullopt(int)
Definition juce_Optional.h:42
static constexpr auto value
Definition juce_Optional.h:78
#define const
Definition zconf.h:137