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