Commit | Line | Data |
---|---|---|
9dc3671c SM |
1 | // |
2 | // Copyright (c) 2014-2021 Martin Moene | |
3 | // | |
4 | // https://github.com/martinmoene/optional-lite | |
5 | // | |
6 | // Distributed under the Boost Software License, Version 1.0. | |
7 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #pragma once | |
10 | ||
11 | #ifndef NONSTD_OPTIONAL_LITE_HPP | |
12 | #define NONSTD_OPTIONAL_LITE_HPP | |
13 | ||
14 | #define optional_lite_MAJOR 3 | |
15 | #define optional_lite_MINOR 5 | |
16 | #define optional_lite_PATCH 0 | |
17 | ||
18 | #define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH) | |
19 | ||
20 | #define optional_STRINGIFY( x ) optional_STRINGIFY_( x ) | |
21 | #define optional_STRINGIFY_( x ) #x | |
22 | ||
23 | // optional-lite configuration: | |
24 | ||
25 | #define optional_OPTIONAL_DEFAULT 0 | |
26 | #define optional_OPTIONAL_NONSTD 1 | |
27 | #define optional_OPTIONAL_STD 2 | |
28 | ||
29 | // tweak header support: | |
30 | ||
31 | #ifdef __has_include | |
32 | # if __has_include(<nonstd/optional.tweak.hpp>) | |
33 | # include <nonstd/optional.tweak.hpp> | |
34 | # endif | |
35 | #define optional_HAVE_TWEAK_HEADER 1 | |
36 | #else | |
37 | #define optional_HAVE_TWEAK_HEADER 0 | |
38 | //# pragma message("optional.hpp: Note: Tweak header not supported.") | |
39 | #endif | |
40 | ||
41 | // optional selection and configuration: | |
42 | ||
43 | #if !defined( optional_CONFIG_SELECT_OPTIONAL ) | |
44 | # define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD ) | |
45 | #endif | |
46 | ||
47 | // Control presence of extensions: | |
48 | ||
49 | #ifndef optional_CONFIG_NO_EXTENSIONS | |
50 | #define optional_CONFIG_NO_EXTENSIONS 0 | |
51 | #endif | |
52 | ||
53 | // Control presence of exception handling (try and auto discover): | |
54 | ||
55 | #ifndef optional_CONFIG_NO_EXCEPTIONS | |
56 | # if defined(_MSC_VER) | |
57 | # include <cstddef> // for _HAS_EXCEPTIONS | |
58 | # endif | |
59 | # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) | |
60 | # define optional_CONFIG_NO_EXCEPTIONS 0 | |
61 | # else | |
62 | # define optional_CONFIG_NO_EXCEPTIONS 1 | |
63 | # endif | |
64 | #endif | |
65 | ||
66 | // C++ language version detection (C++20 is speculative): | |
67 | // Note: VC14.0/1900 (VS2015) lacks too much from C++14. | |
68 | ||
69 | #ifndef optional_CPLUSPLUS | |
70 | # if defined(_MSVC_LANG ) && !defined(__clang__) | |
71 | # define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) | |
72 | # else | |
73 | # define optional_CPLUSPLUS __cplusplus | |
74 | # endif | |
75 | #endif | |
76 | ||
77 | #define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L ) | |
78 | #define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L ) | |
79 | #define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L ) | |
80 | #define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L ) | |
81 | #define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L ) | |
82 | #define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L ) | |
83 | ||
84 | // C++ language version (represent 98 as 3): | |
85 | ||
86 | #define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) ) | |
87 | ||
88 | // Use C++17 std::optional if available and requested: | |
89 | ||
90 | #if optional_CPP17_OR_GREATER && defined(__has_include ) | |
91 | # if __has_include( <optional> ) | |
92 | # define optional_HAVE_STD_OPTIONAL 1 | |
93 | # else | |
94 | # define optional_HAVE_STD_OPTIONAL 0 | |
95 | # endif | |
96 | #else | |
97 | # define optional_HAVE_STD_OPTIONAL 0 | |
98 | #endif | |
99 | ||
100 | #define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) ) | |
101 | ||
102 | // | |
103 | // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite: | |
104 | // | |
105 | ||
106 | #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES | |
107 | #define nonstd_lite_HAVE_IN_PLACE_TYPES 1 | |
108 | ||
109 | // C++17 std::in_place in <utility>: | |
110 | ||
111 | #if optional_CPP17_OR_GREATER | |
112 | ||
113 | #include <utility> | |
114 | ||
115 | namespace nonstd { | |
116 | ||
117 | using std::in_place; | |
118 | using std::in_place_type; | |
119 | using std::in_place_index; | |
120 | using std::in_place_t; | |
121 | using std::in_place_type_t; | |
122 | using std::in_place_index_t; | |
123 | ||
124 | #define nonstd_lite_in_place_t( T) std::in_place_t | |
125 | #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T> | |
126 | #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K> | |
127 | ||
128 | #define nonstd_lite_in_place( T) std::in_place_t{} | |
129 | #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{} | |
130 | #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{} | |
131 | ||
132 | } // namespace nonstd | |
133 | ||
134 | #else // optional_CPP17_OR_GREATER | |
135 | ||
136 | #include <cstddef> | |
137 | ||
138 | namespace nonstd { | |
139 | namespace detail { | |
140 | ||
141 | template< class T > | |
142 | struct in_place_type_tag {}; | |
143 | ||
144 | template< std::size_t K > | |
145 | struct in_place_index_tag {}; | |
146 | ||
147 | } // namespace detail | |
148 | ||
149 | struct in_place_t {}; | |
150 | ||
151 | template< class T > | |
152 | inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() ) | |
153 | { | |
154 | return in_place_t(); | |
155 | } | |
156 | ||
157 | template< std::size_t K > | |
158 | inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() ) | |
159 | { | |
160 | return in_place_t(); | |
161 | } | |
162 | ||
163 | template< class T > | |
164 | inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() ) | |
165 | { | |
166 | return in_place_t(); | |
167 | } | |
168 | ||
169 | template< std::size_t K > | |
170 | inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() ) | |
171 | { | |
172 | return in_place_t(); | |
173 | } | |
174 | ||
175 | // mimic templated typedef: | |
176 | ||
177 | #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) | |
178 | #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) | |
179 | #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> ) | |
180 | ||
181 | #define nonstd_lite_in_place( T) nonstd::in_place_type<T> | |
182 | #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T> | |
183 | #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K> | |
184 | ||
185 | } // namespace nonstd | |
186 | ||
187 | #endif // optional_CPP17_OR_GREATER | |
188 | #endif // nonstd_lite_HAVE_IN_PLACE_TYPES | |
189 | ||
190 | // | |
191 | // Using std::optional: | |
192 | // | |
193 | ||
194 | #if optional_USES_STD_OPTIONAL | |
195 | ||
196 | #include <optional> | |
197 | ||
198 | namespace nonstd { | |
199 | ||
200 | using std::optional; | |
201 | using std::bad_optional_access; | |
202 | using std::hash; | |
203 | ||
204 | using std::nullopt; | |
205 | using std::nullopt_t; | |
206 | ||
207 | using std::operator==; | |
208 | using std::operator!=; | |
209 | using std::operator<; | |
210 | using std::operator<=; | |
211 | using std::operator>; | |
212 | using std::operator>=; | |
213 | using std::make_optional; | |
214 | using std::swap; | |
215 | } | |
216 | ||
217 | #else // optional_USES_STD_OPTIONAL | |
218 | ||
219 | #include <cassert> | |
220 | #include <utility> | |
221 | ||
222 | // optional-lite alignment configuration: | |
223 | ||
224 | #ifndef optional_CONFIG_MAX_ALIGN_HACK | |
225 | # define optional_CONFIG_MAX_ALIGN_HACK 0 | |
226 | #endif | |
227 | ||
228 | #ifndef optional_CONFIG_ALIGN_AS | |
229 | // no default, used in #if defined() | |
230 | #endif | |
231 | ||
232 | #ifndef optional_CONFIG_ALIGN_AS_FALLBACK | |
233 | # define optional_CONFIG_ALIGN_AS_FALLBACK double | |
234 | #endif | |
235 | ||
236 | // Compiler warning suppression: | |
237 | ||
238 | #if defined(__clang__) | |
239 | # pragma clang diagnostic push | |
240 | # pragma clang diagnostic ignored "-Wundef" | |
241 | #elif defined(__GNUC__) | |
242 | # pragma GCC diagnostic push | |
243 | # pragma GCC diagnostic ignored "-Wundef" | |
244 | #elif defined(_MSC_VER ) | |
245 | # pragma warning( push ) | |
246 | #endif | |
247 | ||
248 | // half-open range [lo..hi): | |
249 | #define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) | |
250 | ||
251 | // Compiler versions: | |
252 | // | |
253 | // MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) | |
254 | // MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) | |
255 | // MSVC++ 7.1 _MSC_VER == 1310 optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) | |
256 | // MSVC++ 8.0 _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) | |
257 | // MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) | |
258 | // MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) | |
259 | // MSVC++ 11.0 _MSC_VER == 1700 optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) | |
260 | // MSVC++ 12.0 _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) | |
261 | // MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) | |
262 | // MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) | |
263 | // MSVC++ 14.2 _MSC_VER >= 1920 optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) | |
264 | ||
265 | #if defined(_MSC_VER ) && !defined(__clang__) | |
266 | # define optional_COMPILER_MSVC_VER (_MSC_VER ) | |
267 | # define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) | |
268 | #else | |
269 | # define optional_COMPILER_MSVC_VER 0 | |
270 | # define optional_COMPILER_MSVC_VERSION 0 | |
271 | #endif | |
272 | ||
273 | #define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) ) | |
274 | ||
275 | #if defined(__GNUC__) && !defined(__clang__) | |
276 | # define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) | |
277 | #else | |
278 | # define optional_COMPILER_GNUC_VERSION 0 | |
279 | #endif | |
280 | ||
281 | #if defined(__clang__) | |
282 | # define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) | |
283 | #else | |
284 | # define optional_COMPILER_CLANG_VERSION 0 | |
285 | #endif | |
286 | ||
287 | #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 ) | |
288 | # pragma warning( disable: 4345 ) // initialization behavior changed | |
289 | #endif | |
290 | ||
291 | #if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 ) | |
292 | # pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const' | |
293 | #endif | |
294 | ||
295 | // Presence of language and library features: | |
296 | ||
297 | #define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE ) | |
298 | ||
299 | #ifdef _HAS_CPP0X | |
300 | # define optional_HAS_CPP0X _HAS_CPP0X | |
301 | #else | |
302 | # define optional_HAS_CPP0X 0 | |
303 | #endif | |
304 | ||
305 | // Unless defined otherwise below, consider VC14 as C++11 for optional-lite: | |
306 | ||
307 | #if optional_COMPILER_MSVC_VER >= 1900 | |
308 | # undef optional_CPP11_OR_GREATER | |
309 | # define optional_CPP11_OR_GREATER 1 | |
310 | #endif | |
311 | ||
312 | #define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500) | |
313 | #define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600) | |
314 | #define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700) | |
315 | #define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800) | |
316 | #define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900) | |
317 | #define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910) | |
318 | ||
319 | #define optional_CPP14_000 (optional_CPP14_OR_GREATER) | |
320 | #define optional_CPP17_000 (optional_CPP17_OR_GREATER) | |
321 | ||
322 | // clang >= 2.9, gcc >= 4.9, msvc >= vc14.0/1900 (vs15): | |
323 | #define optional_CPP11_140_C290_G490 ((optional_CPP11_OR_GREATER_ && (optional_COMPILER_CLANG_VERSION >= 290 || optional_COMPILER_GNUC_VERSION >= 490)) || (optional_COMPILER_MSVC_VER >= 1900)) | |
324 | ||
325 | // clang >= 3.5, msvc >= vc11 (vs12): | |
326 | #define optional_CPP11_110_C350 ( optional_CPP11_110 && !optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) ) | |
327 | ||
328 | // clang >= 3.5, gcc >= 5.0, msvc >= vc11 (vs12): | |
329 | #define optional_CPP11_110_C350_G500 \ | |
330 | ( optional_CPP11_110 && \ | |
331 | !( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \ | |
332 | || optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) ) | |
333 | ||
334 | // Presence of C++11 language features: | |
335 | ||
336 | #define optional_HAVE_CONSTEXPR_11 optional_CPP11_140 | |
337 | #define optional_HAVE_IS_DEFAULT optional_CPP11_140 | |
338 | #define optional_HAVE_NOEXCEPT optional_CPP11_140 | |
339 | #define optional_HAVE_NULLPTR optional_CPP11_100 | |
340 | #define optional_HAVE_REF_QUALIFIER optional_CPP11_140_C290_G490 | |
341 | #define optional_HAVE_STATIC_ASSERT optional_CPP11_110 | |
342 | #define optional_HAVE_INITIALIZER_LIST optional_CPP11_140 | |
343 | ||
344 | // Presence of C++14 language features: | |
345 | ||
346 | #define optional_HAVE_CONSTEXPR_14 optional_CPP14_000 | |
347 | ||
348 | // Presence of C++17 language features: | |
349 | ||
350 | #define optional_HAVE_NODISCARD optional_CPP17_000 | |
351 | ||
352 | // Presence of C++ library features: | |
353 | ||
354 | #define optional_HAVE_CONDITIONAL optional_CPP11_120 | |
355 | #define optional_HAVE_REMOVE_CV optional_CPP11_120 | |
356 | #define optional_HAVE_TYPE_TRAITS optional_CPP11_90 | |
357 | ||
358 | #define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION ) | |
359 | #define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION ) | |
360 | ||
361 | #define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110_C350 | |
362 | #define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350 | |
363 | #define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110_C350 | |
364 | #define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350 | |
365 | #define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_CPP11_110_C350_G500 | |
366 | #define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_CPP11_110_C350_G500 | |
367 | ||
368 | // C++ feature usage: | |
369 | ||
370 | #if optional_HAVE( CONSTEXPR_11 ) | |
371 | # define optional_constexpr constexpr | |
372 | #else | |
373 | # define optional_constexpr /*constexpr*/ | |
374 | #endif | |
375 | ||
376 | #if optional_HAVE( IS_DEFAULT ) | |
377 | # define optional_is_default = default; | |
378 | #else | |
379 | # define optional_is_default {} | |
380 | #endif | |
381 | ||
382 | #if optional_HAVE( CONSTEXPR_14 ) | |
383 | # define optional_constexpr14 constexpr | |
384 | #else | |
385 | # define optional_constexpr14 /*constexpr*/ | |
386 | #endif | |
387 | ||
388 | #if optional_HAVE( NODISCARD ) | |
389 | # define optional_nodiscard [[nodiscard]] | |
390 | #else | |
391 | # define optional_nodiscard /*[[nodiscard]]*/ | |
392 | #endif | |
393 | ||
394 | #if optional_HAVE( NOEXCEPT ) | |
395 | # define optional_noexcept noexcept | |
396 | #else | |
397 | # define optional_noexcept /*noexcept*/ | |
398 | #endif | |
399 | ||
400 | #if optional_HAVE( NULLPTR ) | |
401 | # define optional_nullptr nullptr | |
402 | #else | |
403 | # define optional_nullptr NULL | |
404 | #endif | |
405 | ||
406 | #if optional_HAVE( REF_QUALIFIER ) | |
407 | // NOLINTNEXTLINE( bugprone-macro-parentheses ) | |
408 | # define optional_ref_qual & | |
409 | # define optional_refref_qual && | |
410 | #else | |
411 | # define optional_ref_qual /*&*/ | |
412 | # define optional_refref_qual /*&&*/ | |
413 | #endif | |
414 | ||
415 | #if optional_HAVE( STATIC_ASSERT ) | |
416 | # define optional_static_assert(expr, text) static_assert(expr, text); | |
417 | #else | |
418 | # define optional_static_assert(expr, text) /*static_assert(expr, text);*/ | |
419 | #endif | |
420 | ||
421 | // additional includes: | |
422 | ||
423 | #if optional_CONFIG_NO_EXCEPTIONS | |
424 | // already included: <cassert> | |
425 | #else | |
426 | # include <stdexcept> | |
427 | #endif | |
428 | ||
429 | #if optional_CPP11_OR_GREATER | |
430 | # include <functional> | |
431 | #endif | |
432 | ||
433 | #if optional_HAVE( INITIALIZER_LIST ) | |
434 | # include <initializer_list> | |
435 | #endif | |
436 | ||
437 | #if optional_HAVE( TYPE_TRAITS ) | |
438 | # include <type_traits> | |
439 | #elif optional_HAVE( TR1_TYPE_TRAITS ) | |
440 | # include <tr1/type_traits> | |
441 | #endif | |
442 | ||
443 | // Method enabling | |
444 | ||
445 | #if optional_CPP11_OR_GREATER | |
446 | ||
447 | #define optional_REQUIRES_0(...) \ | |
448 | template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 > | |
449 | ||
450 | #define optional_REQUIRES_T(...) \ | |
451 | , typename std::enable_if< (__VA_ARGS__), int >::type = 0 | |
452 | ||
453 | #define optional_REQUIRES_R(R, ...) \ | |
454 | typename std::enable_if< (__VA_ARGS__), R>::type | |
455 | ||
456 | #define optional_REQUIRES_A(...) \ | |
457 | , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr | |
458 | ||
459 | #endif | |
460 | ||
461 | // | |
462 | // optional: | |
463 | // | |
464 | ||
465 | namespace nonstd { namespace optional_lite { | |
466 | ||
467 | namespace std11 { | |
468 | ||
469 | template< class T, T v > struct integral_constant { enum { value = v }; }; | |
470 | template< bool B > struct bool_constant : integral_constant<bool, B>{}; | |
471 | ||
472 | typedef bool_constant< true > true_type; | |
473 | typedef bool_constant< false > false_type; | |
474 | ||
475 | #if optional_CPP11_OR_GREATER | |
476 | using std::move; | |
477 | #else | |
478 | template< typename T > T & move( T & t ) { return t; } | |
479 | #endif | |
480 | ||
481 | #if optional_HAVE( CONDITIONAL ) | |
482 | using std::conditional; | |
483 | #else | |
484 | template< bool B, typename T, typename F > struct conditional { typedef T type; }; | |
485 | template< typename T, typename F > struct conditional<false, T, F> { typedef F type; }; | |
486 | #endif // optional_HAVE_CONDITIONAL | |
487 | ||
488 | #if optional_HAVE( IS_ASSIGNABLE ) | |
489 | using std::is_assignable; | |
490 | #else | |
491 | template< class T, class U > struct is_assignable : std11::true_type{}; | |
492 | #endif | |
493 | ||
494 | #if optional_HAVE( IS_MOVE_CONSTRUCTIBLE ) | |
495 | using std::is_move_constructible; | |
496 | #else | |
497 | template< class T > struct is_move_constructible : std11::true_type{}; | |
498 | #endif | |
499 | ||
500 | #if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE ) | |
501 | using std::is_nothrow_move_assignable; | |
502 | #else | |
503 | template< class T > struct is_nothrow_move_assignable : std11::true_type{}; | |
504 | #endif | |
505 | ||
506 | #if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE ) | |
507 | using std::is_nothrow_move_constructible; | |
508 | #else | |
509 | template< class T > struct is_nothrow_move_constructible : std11::true_type{}; | |
510 | #endif | |
511 | ||
512 | #if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE ) | |
513 | using std::is_trivially_copy_constructible; | |
514 | #else | |
515 | template< class T > struct is_trivially_copy_constructible : std11::true_type{}; | |
516 | #endif | |
517 | ||
518 | #if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE ) | |
519 | using std::is_trivially_move_constructible; | |
520 | #else | |
521 | template< class T > struct is_trivially_move_constructible : std11::true_type{}; | |
522 | #endif | |
523 | ||
524 | } // namespace std11 | |
525 | ||
526 | #if optional_CPP11_OR_GREATER | |
527 | ||
528 | /// type traits C++17: | |
529 | ||
530 | namespace std17 { | |
531 | ||
532 | #if optional_CPP17_OR_GREATER | |
533 | ||
534 | using std::is_swappable; | |
535 | using std::is_nothrow_swappable; | |
536 | ||
537 | #elif optional_CPP11_OR_GREATER | |
538 | ||
539 | namespace detail { | |
540 | ||
541 | using std::swap; | |
542 | ||
543 | struct is_swappable | |
544 | { | |
545 | template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) > | |
546 | static std11::true_type test( int /*unused*/ ); | |
547 | ||
548 | template< typename > | |
549 | static std11::false_type test(...); | |
550 | }; | |
551 | ||
552 | struct is_nothrow_swappable | |
553 | { | |
554 | // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015): | |
555 | ||
556 | template< typename T > | |
557 | static constexpr bool satisfies() | |
558 | { | |
559 | return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) ); | |
560 | } | |
561 | ||
562 | template< typename T > | |
563 | static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{} | |
564 | ||
565 | template< typename > | |
566 | static auto test(...) -> std11::false_type; | |
567 | }; | |
568 | ||
569 | } // namespace detail | |
570 | ||
571 | // is [nothow] swappable: | |
572 | ||
573 | template< typename T > | |
574 | struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){}; | |
575 | ||
576 | template< typename T > | |
577 | struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){}; | |
578 | ||
579 | #endif // optional_CPP17_OR_GREATER | |
580 | ||
581 | } // namespace std17 | |
582 | ||
583 | /// type traits C++20: | |
584 | ||
585 | namespace std20 { | |
586 | ||
587 | template< typename T > | |
588 | struct remove_cvref | |
589 | { | |
590 | typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type; | |
591 | }; | |
592 | ||
593 | } // namespace std20 | |
594 | ||
595 | #endif // optional_CPP11_OR_GREATER | |
596 | ||
597 | /// class optional | |
598 | ||
599 | template< typename T > | |
600 | class optional; | |
601 | ||
602 | namespace detail { | |
603 | ||
604 | // C++11 emulation: | |
605 | ||
606 | struct nulltype{}; | |
607 | ||
608 | template< typename Head, typename Tail > | |
609 | struct typelist | |
610 | { | |
611 | typedef Head head; | |
612 | typedef Tail tail; | |
613 | }; | |
614 | ||
615 | #if optional_CONFIG_MAX_ALIGN_HACK | |
616 | ||
617 | // Max align, use most restricted type for alignment: | |
618 | ||
619 | #define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ ) | |
620 | #define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line ) | |
621 | #define optional_UNIQUE3( name, line ) name ## line | |
622 | ||
623 | #define optional_ALIGN_TYPE( type ) \ | |
624 | type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st ) | |
625 | ||
626 | template< typename T > | |
627 | struct struct_t { T _; }; | |
628 | ||
629 | union max_align_t | |
630 | { | |
631 | optional_ALIGN_TYPE( char ); | |
632 | optional_ALIGN_TYPE( short int ); | |
633 | optional_ALIGN_TYPE( int ); | |
634 | optional_ALIGN_TYPE( long int ); | |
635 | optional_ALIGN_TYPE( float ); | |
636 | optional_ALIGN_TYPE( double ); | |
637 | optional_ALIGN_TYPE( long double ); | |
638 | optional_ALIGN_TYPE( char * ); | |
639 | optional_ALIGN_TYPE( short int * ); | |
640 | optional_ALIGN_TYPE( int * ); | |
641 | optional_ALIGN_TYPE( long int * ); | |
642 | optional_ALIGN_TYPE( float * ); | |
643 | optional_ALIGN_TYPE( double * ); | |
644 | optional_ALIGN_TYPE( long double * ); | |
645 | optional_ALIGN_TYPE( void * ); | |
646 | ||
647 | #ifdef HAVE_LONG_LONG | |
648 | optional_ALIGN_TYPE( long long ); | |
649 | #endif | |
650 | ||
651 | struct Unknown; | |
652 | ||
653 | Unknown ( * optional_UNIQUE(_) )( Unknown ); | |
654 | Unknown * Unknown::* optional_UNIQUE(_); | |
655 | Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown ); | |
656 | ||
657 | struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_); | |
658 | struct_t< Unknown * Unknown::* > optional_UNIQUE(_); | |
659 | struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_); | |
660 | }; | |
661 | ||
662 | #undef optional_UNIQUE | |
663 | #undef optional_UNIQUE2 | |
664 | #undef optional_UNIQUE3 | |
665 | ||
666 | #undef optional_ALIGN_TYPE | |
667 | ||
668 | #elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK | |
669 | ||
670 | // Use user-specified type for alignment: | |
671 | ||
672 | #define optional_ALIGN_AS( unused ) \ | |
673 | optional_CONFIG_ALIGN_AS | |
674 | ||
675 | #else // optional_CONFIG_MAX_ALIGN_HACK | |
676 | ||
677 | // Determine POD type to use for alignment: | |
678 | ||
679 | #define optional_ALIGN_AS( to_align ) \ | |
680 | typename type_of_size< alignment_types, alignment_of< to_align >::value >::type | |
681 | ||
682 | template< typename T > | |
683 | struct alignment_of; | |
684 | ||
685 | template< typename T > | |
686 | struct alignment_of_hack | |
687 | { | |
688 | char c; | |
689 | T t; | |
690 | alignment_of_hack(); | |
691 | }; | |
692 | ||
693 | template< size_t A, size_t S > | |
694 | struct alignment_logic | |
695 | { | |
696 | enum { value = A < S ? A : S }; | |
697 | }; | |
698 | ||
699 | template< typename T > | |
700 | struct alignment_of | |
701 | { | |
702 | enum { value = alignment_logic< | |
703 | sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value }; | |
704 | }; | |
705 | ||
706 | template< typename List, size_t N > | |
707 | struct type_of_size | |
708 | { | |
709 | typedef typename std11::conditional< | |
710 | N == sizeof( typename List::head ), | |
711 | typename List::head, | |
712 | typename type_of_size<typename List::tail, N >::type >::type type; | |
713 | }; | |
714 | ||
715 | template< size_t N > | |
716 | struct type_of_size< nulltype, N > | |
717 | { | |
718 | typedef optional_CONFIG_ALIGN_AS_FALLBACK type; | |
719 | }; | |
720 | ||
721 | template< typename T> | |
722 | struct struct_t { T _; }; | |
723 | ||
724 | #define optional_ALIGN_TYPE( type ) \ | |
725 | typelist< type , typelist< struct_t< type > | |
726 | ||
727 | struct Unknown; | |
728 | ||
729 | typedef | |
730 | optional_ALIGN_TYPE( char ), | |
731 | optional_ALIGN_TYPE( short ), | |
732 | optional_ALIGN_TYPE( int ), | |
733 | optional_ALIGN_TYPE( long ), | |
734 | optional_ALIGN_TYPE( float ), | |
735 | optional_ALIGN_TYPE( double ), | |
736 | optional_ALIGN_TYPE( long double ), | |
737 | ||
738 | optional_ALIGN_TYPE( char *), | |
739 | optional_ALIGN_TYPE( short * ), | |
740 | optional_ALIGN_TYPE( int * ), | |
741 | optional_ALIGN_TYPE( long * ), | |
742 | optional_ALIGN_TYPE( float * ), | |
743 | optional_ALIGN_TYPE( double * ), | |
744 | optional_ALIGN_TYPE( long double * ), | |
745 | ||
746 | optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ), | |
747 | optional_ALIGN_TYPE( Unknown * Unknown::* ), | |
748 | optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ), | |
749 | ||
750 | nulltype | |
751 | > > > > > > > > > > > > > > | |
752 | > > > > > > > > > > > > > > | |
753 | > > > > > > | |
754 | alignment_types; | |
755 | ||
756 | #undef optional_ALIGN_TYPE | |
757 | ||
758 | #endif // optional_CONFIG_MAX_ALIGN_HACK | |
759 | ||
760 | /// C++03 constructed union to hold value. | |
761 | ||
762 | template< typename T > | |
763 | union storage_t | |
764 | { | |
765 | //private: | |
766 | // template< typename > friend class optional; | |
767 | ||
768 | typedef T value_type; | |
769 | ||
770 | storage_t() optional_is_default | |
771 | ||
772 | explicit storage_t( value_type const & v ) | |
773 | { | |
774 | construct_value( v ); | |
775 | } | |
776 | ||
777 | void construct_value( value_type const & v ) | |
778 | { | |
779 | ::new( value_ptr() ) value_type( v ); | |
780 | } | |
781 | ||
782 | #if optional_CPP11_OR_GREATER | |
783 | ||
784 | explicit storage_t( value_type && v ) | |
785 | { | |
786 | construct_value( std::move( v ) ); | |
787 | } | |
788 | ||
789 | void construct_value( value_type && v ) | |
790 | { | |
791 | ::new( value_ptr() ) value_type( std::move( v ) ); | |
792 | } | |
793 | ||
794 | template< class... Args > | |
795 | storage_t( nonstd_lite_in_place_t(T), Args&&... args ) | |
796 | { | |
797 | emplace( std::forward<Args>(args)... ); | |
798 | } | |
799 | ||
800 | template< class... Args > | |
801 | void emplace( Args&&... args ) | |
802 | { | |
803 | ::new( value_ptr() ) value_type( std::forward<Args>(args)... ); | |
804 | } | |
805 | ||
806 | template< class U, class... Args > | |
807 | void emplace( std::initializer_list<U> il, Args&&... args ) | |
808 | { | |
809 | ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... ); | |
810 | } | |
811 | ||
812 | #endif | |
813 | ||
814 | void destruct_value() | |
815 | { | |
816 | value_ptr()->~T(); | |
817 | } | |
818 | ||
819 | optional_nodiscard value_type const * value_ptr() const | |
820 | { | |
821 | return as<value_type>(); | |
822 | } | |
823 | ||
824 | value_type * value_ptr() | |
825 | { | |
826 | return as<value_type>(); | |
827 | } | |
828 | ||
829 | optional_nodiscard value_type const & value() const optional_ref_qual | |
830 | { | |
831 | return * value_ptr(); | |
832 | } | |
833 | ||
834 | value_type & value() optional_ref_qual | |
835 | { | |
836 | return * value_ptr(); | |
837 | } | |
838 | ||
839 | #if optional_HAVE( REF_QUALIFIER ) | |
840 | ||
841 | optional_nodiscard value_type const && value() const optional_refref_qual | |
842 | { | |
843 | return std::move( value() ); | |
844 | } | |
845 | ||
846 | value_type && value() optional_refref_qual | |
847 | { | |
848 | return std::move( value() ); | |
849 | } | |
850 | ||
851 | #endif | |
852 | ||
853 | #if optional_CPP11_OR_GREATER | |
854 | ||
855 | using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type; | |
856 | aligned_storage_t data; | |
857 | ||
858 | #elif optional_CONFIG_MAX_ALIGN_HACK | |
859 | ||
860 | typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t; | |
861 | ||
862 | max_align_t hack; | |
863 | aligned_storage_t data; | |
864 | ||
865 | #else | |
866 | typedef optional_ALIGN_AS(value_type) align_as_type; | |
867 | ||
868 | typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t; | |
869 | aligned_storage_t data; | |
870 | ||
871 | # undef optional_ALIGN_AS | |
872 | ||
873 | #endif // optional_CONFIG_MAX_ALIGN_HACK | |
874 | ||
875 | optional_nodiscard void * ptr() optional_noexcept | |
876 | { | |
877 | return &data; | |
878 | } | |
879 | ||
880 | optional_nodiscard void const * ptr() const optional_noexcept | |
881 | { | |
882 | return &data; | |
883 | } | |
884 | ||
885 | template <typename U> | |
886 | optional_nodiscard U * as() | |
887 | { | |
888 | return reinterpret_cast<U*>( ptr() ); | |
889 | } | |
890 | ||
891 | template <typename U> | |
892 | optional_nodiscard U const * as() const | |
893 | { | |
894 | return reinterpret_cast<U const *>( ptr() ); | |
895 | } | |
896 | }; | |
897 | ||
898 | } // namespace detail | |
899 | ||
900 | /// disengaged state tag | |
901 | ||
902 | struct nullopt_t | |
903 | { | |
904 | struct init{}; | |
905 | explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {} | |
906 | }; | |
907 | ||
908 | #if optional_HAVE( CONSTEXPR_11 ) | |
909 | constexpr nullopt_t nullopt{ nullopt_t::init{} }; | |
910 | #else | |
911 | // extra parenthesis to prevent the most vexing parse: | |
912 | const nullopt_t nullopt(( nullopt_t::init() )); | |
913 | #endif | |
914 | ||
915 | /// optional access error | |
916 | ||
917 | #if ! optional_CONFIG_NO_EXCEPTIONS | |
918 | ||
919 | class bad_optional_access : public std::logic_error | |
920 | { | |
921 | public: | |
922 | explicit bad_optional_access() | |
923 | : logic_error( "bad optional access" ) {} | |
924 | }; | |
925 | ||
926 | #endif //optional_CONFIG_NO_EXCEPTIONS | |
927 | ||
928 | /// optional | |
929 | ||
930 | template< typename T> | |
931 | class optional | |
932 | { | |
933 | optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value ), | |
934 | "T in optional<T> must not be of type 'nullopt_t'.") | |
935 | ||
936 | optional_static_assert(( !std::is_same<typename std::remove_cv<T>::type, in_place_t>::value ), | |
937 | "T in optional<T> must not be of type 'in_place_t'.") | |
938 | ||
939 | optional_static_assert(( std::is_object<T>::value && std::is_destructible<T>::value && !std::is_array<T>::value ), | |
940 | "T in optional<T> must meet the Cpp17Destructible requirements.") | |
941 | ||
942 | private: | |
943 | template< typename > friend class optional; | |
944 | ||
945 | typedef void (optional::*safe_bool)() const; | |
946 | ||
947 | public: | |
948 | typedef T value_type; | |
949 | ||
950 | // x.x.3.1, constructors | |
951 | ||
952 | // 1a - default construct | |
953 | optional_constexpr optional() optional_noexcept | |
954 | : has_value_( false ) | |
955 | , contained() | |
956 | {} | |
957 | ||
958 | // 1b - construct explicitly empty | |
959 | // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) | |
960 | optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept | |
961 | : has_value_( false ) | |
962 | , contained() | |
963 | {} | |
964 | ||
965 | // 2 - copy-construct | |
966 | #if optional_CPP11_OR_GREATER | |
967 | // template< typename U = T | |
968 | // optional_REQUIRES_T( | |
969 | // std::is_copy_constructible<U>::value | |
970 | // || std11::is_trivially_copy_constructible<U>::value | |
971 | // ) | |
972 | // > | |
973 | #endif | |
974 | optional_constexpr14 optional( optional const & other ) | |
975 | : has_value_( other.has_value() ) | |
976 | { | |
977 | if ( other.has_value() ) | |
978 | { | |
979 | contained.construct_value( other.contained.value() ); | |
980 | } | |
981 | } | |
982 | ||
983 | #if optional_CPP11_OR_GREATER | |
984 | ||
985 | // 3 (C++11) - move-construct from optional | |
986 | template< typename U = T | |
987 | optional_REQUIRES_T( | |
988 | std11::is_move_constructible<U>::value | |
989 | || std11::is_trivially_move_constructible<U>::value | |
990 | ) | |
991 | > | |
992 | optional_constexpr14 optional( optional && other ) | |
993 | // NOLINTNEXTLINE( performance-noexcept-move-constructor ) | |
994 | noexcept( std11::is_nothrow_move_constructible<T>::value ) | |
995 | : has_value_( other.has_value() ) | |
996 | { | |
997 | if ( other.has_value() ) | |
998 | { | |
999 | contained.construct_value( std::move( other.contained.value() ) ); | |
1000 | } | |
1001 | } | |
1002 | ||
1003 | // 4a (C++11) - explicit converting copy-construct from optional | |
1004 | template< typename U | |
1005 | optional_REQUIRES_T( | |
1006 | std::is_constructible<T, U const &>::value | |
1007 | && !std::is_constructible<T, optional<U> & >::value | |
1008 | && !std::is_constructible<T, optional<U> && >::value | |
1009 | && !std::is_constructible<T, optional<U> const & >::value | |
1010 | && !std::is_constructible<T, optional<U> const && >::value | |
1011 | && !std::is_convertible< optional<U> & , T>::value | |
1012 | && !std::is_convertible< optional<U> && , T>::value | |
1013 | && !std::is_convertible< optional<U> const & , T>::value | |
1014 | && !std::is_convertible< optional<U> const &&, T>::value | |
1015 | && !std::is_convertible< U const & , T>::value /*=> explicit */ | |
1016 | ) | |
1017 | > | |
1018 | explicit optional( optional<U> const & other ) | |
1019 | : has_value_( other.has_value() ) | |
1020 | { | |
1021 | if ( other.has_value() ) | |
1022 | { | |
1023 | contained.construct_value( T{ other.contained.value() } ); | |
1024 | } | |
1025 | } | |
1026 | #endif // optional_CPP11_OR_GREATER | |
1027 | ||
1028 | // 4b (C++98 and later) - non-explicit converting copy-construct from optional | |
1029 | template< typename U | |
1030 | #if optional_CPP11_OR_GREATER | |
1031 | optional_REQUIRES_T( | |
1032 | std::is_constructible<T, U const &>::value | |
1033 | && !std::is_constructible<T, optional<U> & >::value | |
1034 | && !std::is_constructible<T, optional<U> && >::value | |
1035 | && !std::is_constructible<T, optional<U> const & >::value | |
1036 | && !std::is_constructible<T, optional<U> const && >::value | |
1037 | && !std::is_convertible< optional<U> & , T>::value | |
1038 | && !std::is_convertible< optional<U> && , T>::value | |
1039 | && !std::is_convertible< optional<U> const & , T>::value | |
1040 | && !std::is_convertible< optional<U> const &&, T>::value | |
1041 | && std::is_convertible< U const & , T>::value /*=> non-explicit */ | |
1042 | ) | |
1043 | #endif // optional_CPP11_OR_GREATER | |
1044 | > | |
1045 | // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) | |
1046 | /*non-explicit*/ optional( optional<U> const & other ) | |
1047 | : has_value_( other.has_value() ) | |
1048 | { | |
1049 | if ( other.has_value() ) | |
1050 | { | |
1051 | contained.construct_value( other.contained.value() ); | |
1052 | } | |
1053 | } | |
1054 | ||
1055 | #if optional_CPP11_OR_GREATER | |
1056 | ||
1057 | // 5a (C++11) - explicit converting move-construct from optional | |
1058 | template< typename U | |
1059 | optional_REQUIRES_T( | |
1060 | std::is_constructible<T, U &&>::value | |
1061 | && !std::is_constructible<T, optional<U> & >::value | |
1062 | && !std::is_constructible<T, optional<U> && >::value | |
1063 | && !std::is_constructible<T, optional<U> const & >::value | |
1064 | && !std::is_constructible<T, optional<U> const && >::value | |
1065 | && !std::is_convertible< optional<U> & , T>::value | |
1066 | && !std::is_convertible< optional<U> && , T>::value | |
1067 | && !std::is_convertible< optional<U> const & , T>::value | |
1068 | && !std::is_convertible< optional<U> const &&, T>::value | |
1069 | && !std::is_convertible< U &&, T>::value /*=> explicit */ | |
1070 | ) | |
1071 | > | |
1072 | explicit optional( optional<U> && other | |
1073 | ) | |
1074 | : has_value_( other.has_value() ) | |
1075 | { | |
1076 | if ( other.has_value() ) | |
1077 | { | |
1078 | contained.construct_value( T{ std::move( other.contained.value() ) } ); | |
1079 | } | |
1080 | } | |
1081 | ||
1082 | // 5a (C++11) - non-explicit converting move-construct from optional | |
1083 | template< typename U | |
1084 | optional_REQUIRES_T( | |
1085 | std::is_constructible<T, U &&>::value | |
1086 | && !std::is_constructible<T, optional<U> & >::value | |
1087 | && !std::is_constructible<T, optional<U> && >::value | |
1088 | && !std::is_constructible<T, optional<U> const & >::value | |
1089 | && !std::is_constructible<T, optional<U> const && >::value | |
1090 | && !std::is_convertible< optional<U> & , T>::value | |
1091 | && !std::is_convertible< optional<U> && , T>::value | |
1092 | && !std::is_convertible< optional<U> const & , T>::value | |
1093 | && !std::is_convertible< optional<U> const &&, T>::value | |
1094 | && std::is_convertible< U &&, T>::value /*=> non-explicit */ | |
1095 | ) | |
1096 | > | |
1097 | // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) | |
1098 | /*non-explicit*/ optional( optional<U> && other ) | |
1099 | : has_value_( other.has_value() ) | |
1100 | { | |
1101 | if ( other.has_value() ) | |
1102 | { | |
1103 | contained.construct_value( std::move( other.contained.value() ) ); | |
1104 | } | |
1105 | } | |
1106 | ||
1107 | // 6 (C++11) - in-place construct | |
1108 | template< typename... Args | |
1109 | optional_REQUIRES_T( | |
1110 | std::is_constructible<T, Args&&...>::value | |
1111 | ) | |
1112 | > | |
1113 | optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args ) | |
1114 | : has_value_( true ) | |
1115 | , contained( in_place, std::forward<Args>(args)... ) | |
1116 | {} | |
1117 | ||
1118 | // 7 (C++11) - in-place construct, initializer-list | |
1119 | template< typename U, typename... Args | |
1120 | optional_REQUIRES_T( | |
1121 | std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value | |
1122 | ) | |
1123 | > | |
1124 | optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args ) | |
1125 | : has_value_( true ) | |
1126 | , contained( T( il, std::forward<Args>(args)...) ) | |
1127 | {} | |
1128 | ||
1129 | // 8a (C++11) - explicit move construct from value | |
1130 | template< typename U = T | |
1131 | optional_REQUIRES_T( | |
1132 | std::is_constructible<T, U&&>::value | |
1133 | && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value | |
1134 | && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value | |
1135 | && !std::is_convertible<U&&, T>::value /*=> explicit */ | |
1136 | ) | |
1137 | > | |
1138 | optional_constexpr explicit optional( U && value ) | |
1139 | : has_value_( true ) | |
1140 | , contained( nonstd_lite_in_place(T), std::forward<U>( value ) ) | |
1141 | {} | |
1142 | ||
1143 | // 8b (C++11) - non-explicit move construct from value | |
1144 | template< typename U = T | |
1145 | optional_REQUIRES_T( | |
1146 | std::is_constructible<T, U&&>::value | |
1147 | && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value | |
1148 | && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value | |
1149 | && std::is_convertible<U&&, T>::value /*=> non-explicit */ | |
1150 | ) | |
1151 | > | |
1152 | // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions ) | |
1153 | optional_constexpr /*non-explicit*/ optional( U && value ) | |
1154 | : has_value_( true ) | |
1155 | , contained( nonstd_lite_in_place(T), std::forward<U>( value ) ) | |
1156 | {} | |
1157 | ||
1158 | #else // optional_CPP11_OR_GREATER | |
1159 | ||
1160 | // 8 (C++98) | |
1161 | optional( value_type const & value ) | |
1162 | : has_value_( true ) | |
1163 | , contained( value ) | |
1164 | {} | |
1165 | ||
1166 | #endif // optional_CPP11_OR_GREATER | |
1167 | ||
1168 | // x.x.3.2, destructor | |
1169 | ||
1170 | ~optional() | |
1171 | { | |
1172 | if ( has_value() ) | |
1173 | { | |
1174 | contained.destruct_value(); | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | // x.x.3.3, assignment | |
1179 | ||
1180 | // 1 (C++98and later) - assign explicitly empty | |
1181 | optional & operator=( nullopt_t /*unused*/) optional_noexcept | |
1182 | { | |
1183 | reset(); | |
1184 | return *this; | |
1185 | } | |
1186 | ||
1187 | // 2 (C++98and later) - copy-assign from optional | |
1188 | #if optional_CPP11_OR_GREATER | |
1189 | // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) | |
1190 | optional_REQUIRES_R( | |
1191 | optional &, | |
1192 | true | |
1193 | // std::is_copy_constructible<T>::value | |
1194 | // && std::is_copy_assignable<T>::value | |
1195 | ) | |
1196 | operator=( optional const & other ) | |
1197 | noexcept( | |
1198 | std11::is_nothrow_move_assignable<T>::value | |
1199 | && std11::is_nothrow_move_constructible<T>::value | |
1200 | ) | |
1201 | #else | |
1202 | optional & operator=( optional const & other ) | |
1203 | #endif | |
1204 | { | |
1205 | if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); } | |
1206 | else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); } | |
1207 | else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; } | |
1208 | return *this; | |
1209 | } | |
1210 | ||
1211 | #if optional_CPP11_OR_GREATER | |
1212 | ||
1213 | // 3 (C++11) - move-assign from optional | |
1214 | // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) | |
1215 | optional_REQUIRES_R( | |
1216 | optional &, | |
1217 | true | |
1218 | // std11::is_move_constructible<T>::value | |
1219 | // && std::is_move_assignable<T>::value | |
1220 | ) | |
1221 | operator=( optional && other ) noexcept | |
1222 | { | |
1223 | if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); } | |
1224 | else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); } | |
1225 | else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); } | |
1226 | return *this; | |
1227 | } | |
1228 | ||
1229 | // 4 (C++11) - move-assign from value | |
1230 | template< typename U = T > | |
1231 | // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) | |
1232 | optional_REQUIRES_R( | |
1233 | optional &, | |
1234 | std::is_constructible<T , U>::value | |
1235 | && std11::is_assignable<T&, U>::value | |
1236 | && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value | |
1237 | && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value | |
1238 | && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value) | |
1239 | ) | |
1240 | operator=( U && value ) | |
1241 | { | |
1242 | if ( has_value() ) | |
1243 | { | |
1244 | contained.value() = std::forward<U>( value ); | |
1245 | } | |
1246 | else | |
1247 | { | |
1248 | initialize( T( std::forward<U>( value ) ) ); | |
1249 | } | |
1250 | return *this; | |
1251 | } | |
1252 | ||
1253 | #else // optional_CPP11_OR_GREATER | |
1254 | ||
1255 | // 4 (C++98) - copy-assign from value | |
1256 | template< typename U /*= T*/ > | |
1257 | optional & operator=( U const & value ) | |
1258 | { | |
1259 | if ( has_value() ) contained.value() = value; | |
1260 | else initialize( T( value ) ); | |
1261 | return *this; | |
1262 | } | |
1263 | ||
1264 | #endif // optional_CPP11_OR_GREATER | |
1265 | ||
1266 | // 5 (C++98 and later) - converting copy-assign from optional | |
1267 | template< typename U > | |
1268 | #if optional_CPP11_OR_GREATER | |
1269 | // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) | |
1270 | optional_REQUIRES_R( | |
1271 | optional&, | |
1272 | std::is_constructible< T , U const &>::value | |
1273 | && std11::is_assignable< T&, U const &>::value | |
1274 | && !std::is_constructible<T, optional<U> & >::value | |
1275 | && !std::is_constructible<T, optional<U> && >::value | |
1276 | && !std::is_constructible<T, optional<U> const & >::value | |
1277 | && !std::is_constructible<T, optional<U> const && >::value | |
1278 | && !std::is_convertible< optional<U> & , T>::value | |
1279 | && !std::is_convertible< optional<U> && , T>::value | |
1280 | && !std::is_convertible< optional<U> const & , T>::value | |
1281 | && !std::is_convertible< optional<U> const &&, T>::value | |
1282 | && !std11::is_assignable< T&, optional<U> & >::value | |
1283 | && !std11::is_assignable< T&, optional<U> && >::value | |
1284 | && !std11::is_assignable< T&, optional<U> const & >::value | |
1285 | && !std11::is_assignable< T&, optional<U> const && >::value | |
1286 | ) | |
1287 | #else | |
1288 | optional& | |
1289 | #endif // optional_CPP11_OR_GREATER | |
1290 | operator=( optional<U> const & other ) | |
1291 | { | |
1292 | return *this = optional( other ); | |
1293 | } | |
1294 | ||
1295 | #if optional_CPP11_OR_GREATER | |
1296 | ||
1297 | // 6 (C++11) - converting move-assign from optional | |
1298 | template< typename U > | |
1299 | // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator ) | |
1300 | optional_REQUIRES_R( | |
1301 | optional&, | |
1302 | std::is_constructible< T , U>::value | |
1303 | && std11::is_assignable< T&, U>::value | |
1304 | && !std::is_constructible<T, optional<U> & >::value | |
1305 | && !std::is_constructible<T, optional<U> && >::value | |
1306 | && !std::is_constructible<T, optional<U> const & >::value | |
1307 | && !std::is_constructible<T, optional<U> const && >::value | |
1308 | && !std::is_convertible< optional<U> & , T>::value | |
1309 | && !std::is_convertible< optional<U> && , T>::value | |
1310 | && !std::is_convertible< optional<U> const & , T>::value | |
1311 | && !std::is_convertible< optional<U> const &&, T>::value | |
1312 | && !std11::is_assignable< T&, optional<U> & >::value | |
1313 | && !std11::is_assignable< T&, optional<U> && >::value | |
1314 | && !std11::is_assignable< T&, optional<U> const & >::value | |
1315 | && !std11::is_assignable< T&, optional<U> const && >::value | |
1316 | ) | |
1317 | operator=( optional<U> && other ) | |
1318 | { | |
1319 | return *this = optional( std::move( other ) ); | |
1320 | } | |
1321 | ||
1322 | // 7 (C++11) - emplace | |
1323 | template< typename... Args | |
1324 | optional_REQUIRES_T( | |
1325 | std::is_constructible<T, Args&&...>::value | |
1326 | ) | |
1327 | > | |
1328 | T& emplace( Args&&... args ) | |
1329 | { | |
1330 | *this = nullopt; | |
1331 | contained.emplace( std::forward<Args>(args)... ); | |
1332 | has_value_ = true; | |
1333 | return contained.value(); | |
1334 | } | |
1335 | ||
1336 | // 8 (C++11) - emplace, initializer-list | |
1337 | template< typename U, typename... Args | |
1338 | optional_REQUIRES_T( | |
1339 | std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value | |
1340 | ) | |
1341 | > | |
1342 | T& emplace( std::initializer_list<U> il, Args&&... args ) | |
1343 | { | |
1344 | *this = nullopt; | |
1345 | contained.emplace( il, std::forward<Args>(args)... ); | |
1346 | has_value_ = true; | |
1347 | return contained.value(); | |
1348 | } | |
1349 | ||
1350 | #endif // optional_CPP11_OR_GREATER | |
1351 | ||
1352 | // x.x.3.4, swap | |
1353 | ||
1354 | void swap( optional & other ) | |
1355 | #if optional_CPP11_OR_GREATER | |
1356 | noexcept( | |
1357 | std11::is_nothrow_move_constructible<T>::value | |
1358 | && std17::is_nothrow_swappable<T>::value | |
1359 | ) | |
1360 | #endif | |
1361 | { | |
1362 | using std::swap; | |
1363 | if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); } | |
1364 | else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); } | |
1365 | else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); } | |
1366 | } | |
1367 | ||
1368 | // x.x.3.5, observers | |
1369 | ||
1370 | optional_constexpr value_type const * operator ->() const | |
1371 | { | |
1372 | return assert( has_value() ), | |
1373 | contained.value_ptr(); | |
1374 | } | |
1375 | ||
1376 | optional_constexpr14 value_type * operator ->() | |
1377 | { | |
1378 | return assert( has_value() ), | |
1379 | contained.value_ptr(); | |
1380 | } | |
1381 | ||
1382 | optional_constexpr value_type const & operator *() const optional_ref_qual | |
1383 | { | |
1384 | return assert( has_value() ), | |
1385 | contained.value(); | |
1386 | } | |
1387 | ||
1388 | optional_constexpr14 value_type & operator *() optional_ref_qual | |
1389 | { | |
1390 | return assert( has_value() ), | |
1391 | contained.value(); | |
1392 | } | |
1393 | ||
1394 | #if optional_HAVE( REF_QUALIFIER ) | |
1395 | ||
1396 | optional_constexpr value_type const && operator *() const optional_refref_qual | |
1397 | { | |
1398 | return std::move( **this ); | |
1399 | } | |
1400 | ||
1401 | optional_constexpr14 value_type && operator *() optional_refref_qual | |
1402 | { | |
1403 | return std::move( **this ); | |
1404 | } | |
1405 | ||
1406 | #endif | |
1407 | ||
1408 | #if optional_CPP11_OR_GREATER | |
1409 | optional_constexpr explicit operator bool() const optional_noexcept | |
1410 | { | |
1411 | return has_value(); | |
1412 | } | |
1413 | #else | |
1414 | optional_constexpr operator safe_bool() const optional_noexcept | |
1415 | { | |
1416 | return has_value() ? &optional::this_type_does_not_support_comparisons : 0; | |
1417 | } | |
1418 | #endif | |
1419 | ||
1420 | // NOLINTNEXTLINE( modernize-use-nodiscard ) | |
1421 | /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept | |
1422 | { | |
1423 | return has_value_; | |
1424 | } | |
1425 | ||
1426 | // NOLINTNEXTLINE( modernize-use-nodiscard ) | |
1427 | /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual | |
1428 | { | |
1429 | #if optional_CONFIG_NO_EXCEPTIONS | |
1430 | assert( has_value() ); | |
1431 | #else | |
1432 | if ( ! has_value() ) | |
1433 | { | |
1434 | throw bad_optional_access(); | |
1435 | } | |
1436 | #endif | |
1437 | return contained.value(); | |
1438 | } | |
1439 | ||
1440 | optional_constexpr14 value_type & value() optional_ref_qual | |
1441 | { | |
1442 | #if optional_CONFIG_NO_EXCEPTIONS | |
1443 | assert( has_value() ); | |
1444 | #else | |
1445 | if ( ! has_value() ) | |
1446 | { | |
1447 | throw bad_optional_access(); | |
1448 | } | |
1449 | #endif | |
1450 | return contained.value(); | |
1451 | } | |
1452 | ||
1453 | #if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 ) | |
1454 | ||
1455 | // NOLINTNEXTLINE( modernize-use-nodiscard ) | |
1456 | /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual | |
1457 | { | |
1458 | return std::move( value() ); | |
1459 | } | |
1460 | ||
1461 | optional_constexpr14 value_type && value() optional_refref_qual | |
1462 | { | |
1463 | return std::move( value() ); | |
1464 | } | |
1465 | ||
1466 | #endif | |
1467 | ||
1468 | #if optional_HAVE( REF_QUALIFIER ) | |
1469 | ||
1470 | template< typename U > | |
1471 | optional_constexpr value_type value_or( U && v ) const optional_ref_qual | |
1472 | { | |
1473 | return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) ); | |
1474 | } | |
1475 | ||
1476 | template< typename U > | |
1477 | optional_constexpr14 value_type value_or( U && v ) optional_refref_qual | |
1478 | { | |
1479 | #if optional_COMPILER_CLANG_VERSION | |
1480 | return has_value() ? /*std::move*/( contained.value() ) : static_cast<T>(std::forward<U>( v ) ); | |
1481 | #else | |
1482 | return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) ); | |
1483 | #endif | |
1484 | } | |
1485 | ||
1486 | #else | |
1487 | ||
1488 | template< typename U > | |
1489 | optional_constexpr value_type value_or( U const & v ) const | |
1490 | { | |
1491 | return has_value() ? contained.value() : static_cast<value_type>( v ); | |
1492 | } | |
1493 | ||
1494 | #endif // optional_HAVE( REF_QUALIFIER ) | |
1495 | ||
1496 | #if !optional_CONFIG_NO_EXTENSIONS | |
1497 | #if optional_HAVE( REF_QUALIFIER ) | |
1498 | ||
1499 | template< typename F > | |
1500 | optional_constexpr value_type value_or_eval( F f ) const & | |
1501 | { | |
1502 | return has_value() ? contained.value() : f(); | |
1503 | } | |
1504 | ||
1505 | template< typename F > | |
1506 | optional_constexpr14 value_type value_or_eval( F f ) && | |
1507 | { | |
1508 | if ( has_value() ) | |
1509 | { | |
1510 | return std::move( contained.value() ); | |
1511 | } | |
1512 | else | |
1513 | { | |
1514 | return f(); | |
1515 | } | |
1516 | } | |
1517 | ||
1518 | #else | |
1519 | ||
1520 | template< typename F > | |
1521 | optional_constexpr value_type value_or_eval( F f ) const | |
1522 | { | |
1523 | return has_value() ? contained.value() : f(); | |
1524 | } | |
1525 | ||
1526 | #endif // optional_HAVE( REF_QUALIFIER ) | |
1527 | #endif // !optional_CONFIG_NO_EXTENSIONS | |
1528 | ||
1529 | // x.x.3.6, modifiers | |
1530 | ||
1531 | void reset() optional_noexcept | |
1532 | { | |
1533 | if ( has_value() ) | |
1534 | { | |
1535 | contained.destruct_value(); | |
1536 | } | |
1537 | ||
1538 | has_value_ = false; | |
1539 | } | |
1540 | ||
1541 | private: | |
1542 | void this_type_does_not_support_comparisons() const {} | |
1543 | ||
1544 | template< typename V > | |
1545 | void initialize( V const & value ) | |
1546 | { | |
1547 | assert( ! has_value() ); | |
1548 | contained.construct_value( value ); | |
1549 | has_value_ = true; | |
1550 | } | |
1551 | ||
1552 | #if optional_CPP11_OR_GREATER | |
1553 | template< typename V > | |
1554 | void initialize( V && value ) | |
1555 | { | |
1556 | assert( ! has_value() ); | |
1557 | contained.construct_value( std::move( value ) ); | |
1558 | has_value_ = true; | |
1559 | } | |
1560 | ||
1561 | #endif | |
1562 | ||
1563 | private: | |
1564 | bool has_value_; | |
1565 | detail::storage_t< value_type > contained; | |
1566 | ||
1567 | }; | |
1568 | ||
1569 | // Relational operators | |
1570 | ||
1571 | template< typename T, typename U > | |
1572 | optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y ) | |
1573 | { | |
1574 | return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y; | |
1575 | } | |
1576 | ||
1577 | template< typename T, typename U > | |
1578 | optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y ) | |
1579 | { | |
1580 | return !(x == y); | |
1581 | } | |
1582 | ||
1583 | template< typename T, typename U > | |
1584 | optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y ) | |
1585 | { | |
1586 | return (!y) ? false : (!x) ? true : *x < *y; | |
1587 | } | |
1588 | ||
1589 | template< typename T, typename U > | |
1590 | optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y ) | |
1591 | { | |
1592 | return (y < x); | |
1593 | } | |
1594 | ||
1595 | template< typename T, typename U > | |
1596 | optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y ) | |
1597 | { | |
1598 | return !(y < x); | |
1599 | } | |
1600 | ||
1601 | template< typename T, typename U > | |
1602 | optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y ) | |
1603 | { | |
1604 | return !(x < y); | |
1605 | } | |
1606 | ||
1607 | // Comparison with nullopt | |
1608 | ||
1609 | template< typename T > | |
1610 | optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept | |
1611 | { | |
1612 | return (!x); | |
1613 | } | |
1614 | ||
1615 | template< typename T > | |
1616 | optional_nodiscard optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept | |
1617 | { | |
1618 | return (!x); | |
1619 | } | |
1620 | ||
1621 | template< typename T > | |
1622 | optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept | |
1623 | { | |
1624 | return bool(x); | |
1625 | } | |
1626 | ||
1627 | template< typename T > | |
1628 | optional_nodiscard optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept | |
1629 | { | |
1630 | return bool(x); | |
1631 | } | |
1632 | ||
1633 | template< typename T > | |
1634 | optional_nodiscard optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept | |
1635 | { | |
1636 | return false; | |
1637 | } | |
1638 | ||
1639 | template< typename T > | |
1640 | optional_nodiscard optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept | |
1641 | { | |
1642 | return bool(x); | |
1643 | } | |
1644 | ||
1645 | template< typename T > | |
1646 | optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept | |
1647 | { | |
1648 | return (!x); | |
1649 | } | |
1650 | ||
1651 | template< typename T > | |
1652 | optional_nodiscard optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept | |
1653 | { | |
1654 | return true; | |
1655 | } | |
1656 | ||
1657 | template< typename T > | |
1658 | optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept | |
1659 | { | |
1660 | return bool(x); | |
1661 | } | |
1662 | ||
1663 | template< typename T > | |
1664 | optional_nodiscard optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept | |
1665 | { | |
1666 | return false; | |
1667 | } | |
1668 | ||
1669 | template< typename T > | |
1670 | optional_nodiscard optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept | |
1671 | { | |
1672 | return true; | |
1673 | } | |
1674 | ||
1675 | template< typename T > | |
1676 | optional_nodiscard optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept | |
1677 | { | |
1678 | return (!x); | |
1679 | } | |
1680 | ||
1681 | // Comparison with T | |
1682 | ||
1683 | template< typename T, typename U > | |
1684 | optional_nodiscard optional_constexpr bool operator==( optional<T> const & x, U const & v ) | |
1685 | { | |
1686 | return bool(x) ? *x == v : false; | |
1687 | } | |
1688 | ||
1689 | template< typename T, typename U > | |
1690 | optional_nodiscard optional_constexpr bool operator==( U const & v, optional<T> const & x ) | |
1691 | { | |
1692 | return bool(x) ? v == *x : false; | |
1693 | } | |
1694 | ||
1695 | template< typename T, typename U > | |
1696 | optional_nodiscard optional_constexpr bool operator!=( optional<T> const & x, U const & v ) | |
1697 | { | |
1698 | return bool(x) ? *x != v : true; | |
1699 | } | |
1700 | ||
1701 | template< typename T, typename U > | |
1702 | optional_nodiscard optional_constexpr bool operator!=( U const & v, optional<T> const & x ) | |
1703 | { | |
1704 | return bool(x) ? v != *x : true; | |
1705 | } | |
1706 | ||
1707 | template< typename T, typename U > | |
1708 | optional_nodiscard optional_constexpr bool operator<( optional<T> const & x, U const & v ) | |
1709 | { | |
1710 | return bool(x) ? *x < v : true; | |
1711 | } | |
1712 | ||
1713 | template< typename T, typename U > | |
1714 | optional_nodiscard optional_constexpr bool operator<( U const & v, optional<T> const & x ) | |
1715 | { | |
1716 | return bool(x) ? v < *x : false; | |
1717 | } | |
1718 | ||
1719 | template< typename T, typename U > | |
1720 | optional_nodiscard optional_constexpr bool operator<=( optional<T> const & x, U const & v ) | |
1721 | { | |
1722 | return bool(x) ? *x <= v : true; | |
1723 | } | |
1724 | ||
1725 | template< typename T, typename U > | |
1726 | optional_nodiscard optional_constexpr bool operator<=( U const & v, optional<T> const & x ) | |
1727 | { | |
1728 | return bool(x) ? v <= *x : false; | |
1729 | } | |
1730 | ||
1731 | template< typename T, typename U > | |
1732 | optional_nodiscard optional_constexpr bool operator>( optional<T> const & x, U const & v ) | |
1733 | { | |
1734 | return bool(x) ? *x > v : false; | |
1735 | } | |
1736 | ||
1737 | template< typename T, typename U > | |
1738 | optional_nodiscard optional_constexpr bool operator>( U const & v, optional<T> const & x ) | |
1739 | { | |
1740 | return bool(x) ? v > *x : true; | |
1741 | } | |
1742 | ||
1743 | template< typename T, typename U > | |
1744 | optional_nodiscard optional_constexpr bool operator>=( optional<T> const & x, U const & v ) | |
1745 | { | |
1746 | return bool(x) ? *x >= v : false; | |
1747 | } | |
1748 | ||
1749 | template< typename T, typename U > | |
1750 | optional_nodiscard optional_constexpr bool operator>=( U const & v, optional<T> const & x ) | |
1751 | { | |
1752 | return bool(x) ? v >= *x : true; | |
1753 | } | |
1754 | ||
1755 | // Specialized algorithms | |
1756 | ||
1757 | template< typename T | |
1758 | #if optional_CPP11_OR_GREATER | |
1759 | optional_REQUIRES_T( | |
1760 | std11::is_move_constructible<T>::value | |
1761 | && std17::is_swappable<T>::value ) | |
1762 | #endif | |
1763 | > | |
1764 | void swap( optional<T> & x, optional<T> & y ) | |
1765 | #if optional_CPP11_OR_GREATER | |
1766 | noexcept( noexcept( x.swap(y) ) ) | |
1767 | #endif | |
1768 | { | |
1769 | x.swap( y ); | |
1770 | } | |
1771 | ||
1772 | #if optional_CPP11_OR_GREATER | |
1773 | ||
1774 | template< typename T > | |
1775 | optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value ) | |
1776 | { | |
1777 | return optional< typename std::decay<T>::type >( std::forward<T>( value ) ); | |
1778 | } | |
1779 | ||
1780 | template< typename T, typename...Args > | |
1781 | optional_constexpr optional<T> make_optional( Args&&... args ) | |
1782 | { | |
1783 | return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...); | |
1784 | } | |
1785 | ||
1786 | template< typename T, typename U, typename... Args > | |
1787 | optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args ) | |
1788 | { | |
1789 | return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...); | |
1790 | } | |
1791 | ||
1792 | #else | |
1793 | ||
1794 | template< typename T > | |
1795 | optional<T> make_optional( T const & value ) | |
1796 | { | |
1797 | return optional<T>( value ); | |
1798 | } | |
1799 | ||
1800 | #endif // optional_CPP11_OR_GREATER | |
1801 | ||
1802 | } // namespace optional_lite | |
1803 | ||
1804 | using optional_lite::optional; | |
1805 | using optional_lite::nullopt_t; | |
1806 | using optional_lite::nullopt; | |
1807 | ||
1808 | #if ! optional_CONFIG_NO_EXCEPTIONS | |
1809 | using optional_lite::bad_optional_access; | |
1810 | #endif | |
1811 | ||
1812 | using optional_lite::make_optional; | |
1813 | ||
1814 | } // namespace nonstd | |
1815 | ||
1816 | #if optional_CPP11_OR_GREATER | |
1817 | ||
1818 | // specialize the std::hash algorithm: | |
1819 | ||
1820 | namespace std { | |
1821 | ||
1822 | template< class T > | |
1823 | struct hash< nonstd::optional<T> > | |
1824 | { | |
1825 | public: | |
1826 | std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept | |
1827 | { | |
1828 | return bool( v ) ? std::hash<T>{}( *v ) : 0; | |
1829 | } | |
1830 | }; | |
1831 | ||
1832 | } //namespace std | |
1833 | ||
1834 | #endif // optional_CPP11_OR_GREATER | |
1835 | ||
1836 | #if defined(__clang__) | |
1837 | # pragma clang diagnostic pop | |
1838 | #elif defined(__GNUC__) | |
1839 | # pragma GCC diagnostic pop | |
1840 | #elif defined(_MSC_VER ) | |
1841 | # pragma warning( pop ) | |
1842 | #endif | |
1843 | ||
1844 | #endif // optional_USES_STD_OPTIONAL | |
1845 | ||
1846 | #endif // NONSTD_OPTIONAL_LITE_HPP |