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