1
|
|
-// Copyright (c) 2016, Charles Lechasseur
|
2
|
|
-// Distributed under the MIT license (see LICENSE).
|
|
1
|
+//
|
|
2
|
+// Copyright (c) 2014-2018 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)
|
3
|
8
|
|
4
|
|
-// Implementation of C++17's std::optional
|
|
9
|
+#pragma once
|
5
|
10
|
|
6
|
|
-#ifndef CL_OPTIONAL_H
|
7
|
|
-#define CL_OPTIONAL_H
|
|
11
|
+#ifndef NONSTD_OPTIONAL_LITE_HPP
|
|
12
|
+#define NONSTD_OPTIONAL_LITE_HPP
|
8
|
13
|
|
9
|
|
-#include <functional>
|
|
14
|
+#define optional_lite_MAJOR 3
|
|
15
|
+#define optional_lite_MINOR 1
|
|
16
|
+#define optional_lite_PATCH 1
|
|
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
|
+#if !defined( optional_CONFIG_SELECT_OPTIONAL )
|
|
30
|
+# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
|
|
31
|
+#endif
|
|
32
|
+
|
|
33
|
+// C++ language version detection (C++20 is speculative):
|
|
34
|
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
|
|
35
|
+
|
|
36
|
+#ifndef optional_CPLUSPLUS
|
|
37
|
+# if defined(_MSVC_LANG ) && !defined(__clang__)
|
|
38
|
+# define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
|
|
39
|
+# else
|
|
40
|
+# define optional_CPLUSPLUS __cplusplus
|
|
41
|
+# endif
|
|
42
|
+#endif
|
|
43
|
+
|
|
44
|
+#define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L )
|
|
45
|
+#define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L )
|
|
46
|
+#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
|
|
47
|
+#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
|
|
48
|
+#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
|
|
49
|
+#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L )
|
|
50
|
+
|
|
51
|
+// C++ language version (represent 98 as 3):
|
|
52
|
+
|
|
53
|
+#define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
|
|
54
|
+
|
|
55
|
+// Use C++17 std::optional if available and requested:
|
|
56
|
+
|
|
57
|
+#if optional_CPP17_OR_GREATER && defined(__has_include )
|
|
58
|
+# if __has_include( <optional> )
|
|
59
|
+# define optional_HAVE_STD_OPTIONAL 1
|
|
60
|
+# else
|
|
61
|
+# define optional_HAVE_STD_OPTIONAL 0
|
|
62
|
+# endif
|
|
63
|
+#else
|
|
64
|
+# define optional_HAVE_STD_OPTIONAL 0
|
|
65
|
+#endif
|
|
66
|
+
|
|
67
|
+#define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
|
|
68
|
+
|
|
69
|
+//
|
|
70
|
+// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
|
|
71
|
+//
|
|
72
|
+
|
|
73
|
+#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
|
|
74
|
+#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
|
|
75
|
+
|
|
76
|
+// C++17 std::in_place in <utility>:
|
|
77
|
+
|
|
78
|
+#if optional_CPP17_OR_GREATER
|
|
79
|
+
|
|
80
|
+#include <utility>
|
|
81
|
+
|
|
82
|
+namespace nonstd {
|
|
83
|
+
|
|
84
|
+using std::in_place;
|
|
85
|
+using std::in_place_type;
|
|
86
|
+using std::in_place_index;
|
|
87
|
+using std::in_place_t;
|
|
88
|
+using std::in_place_type_t;
|
|
89
|
+using std::in_place_index_t;
|
|
90
|
+
|
|
91
|
+#define nonstd_lite_in_place_t( T) std::in_place_t
|
|
92
|
+#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
|
|
93
|
+#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
|
|
94
|
+
|
|
95
|
+#define nonstd_lite_in_place( T) std::in_place_t{}
|
|
96
|
+#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
|
|
97
|
+#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
|
|
98
|
+
|
|
99
|
+} // namespace nonstd
|
|
100
|
+
|
|
101
|
+#else // optional_CPP17_OR_GREATER
|
|
102
|
+
|
|
103
|
+#include <cstddef>
|
|
104
|
+
|
|
105
|
+namespace nonstd {
|
|
106
|
+namespace detail {
|
|
107
|
+
|
|
108
|
+template< class T >
|
|
109
|
+struct in_place_type_tag {};
|
|
110
|
+
|
|
111
|
+template< std::size_t K >
|
|
112
|
+struct in_place_index_tag {};
|
|
113
|
+
|
|
114
|
+} // namespace detail
|
|
115
|
+
|
|
116
|
+struct in_place_t {};
|
|
117
|
+
|
|
118
|
+template< class T >
|
|
119
|
+inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
|
|
120
|
+{
|
|
121
|
+ return in_place_t();
|
|
122
|
+}
|
|
123
|
+
|
|
124
|
+template< std::size_t K >
|
|
125
|
+inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
|
|
126
|
+{
|
|
127
|
+ return in_place_t();
|
|
128
|
+}
|
|
129
|
+
|
|
130
|
+template< class T >
|
|
131
|
+inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
|
|
132
|
+{
|
|
133
|
+ return in_place_t();
|
|
134
|
+}
|
|
135
|
+
|
|
136
|
+template< std::size_t K >
|
|
137
|
+inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
|
|
138
|
+{
|
|
139
|
+ return in_place_t();
|
|
140
|
+}
|
|
141
|
+
|
|
142
|
+// mimic templated typedef:
|
|
143
|
+
|
|
144
|
+#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
|
|
145
|
+#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
|
|
146
|
+#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
|
|
147
|
+
|
|
148
|
+#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
|
|
149
|
+#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
|
|
150
|
+#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
|
|
151
|
+
|
|
152
|
+} // namespace nonstd
|
|
153
|
+
|
|
154
|
+#endif // optional_CPP17_OR_GREATER
|
|
155
|
+#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
|
|
156
|
+
|
|
157
|
+//
|
|
158
|
+// Using std::optional:
|
|
159
|
+//
|
|
160
|
+
|
|
161
|
+#if optional_USES_STD_OPTIONAL
|
|
162
|
+
|
|
163
|
+#include <optional>
|
|
164
|
+
|
|
165
|
+namespace nonstd {
|
|
166
|
+
|
|
167
|
+ using std::optional;
|
|
168
|
+ using std::bad_optional_access;
|
|
169
|
+ using std::hash;
|
|
170
|
+
|
|
171
|
+ using std::nullopt;
|
|
172
|
+ using std::nullopt_t;
|
|
173
|
+
|
|
174
|
+ using std::operator==;
|
|
175
|
+ using std::operator!=;
|
|
176
|
+ using std::operator<;
|
|
177
|
+ using std::operator<=;
|
|
178
|
+ using std::operator>;
|
|
179
|
+ using std::operator>=;
|
|
180
|
+ using std::make_optional;
|
|
181
|
+ using std::swap;
|
|
182
|
+}
|
|
183
|
+
|
|
184
|
+#else // optional_USES_STD_OPTIONAL
|
|
185
|
+
|
|
186
|
+#include <cassert>
|
10
|
187
|
#include <stdexcept>
|
11
|
|
-#include <string>
|
12
|
|
-#include <type_traits>
|
13
|
188
|
#include <utility>
|
14
|
189
|
|
|
190
|
+// optional-lite alignment configuration:
|
|
191
|
+
|
|
192
|
+#ifndef optional_CONFIG_MAX_ALIGN_HACK
|
|
193
|
+# define optional_CONFIG_MAX_ALIGN_HACK 0
|
|
194
|
+#endif
|
|
195
|
+
|
|
196
|
+#ifndef optional_CONFIG_ALIGN_AS
|
|
197
|
+// no default, used in #if defined()
|
|
198
|
+#endif
|
|
199
|
+
|
|
200
|
+#ifndef optional_CONFIG_ALIGN_AS_FALLBACK
|
|
201
|
+# define optional_CONFIG_ALIGN_AS_FALLBACK double
|
|
202
|
+#endif
|
|
203
|
+
|
|
204
|
+// Compiler warning suppression:
|
|
205
|
+
|
|
206
|
+#if defined(__clang__)
|
|
207
|
+# pragma clang diagnostic push
|
|
208
|
+# pragma clang diagnostic ignored "-Wundef"
|
|
209
|
+#elif defined(__GNUC__)
|
|
210
|
+# pragma GCC diagnostic push
|
|
211
|
+# pragma GCC diagnostic ignored "-Wundef"
|
|
212
|
+#endif
|
|
213
|
+
|
|
214
|
+// half-open range [lo..hi):
|
|
215
|
+#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
|
|
216
|
+
|
|
217
|
+// Compiler versions:
|
|
218
|
+//
|
|
219
|
+// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
|
|
220
|
+// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
|
|
221
|
+// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
|
|
222
|
+// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
|
|
223
|
+// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
|
|
224
|
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
|
|
225
|
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
|
|
226
|
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
|
|
227
|
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
|
|
228
|
+// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
|
|
229
|
+
|
|
230
|
+#if defined(_MSC_VER ) && !defined(__clang__)
|
|
231
|
+# define optional_COMPILER_MSVC_VER (_MSC_VER )
|
|
232
|
+# define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
|
|
233
|
+#else
|
|
234
|
+# define optional_COMPILER_MSVC_VER 0
|
|
235
|
+# define optional_COMPILER_MSVC_VERSION 0
|
|
236
|
+#endif
|
|
237
|
+
|
|
238
|
+#define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * major + minor ) + patch )
|
15
|
239
|
|
16
|
|
-// Compiler detection
|
17
|
|
-#if defined(_MSC_VER)
|
18
|
|
-# if _MSC_VER >= 1800 // Visual Studio 2013
|
19
|
|
-# define CL_OPTIONAL_VARIADIC
|
20
|
|
-# define CL_OPTIONAL_EXPLICIT_OP_BOOL
|
21
|
|
-# define CL_OPTIONAL_TEMPLATE_FUNCS_DEFAULT_PARAMS
|
22
|
|
-# endif
|
23
|
|
-# if _MSC_VER >= 1900 // Visual Studio 2015
|
24
|
|
-# define CL_OPTIONAL_NORETURN
|
25
|
|
-# define CL_OPTIONAL_MEMBERS_REF_QUALIFIERS
|
26
|
|
-# endif
|
27
|
|
-# if _MSC_VER >= 1910 // Visual Studio 2017
|
28
|
|
-# define CL_OPTIONAL_NOEXCEPT // Note: in theory this is supported in VC14, but a bug in VC14 update 3 can cause compiler errors
|
29
|
|
-# define CL_OPTIONAL_CONSTEXPR
|
30
|
|
-# endif
|
31
|
|
-#elif defined(__clang__)
|
32
|
|
-# if __has_feature(cxx_noexcept)
|
33
|
|
-# define CL_OPTIONAL_NOEXCEPT
|
34
|
|
-# endif
|
35
|
|
-# if __has_feature(cxx_constexpr) && __cplusplus >= 201402L
|
36
|
|
-# define CL_OPTIONAL_CONSTEXPR
|
37
|
|
-# endif
|
38
|
|
-# if __has_feature(cxx_attributes)
|
39
|
|
-# define CL_OPTIONAL_NORETURN
|
40
|
|
-# endif
|
41
|
|
-# if __has_feature(cxx_variadic_templates)
|
42
|
|
-# define CL_OPTIONAL_VARIADIC
|
43
|
|
-# endif
|
44
|
|
-# if __has_feature(cxx_reference_qualified_functions) && __cplusplus >= 201402L
|
45
|
|
-# define CL_OPTIONAL_MEMBERS_REF_QUALIFIERS
|
46
|
|
-# endif
|
47
|
|
-# if __has_feature(cxx_explicit_conversions)
|
48
|
|
-# define CL_OPTIONAL_EXPLICIT_OP_BOOL
|
49
|
|
-# endif
|
50
|
|
-# if __has_feature(cxx_default_function_template_args)
|
51
|
|
-# define CL_OPTIONAL_TEMPLATE_FUNCS_DEFAULT_PARAMS
|
52
|
|
-# endif
|
53
|
|
-#elif defined(__GNUG__)
|
54
|
|
-# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
|
55
|
|
-# define CL_OPTIONAL_NOEXCEPT
|
56
|
|
-# define CL_OPTIONAL_NORETURN
|
57
|
|
-# define CL_OPTIONAL_VARIADIC
|
58
|
|
-# define CL_OPTIONAL_MEMBERS_REF_QUALIFIERS
|
59
|
|
-# define CL_OPTIONAL_EXPLICIT_OP_BOOL
|
60
|
|
-# define CL_OPTIONAL_TEMPLATE_FUNCS_DEFAULT_PARAMS
|
61
|
|
-# endif
|
62
|
|
-# if __GNUC__ >= 5
|
63
|
|
-# define CL_OPTIONAL_CONSTEXPR
|
64
|
|
-# endif
|
65
|
|
-#endif
|
66
|
|
-
|
67
|
|
-
|
68
|
|
-// Define CL_OPTIONAL_NOEXCEPT to get noexcept specifications
|
69
|
|
-#ifdef CL_OPTIONAL_NOEXCEPT
|
70
|
|
-# define _CL_OPT_NOEXCEPT noexcept
|
71
|
|
-# define _CL_OPT_NOEXCEPTEX(...) noexcept(__VA_ARGS__)
|
|
240
|
+#if defined(__GNUC__) && !defined(__clang__)
|
|
241
|
+# define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
72
|
242
|
#else
|
73
|
|
-# define _CL_OPT_NOEXCEPT
|
74
|
|
-# define _CL_OPT_NOEXCEPTEX(...)
|
|
243
|
+# define optional_COMPILER_GNUC_VERSION 0
|
75
|
244
|
#endif
|
76
|
245
|
|
77
|
|
-// Define CL_OPTIONAL_CONSTEXPR to get constexpr specifications
|
78
|
|
-#ifdef CL_OPTIONAL_CONSTEXPR
|
79
|
|
-# define _CL_OPT_CONSTEXPR constexpr
|
80
|
|
-# define _CL_OPT_CONSTEXPR_OR_CONST constexpr
|
|
246
|
+#if defined(__clang__)
|
|
247
|
+# define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
|
81
|
248
|
#else
|
82
|
|
-# define _CL_OPT_CONSTEXPR
|
83
|
|
-# define _CL_OPT_CONSTEXPR_OR_CONST const
|
|
249
|
+# define optional_COMPILER_CLANG_VERSION 0
|
|
250
|
+#endif
|
|
251
|
+
|
|
252
|
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
|
|
253
|
+# pragma warning( push )
|
|
254
|
+# pragma warning( disable: 4345 ) // initialization behavior changed
|
|
255
|
+#endif
|
|
256
|
+
|
|
257
|
+#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
|
|
258
|
+# pragma warning( push )
|
|
259
|
+# pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
|
84
|
260
|
#endif
|
85
|
261
|
|
86
|
|
-// Define CL_OPTIONAL_VARIADIC to get variadic templates
|
87
|
|
-#ifdef CL_OPTIONAL_VARIADIC
|
88
|
|
-# define _CL_OPT_VARIADIC 1
|
|
262
|
+// Presence of language and library features:
|
|
263
|
+
|
|
264
|
+#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
|
|
265
|
+
|
|
266
|
+#ifdef _HAS_CPP0X
|
|
267
|
+# define optional_HAS_CPP0X _HAS_CPP0X
|
|
268
|
+#else
|
|
269
|
+# define optional_HAS_CPP0X 0
|
|
270
|
+#endif
|
|
271
|
+
|
|
272
|
+// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
|
|
273
|
+
|
|
274
|
+#if optional_COMPILER_MSVC_VER >= 1900
|
|
275
|
+# undef optional_CPP11_OR_GREATER
|
|
276
|
+# define optional_CPP11_OR_GREATER 1
|
|
277
|
+#endif
|
|
278
|
+
|
|
279
|
+#define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
|
|
280
|
+#define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
|
|
281
|
+#define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
|
|
282
|
+#define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
|
|
283
|
+#define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
|
|
284
|
+#define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
|
|
285
|
+
|
|
286
|
+#define optional_CPP14_000 (optional_CPP14_OR_GREATER)
|
|
287
|
+#define optional_CPP17_000 (optional_CPP17_OR_GREATER)
|
|
288
|
+
|
|
289
|
+// Presence of C++11 language features:
|
|
290
|
+
|
|
291
|
+#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
|
|
292
|
+#define optional_HAVE_NOEXCEPT optional_CPP11_140
|
|
293
|
+#define optional_HAVE_NULLPTR optional_CPP11_100
|
|
294
|
+#define optional_HAVE_REF_QUALIFIER optional_CPP11_140
|
|
295
|
+
|
|
296
|
+// Presence of C++14 language features:
|
|
297
|
+
|
|
298
|
+#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
|
|
299
|
+
|
|
300
|
+// Presence of C++17 language features:
|
|
301
|
+
|
|
302
|
+// no flag
|
|
303
|
+
|
|
304
|
+// Presence of C++ library features:
|
|
305
|
+
|
|
306
|
+#define optional_HAVE_CONDITIONAL optional_CPP11_120
|
|
307
|
+#define optional_HAVE_REMOVE_CV optional_CPP11_120
|
|
308
|
+#define optional_HAVE_TYPE_TRAITS optional_CPP11_90
|
|
309
|
+
|
|
310
|
+#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
|
|
311
|
+#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
|
|
312
|
+
|
|
313
|
+// C++ feature usage:
|
|
314
|
+
|
|
315
|
+#if optional_HAVE( CONSTEXPR_11 )
|
|
316
|
+# define optional_constexpr constexpr
|
89
|
317
|
#else
|
90
|
|
-# define _CL_OPT_VARIADIC 0
|
|
318
|
+# define optional_constexpr /*constexpr*/
|
91
|
319
|
#endif
|
92
|
320
|
|
93
|
|
-// Define CL_OPTIONAL_NORETURN to get noreturn specifications
|
94
|
|
-#ifdef CL_OPTIONAL_NORETURN
|
95
|
|
-# define _CL_OPT_NORETURN [[noreturn]]
|
|
321
|
+#if optional_HAVE( CONSTEXPR_14 )
|
|
322
|
+# define optional_constexpr14 constexpr
|
96
|
323
|
#else
|
97
|
|
-# define _CL_OPT_NORETURN
|
|
324
|
+# define optional_constexpr14 /*constexpr*/
|
98
|
325
|
#endif
|
99
|
326
|
|
100
|
|
-// Define CL_OPTIONAL_MEMBERS_REF_QUALIFIERS to get lvalue- and rvalue-qualified members
|
101
|
|
-#ifdef CL_OPTIONAL_MEMBERS_REF_QUALIFIERS
|
102
|
|
-# define _CL_OPT_MEMBERS_REF_QUALIFIERS 1
|
103
|
|
-# define _CL_OPT_LVALUE_REF_QUALIF &
|
|
327
|
+#if optional_HAVE( NOEXCEPT )
|
|
328
|
+# define optional_noexcept noexcept
|
104
|
329
|
#else
|
105
|
|
-# define _CL_OPT_MEMBERS_REF_QUALIFIERS 0
|
106
|
|
-# define _CL_OPT_LVALUE_REF_QUALIF
|
|
330
|
+# define optional_noexcept /*noexcept*/
|
107
|
331
|
#endif
|
108
|
332
|
|
109
|
|
-// Define CL_OPTIONAL_EXPLICIT_OP_BOOL to get explicit operator bool()
|
110
|
|
-#ifdef CL_OPTIONAL_EXPLICIT_OP_BOOL
|
111
|
|
-# define _CL_OPT_OP_EXPLICIT explicit
|
|
333
|
+#if optional_HAVE( NULLPTR )
|
|
334
|
+# define optional_nullptr nullptr
|
112
|
335
|
#else
|
113
|
|
-# define _CL_OPT_OP_EXPLICIT
|
|
336
|
+# define optional_nullptr NULL
|
114
|
337
|
#endif
|
115
|
338
|
|
116
|
|
-// Define CL_OPTIONAL_TEMPLATE_FUNCS_DEFAULT_PARAMS to get template methods
|
117
|
|
-// with default template params, like assignment operator from value
|
118
|
|
-#ifdef CL_OPTIONAL_TEMPLATE_FUNCS_DEFAULT_PARAMS
|
119
|
|
-# define _CL_OPT_TEMPL_FUNC_DEF_PARAMS 1
|
|
339
|
+#if optional_HAVE( REF_QUALIFIER )
|
|
340
|
+# define optional_ref_qual &
|
|
341
|
+# define optional_refref_qual &&
|
120
|
342
|
#else
|
121
|
|
-# define _CL_OPT_TEMPL_FUNC_DEF_PARAMS 0
|
|
343
|
+# define optional_ref_qual /*&*/
|
|
344
|
+# define optional_refref_qual /*&&*/
|
|
345
|
+#endif
|
|
346
|
+
|
|
347
|
+// additional includes:
|
|
348
|
+
|
|
349
|
+#if optional_CPP11_OR_GREATER
|
|
350
|
+# include <functional>
|
|
351
|
+#endif
|
|
352
|
+
|
|
353
|
+#if optional_HAVE( INITIALIZER_LIST )
|
|
354
|
+# include <initializer_list>
|
122
|
355
|
#endif
|
123
|
356
|
|
|
357
|
+#if optional_HAVE( TYPE_TRAITS )
|
|
358
|
+# include <type_traits>
|
|
359
|
+#elif optional_HAVE( TR1_TYPE_TRAITS )
|
|
360
|
+# include <tr1/type_traits>
|
|
361
|
+#endif
|
|
362
|
+
|
|
363
|
+// Method enabling
|
|
364
|
+
|
|
365
|
+#if optional_CPP11_OR_GREATER
|
|
366
|
+
|
|
367
|
+# define optional_REQUIRES_T(...) \
|
|
368
|
+ , typename = typename std::enable_if<__VA_ARGS__>::type
|
|
369
|
+
|
|
370
|
+# define optional_REQUIRES_R(R, ...) \
|
|
371
|
+ typename std::enable_if<__VA_ARGS__, R>::type
|
|
372
|
+
|
|
373
|
+# define optional_REQUIRES_A(...) \
|
|
374
|
+ , typename std::enable_if<__VA_ARGS__, void*>::type = optional_nullptr
|
124
|
375
|
|
125
|
|
-#if _CL_OPT_VARIADIC
|
126
|
|
-# include <initializer_list>
|
127
|
376
|
#endif
|
128
|
377
|
|
129
|
|
-namespace cl {
|
|
378
|
+//
|
|
379
|
+// optional:
|
|
380
|
+//
|
|
381
|
+
|
|
382
|
+namespace nonstd { namespace optional_lite {
|
|
383
|
+
|
|
384
|
+namespace detail {
|
130
|
385
|
|
131
|
|
-// Type indicating an optional object with no value. See:
|
132
|
|
-// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
|
133
|
|
-struct nullopt_t {
|
134
|
|
- _CL_OPT_CONSTEXPR nullopt_t(int) { }
|
|
386
|
+#if optional_HAVE( CONDITIONAL )
|
|
387
|
+ using std::conditional;
|
|
388
|
+#else
|
|
389
|
+ template< bool B, typename T, typename F > struct conditional { typedef T type; };
|
|
390
|
+ template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
|
|
391
|
+#endif // optional_HAVE_CONDITIONAL
|
|
392
|
+
|
|
393
|
+} // namespace detail
|
|
394
|
+
|
|
395
|
+#if optional_CPP11_OR_GREATER
|
|
396
|
+
|
|
397
|
+namespace std20 {
|
|
398
|
+
|
|
399
|
+// type traits C++20:
|
|
400
|
+
|
|
401
|
+template< typename T >
|
|
402
|
+struct remove_cvref
|
|
403
|
+{
|
|
404
|
+ typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
|
135
|
405
|
};
|
136
|
406
|
|
137
|
|
-// Instance of nullopt_t passed to optional's members. See:
|
138
|
|
-// http://en.cppreference.com/w/cpp/utility/optional/nullopt
|
139
|
|
-_CL_OPT_CONSTEXPR_OR_CONST nullopt_t nullopt = 0;
|
|
407
|
+} // namespace std20
|
140
|
408
|
|
141
|
|
-#if _CL_OPT_VARIADIC
|
142
|
|
-// Empty type used for in_place functions. See:
|
143
|
|
-// http://en.cppreference.com/w/cpp/utility/in_place_tag
|
144
|
|
-struct in_place_tag {
|
145
|
|
- in_place_tag() = delete;
|
146
|
|
-private:
|
147
|
|
- in_place_tag(int) { }
|
148
|
|
- friend in_place_tag in_place();
|
|
409
|
+#endif // optional_CPP11_OR_GREATER
|
|
410
|
+
|
|
411
|
+/// class optional
|
|
412
|
+
|
|
413
|
+template< typename T >
|
|
414
|
+class optional;
|
|
415
|
+
|
|
416
|
+namespace detail {
|
|
417
|
+
|
|
418
|
+// C++11 emulation:
|
|
419
|
+
|
|
420
|
+struct nulltype{};
|
|
421
|
+
|
|
422
|
+template< typename Head, typename Tail >
|
|
423
|
+struct typelist
|
|
424
|
+{
|
|
425
|
+ typedef Head head;
|
|
426
|
+ typedef Tail tail;
|
149
|
427
|
};
|
150
|
428
|
|
151
|
|
-// Function to identify an optional method with in-place construction. See:
|
152
|
|
-// http://en.cppreference.com/w/cpp/utility/in_place
|
153
|
|
-inline in_place_tag in_place() { return in_place_tag(0); }
|
154
|
|
-using in_place_t = in_place_tag (&)();
|
155
|
|
-#endif // _CL_OPT_VARIADIC
|
|
429
|
+#if optional_CONFIG_MAX_ALIGN_HACK
|
156
|
430
|
|
157
|
|
-// Exception thrown by optional when trying to access
|
158
|
|
-// an optional with no value. See:
|
159
|
|
-// http://en.cppreference.com/w/cpp/utility/optional/bad_optional_access
|
160
|
|
-class bad_optional_access : public std::logic_error
|
|
431
|
+// Max align, use most restricted type for alignment:
|
|
432
|
+
|
|
433
|
+#define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
|
|
434
|
+#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
|
|
435
|
+#define optional_UNIQUE3( name, line ) name ## line
|
|
436
|
+
|
|
437
|
+#define optional_ALIGN_TYPE( type ) \
|
|
438
|
+ type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
|
|
439
|
+
|
|
440
|
+template< typename T >
|
|
441
|
+struct struct_t { T _; };
|
|
442
|
+
|
|
443
|
+union max_align_t
|
161
|
444
|
{
|
162
|
|
-public:
|
163
|
|
- bad_optional_access(const std::string& what_arg)
|
164
|
|
- : std::logic_error(what_arg) { }
|
165
|
|
- bad_optional_access(const char* what_arg)
|
166
|
|
- : std::logic_error(what_arg) { }
|
|
445
|
+ optional_ALIGN_TYPE( char );
|
|
446
|
+ optional_ALIGN_TYPE( short int );
|
|
447
|
+ optional_ALIGN_TYPE( int );
|
|
448
|
+ optional_ALIGN_TYPE( long int );
|
|
449
|
+ optional_ALIGN_TYPE( float );
|
|
450
|
+ optional_ALIGN_TYPE( double );
|
|
451
|
+ optional_ALIGN_TYPE( long double );
|
|
452
|
+ optional_ALIGN_TYPE( char * );
|
|
453
|
+ optional_ALIGN_TYPE( short int * );
|
|
454
|
+ optional_ALIGN_TYPE( int * );
|
|
455
|
+ optional_ALIGN_TYPE( long int * );
|
|
456
|
+ optional_ALIGN_TYPE( float * );
|
|
457
|
+ optional_ALIGN_TYPE( double * );
|
|
458
|
+ optional_ALIGN_TYPE( long double * );
|
|
459
|
+ optional_ALIGN_TYPE( void * );
|
|
460
|
+
|
|
461
|
+#ifdef HAVE_LONG_LONG
|
|
462
|
+ optional_ALIGN_TYPE( long long );
|
|
463
|
+#endif
|
|
464
|
+
|
|
465
|
+ struct Unknown;
|
|
466
|
+
|
|
467
|
+ Unknown ( * optional_UNIQUE(_) )( Unknown );
|
|
468
|
+ Unknown * Unknown::* optional_UNIQUE(_);
|
|
469
|
+ Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
|
|
470
|
+
|
|
471
|
+ struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
|
|
472
|
+ struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
|
|
473
|
+ struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
|
167
|
474
|
};
|
168
|
475
|
|
169
|
|
-// Wrapper for an optional value. Part of future C++17 API. See:
|
170
|
|
-// http://en.cppreference.com/w/cpp/utility/optional
|
171
|
|
-template<typename T>
|
172
|
|
-class optional
|
|
476
|
+#undef optional_UNIQUE
|
|
477
|
+#undef optional_UNIQUE2
|
|
478
|
+#undef optional_UNIQUE3
|
|
479
|
+
|
|
480
|
+#undef optional_ALIGN_TYPE
|
|
481
|
+
|
|
482
|
+#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
|
|
483
|
+
|
|
484
|
+// Use user-specified type for alignment:
|
|
485
|
+
|
|
486
|
+#define optional_ALIGN_AS( unused ) \
|
|
487
|
+ optional_CONFIG_ALIGN_AS
|
|
488
|
+
|
|
489
|
+#else // optional_CONFIG_MAX_ALIGN_HACK
|
|
490
|
+
|
|
491
|
+// Determine POD type to use for alignment:
|
|
492
|
+
|
|
493
|
+#define optional_ALIGN_AS( to_align ) \
|
|
494
|
+ typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
|
|
495
|
+
|
|
496
|
+template< typename T >
|
|
497
|
+struct alignment_of;
|
|
498
|
+
|
|
499
|
+template< typename T >
|
|
500
|
+struct alignment_of_hack
|
|
501
|
+{
|
|
502
|
+ char c;
|
|
503
|
+ T t;
|
|
504
|
+ alignment_of_hack();
|
|
505
|
+};
|
|
506
|
+
|
|
507
|
+template< size_t A, size_t S >
|
|
508
|
+struct alignment_logic
|
173
|
509
|
{
|
174
|
|
- static_assert(!std::is_reference<T>::value, "cl::optional does not work with reference types");
|
175
|
|
- static_assert(std::is_destructible<T>::value, "cl::optional requires type to be Destructible");
|
|
510
|
+ enum { value = A < S ? A : S };
|
|
511
|
+};
|
176
|
512
|
|
177
|
|
-private:
|
178
|
|
- typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type stg_; // We store any value here.
|
179
|
|
- T* const pval_; // Pointer to value stored in stg_.
|
180
|
|
- bool has_value_; // Whether we have a value in stg_.
|
|
513
|
+template< typename T >
|
|
514
|
+struct alignment_of
|
|
515
|
+{
|
|
516
|
+ enum { value = alignment_logic<
|
|
517
|
+ sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
|
|
518
|
+};
|
|
519
|
+
|
|
520
|
+template< typename List, size_t N >
|
|
521
|
+struct type_of_size
|
|
522
|
+{
|
|
523
|
+ typedef typename conditional<
|
|
524
|
+ N == sizeof( typename List::head ),
|
|
525
|
+ typename List::head,
|
|
526
|
+ typename type_of_size<typename List::tail, N >::type >::type type;
|
|
527
|
+};
|
|
528
|
+
|
|
529
|
+template< size_t N >
|
|
530
|
+struct type_of_size< nulltype, N >
|
|
531
|
+{
|
|
532
|
+ typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
|
|
533
|
+};
|
|
534
|
+
|
|
535
|
+template< typename T>
|
|
536
|
+struct struct_t { T _; };
|
|
537
|
+
|
|
538
|
+#define optional_ALIGN_TYPE( type ) \
|
|
539
|
+ typelist< type , typelist< struct_t< type >
|
|
540
|
+
|
|
541
|
+struct Unknown;
|
181
|
542
|
|
182
|
|
- // Exception helpers
|
183
|
|
- _CL_OPT_NORETURN void throw_bad_optional_access() const {
|
184
|
|
- throw bad_optional_access("bad_optional_access");
|
|
543
|
+typedef
|
|
544
|
+ optional_ALIGN_TYPE( char ),
|
|
545
|
+ optional_ALIGN_TYPE( short ),
|
|
546
|
+ optional_ALIGN_TYPE( int ),
|
|
547
|
+ optional_ALIGN_TYPE( long ),
|
|
548
|
+ optional_ALIGN_TYPE( float ),
|
|
549
|
+ optional_ALIGN_TYPE( double ),
|
|
550
|
+ optional_ALIGN_TYPE( long double ),
|
|
551
|
+
|
|
552
|
+ optional_ALIGN_TYPE( char *),
|
|
553
|
+ optional_ALIGN_TYPE( short * ),
|
|
554
|
+ optional_ALIGN_TYPE( int * ),
|
|
555
|
+ optional_ALIGN_TYPE( long * ),
|
|
556
|
+ optional_ALIGN_TYPE( float * ),
|
|
557
|
+ optional_ALIGN_TYPE( double * ),
|
|
558
|
+ optional_ALIGN_TYPE( long double * ),
|
|
559
|
+
|
|
560
|
+ optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
|
|
561
|
+ optional_ALIGN_TYPE( Unknown * Unknown::* ),
|
|
562
|
+ optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
|
|
563
|
+
|
|
564
|
+ nulltype
|
|
565
|
+ > > > > > > > > > > > > > >
|
|
566
|
+ > > > > > > > > > > > > > >
|
|
567
|
+ > > > > > >
|
|
568
|
+ alignment_types;
|
|
569
|
+
|
|
570
|
+#undef optional_ALIGN_TYPE
|
|
571
|
+
|
|
572
|
+#endif // optional_CONFIG_MAX_ALIGN_HACK
|
|
573
|
+
|
|
574
|
+/// C++03 constructed union to hold value.
|
|
575
|
+
|
|
576
|
+template< typename T >
|
|
577
|
+union storage_t
|
|
578
|
+{
|
|
579
|
+//private:
|
|
580
|
+// template< typename > friend class optional;
|
|
581
|
+
|
|
582
|
+ typedef T value_type;
|
|
583
|
+
|
|
584
|
+ storage_t() {}
|
|
585
|
+
|
|
586
|
+ storage_t( value_type const & v )
|
|
587
|
+ {
|
|
588
|
+ construct_value( v );
|
185
|
589
|
}
|
186
|
590
|
|
187
|
|
- // Helper for swap when one has a value and the other does not
|
188
|
|
- static void swap_helper(optional& from, optional& to) _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value &&
|
189
|
|
- std::is_nothrow_destructible<T>::value)
|
|
591
|
+ void construct_value( value_type const & v )
|
190
|
592
|
{
|
191
|
|
- new (to.pval_) T(std::move(*from.pval_));
|
192
|
|
- from.pval_->~T();
|
193
|
|
- to.has_value_ = true;
|
194
|
|
- from.has_value_ = false;
|
|
593
|
+ ::new( value_ptr() ) value_type( v );
|
195
|
594
|
}
|
196
|
595
|
|
197
|
|
-public:
|
198
|
|
- typedef T value_type;
|
|
596
|
+#if optional_CPP11_OR_GREATER
|
199
|
597
|
|
200
|
|
- // Constructors of optional without a value
|
201
|
|
- _CL_OPT_CONSTEXPR optional() _CL_OPT_NOEXCEPT
|
202
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(false) { }
|
203
|
|
- _CL_OPT_CONSTEXPR optional(nullopt_t) _CL_OPT_NOEXCEPT
|
204
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(false) { }
|
|
598
|
+ storage_t( value_type && v )
|
|
599
|
+ {
|
|
600
|
+ construct_value( std::move( v ) );
|
|
601
|
+ }
|
205
|
602
|
|
206
|
|
- // Copy constructor
|
207
|
|
- optional(const optional& obj) _CL_OPT_NOEXCEPTEX(std::is_nothrow_copy_constructible<T>::value)
|
208
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(obj.has_value_)
|
|
603
|
+ void construct_value( value_type && v )
|
209
|
604
|
{
|
210
|
|
- if (has_value_) {
|
211
|
|
- new (pval_) T(*obj.pval_);
|
212
|
|
- }
|
|
605
|
+ ::new( value_ptr() ) value_type( std::move( v ) );
|
213
|
606
|
}
|
214
|
607
|
|
215
|
|
- // Move constructor (note: does not steal has_value_, see API)
|
216
|
|
- optional(optional&& obj) _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value)
|
217
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(obj.has_value_)
|
|
608
|
+ template< class... Args >
|
|
609
|
+ void emplace( Args&&... args )
|
218
|
610
|
{
|
219
|
|
- if (has_value_) {
|
220
|
|
- new (pval_) T(std::move(*obj.pval_));
|
221
|
|
- }
|
|
611
|
+ ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
|
222
|
612
|
}
|
223
|
613
|
|
224
|
|
- // Constructors of optional with a value
|
225
|
|
- optional(const T& val) _CL_OPT_NOEXCEPTEX(std::is_nothrow_copy_constructible<T>::value)
|
226
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(true)
|
|
614
|
+ template< class U, class... Args >
|
|
615
|
+ void emplace( std::initializer_list<U> il, Args&&... args )
|
227
|
616
|
{
|
228
|
|
- new (pval_) T(val);
|
|
617
|
+ ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
|
229
|
618
|
}
|
230
|
|
- optional(T&& val) _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value)
|
231
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(true)
|
|
619
|
+
|
|
620
|
+#endif
|
|
621
|
+
|
|
622
|
+ void destruct_value()
|
232
|
623
|
{
|
233
|
|
- new (pval_) T(std::move(val));
|
|
624
|
+ value_ptr()->~T();
|
234
|
625
|
}
|
235
|
626
|
|
236
|
|
-#if _CL_OPT_VARIADIC
|
237
|
|
- // In-place constructor of optional with a value
|
238
|
|
- template<typename... Args>
|
239
|
|
- _CL_OPT_CONSTEXPR explicit optional(in_place_t, Args&&... args)
|
240
|
|
- _CL_OPT_NOEXCEPTEX(std::is_nothrow_constructible<T, Args&&...>::value)
|
241
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(true)
|
|
627
|
+ value_type const * value_ptr() const
|
242
|
628
|
{
|
243
|
|
- new (pval_) T(std::forward<Args>(args)...);
|
|
629
|
+ return as<value_type>();
|
244
|
630
|
}
|
245
|
631
|
|
246
|
|
- // Same but with an initializer_list thrown in just for fun
|
247
|
|
- template<typename U, typename... Args,
|
248
|
|
- typename = typename std::enable_if<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, void>::type>
|
249
|
|
- _CL_OPT_CONSTEXPR explicit optional(in_place_t,
|
250
|
|
- std::initializer_list<U> ilist,
|
251
|
|
- Args&&... args)
|
252
|
|
- _CL_OPT_NOEXCEPTEX(std::is_nothrow_constructible<T, std::initializer_list<U>&, Args&&...>::value)
|
253
|
|
- : stg_(), pval_(reinterpret_cast<T*>(&stg_)), has_value_(true)
|
|
632
|
+ value_type * value_ptr()
|
254
|
633
|
{
|
255
|
|
- new (pval_) T(ilist, std::forward<Args>(args)...);
|
|
634
|
+ return as<value_type>();
|
256
|
635
|
}
|
257
|
|
-#endif // _CL_OPT_VARIADIC
|
258
|
636
|
|
259
|
|
- // Destructor
|
260
|
|
- ~optional() _CL_OPT_NOEXCEPTEX(std::is_nothrow_destructible<T>::value) {
|
261
|
|
- if (has_value_) {
|
262
|
|
- // #clp TODO we should not do this for trivially-destructible types as per API
|
263
|
|
- pval_->~T();
|
264
|
|
- }
|
|
637
|
+ value_type const & value() const optional_ref_qual
|
|
638
|
+ {
|
|
639
|
+ return * value_ptr();
|
265
|
640
|
}
|
266
|
641
|
|
267
|
|
- // Assignment operator that clears any held value
|
268
|
|
- optional& operator=(nullopt_t) _CL_OPT_NOEXCEPTEX(std::is_nothrow_destructible<T>::value)
|
|
642
|
+ value_type & value() optional_ref_qual
|
269
|
643
|
{
|
270
|
|
- if (has_value_) {
|
271
|
|
- pval_->~T();
|
272
|
|
- has_value_ = false;
|
273
|
|
- }
|
274
|
|
- return *this;
|
|
644
|
+ return * value_ptr();
|
275
|
645
|
}
|
276
|
646
|
|
277
|
|
- // Copy assignment operator
|
278
|
|
- optional& operator=(const optional& obj) _CL_OPT_NOEXCEPTEX(std::is_nothrow_copy_constructible<T>::value &&
|
279
|
|
- std::is_nothrow_copy_assignable<T>::value &&
|
280
|
|
- std::is_nothrow_destructible<T>::value)
|
281
|
|
- {
|
282
|
|
- if (obj.has_value_) {
|
283
|
|
- if (has_value_) {
|
284
|
|
- // Can assign
|
285
|
|
- *pval_ = *obj.pval_;
|
286
|
|
- } else {
|
287
|
|
- // Need to construct
|
288
|
|
- new (pval_) T(*obj.pval_);
|
289
|
|
- has_value_ = true;
|
290
|
|
- }
|
291
|
|
- } else if (has_value_) {
|
292
|
|
- pval_->~T();
|
293
|
|
- has_value_ = false;
|
294
|
|
- }
|
295
|
|
- return *this;
|
|
647
|
+#if optional_CPP11_OR_GREATER
|
|
648
|
+
|
|
649
|
+ value_type const && value() const optional_refref_qual
|
|
650
|
+ {
|
|
651
|
+ return std::move( value() );
|
296
|
652
|
}
|
297
|
653
|
|
298
|
|
- // Move assignment (note: does not steal has_value_, see API)
|
299
|
|
- optional& operator=(optional&& obj) _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value &&
|
300
|
|
- std::is_nothrow_move_assignable<T>::value &&
|
301
|
|
- std::is_nothrow_destructible<T>::value)
|
302
|
|
- {
|
303
|
|
- if (obj.has_value_) {
|
304
|
|
- if (has_value_) {
|
305
|
|
- // Can assign
|
306
|
|
- *pval_ = std::move(*obj.pval_);
|
307
|
|
- } else {
|
308
|
|
- // Need to construct
|
309
|
|
- new (pval_) T(std::move(*obj.pval_));
|
310
|
|
- has_value_ = true;
|
311
|
|
- }
|
312
|
|
- } else if (has_value_) {
|
313
|
|
- pval_->~T();
|
314
|
|
- has_value_ = false;
|
315
|
|
- }
|
316
|
|
- return *this;
|
|
654
|
+ value_type && value() optional_refref_qual
|
|
655
|
+ {
|
|
656
|
+ return std::move( value() );
|
317
|
657
|
}
|
318
|
658
|
|
319
|
|
-#if _CL_OPT_TEMPL_FUNC_DEF_PARAMS
|
320
|
|
- // Assignment from a value
|
321
|
|
- template<typename U,
|
322
|
|
- typename = typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value, void>::type>
|
323
|
|
- optional& operator=(U&& val)
|
324
|
|
- _CL_OPT_NOEXCEPTEX(std::is_nothrow_constructible<T, U>::value &&
|
325
|
|
- std::is_nothrow_assignable<T, U>::value)
|
326
|
|
- {
|
327
|
|
- if (has_value_) {
|
328
|
|
- // Can assign
|
329
|
|
- *pval_ = std::forward<U>(val);
|
330
|
|
- } else {
|
331
|
|
- // Need to construct
|
332
|
|
- new (pval_) T(std::forward<U>(val));
|
333
|
|
- has_value_ = true;
|
334
|
|
- }
|
335
|
|
- return *this;
|
|
659
|
+#endif
|
|
660
|
+
|
|
661
|
+#if optional_CPP11_OR_GREATER
|
|
662
|
+
|
|
663
|
+ using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
|
|
664
|
+ aligned_storage_t data;
|
|
665
|
+
|
|
666
|
+#elif optional_CONFIG_MAX_ALIGN_HACK
|
|
667
|
+
|
|
668
|
+ typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
|
|
669
|
+
|
|
670
|
+ max_align_t hack;
|
|
671
|
+ aligned_storage_t data;
|
|
672
|
+
|
|
673
|
+#else
|
|
674
|
+ typedef optional_ALIGN_AS(value_type) align_as_type;
|
|
675
|
+
|
|
676
|
+ typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
|
|
677
|
+ aligned_storage_t data;
|
|
678
|
+
|
|
679
|
+# undef optional_ALIGN_AS
|
|
680
|
+
|
|
681
|
+#endif // optional_CONFIG_MAX_ALIGN_HACK
|
|
682
|
+
|
|
683
|
+ void * ptr() optional_noexcept
|
|
684
|
+ {
|
|
685
|
+ return &data;
|
336
|
686
|
}
|
337
|
|
-#endif // _CL_OPT_TEMPL_FUNC_DEF_PARAMS
|
338
|
687
|
|
339
|
|
- // Unchecked operators that access the value
|
340
|
|
- _CL_OPT_CONSTEXPR const T* operator->() const {
|
341
|
|
- return pval_;
|
|
688
|
+ void const * ptr() const optional_noexcept
|
|
689
|
+ {
|
|
690
|
+ return &data;
|
342
|
691
|
}
|
343
|
|
- _CL_OPT_CONSTEXPR T* operator->() {
|
344
|
|
- return pval_;
|
|
692
|
+
|
|
693
|
+ template <typename U>
|
|
694
|
+ U * as()
|
|
695
|
+ {
|
|
696
|
+ return reinterpret_cast<U*>( ptr() );
|
345
|
697
|
}
|
346
|
|
- _CL_OPT_CONSTEXPR const T& operator*() const _CL_OPT_LVALUE_REF_QUALIF {
|
347
|
|
- return *pval_;
|
|
698
|
+
|
|
699
|
+ template <typename U>
|
|
700
|
+ U const * as() const
|
|
701
|
+ {
|
|
702
|
+ return reinterpret_cast<U const *>( ptr() );
|
348
|
703
|
}
|
349
|
|
- _CL_OPT_CONSTEXPR T& operator*() _CL_OPT_LVALUE_REF_QUALIF {
|
350
|
|
- return *pval_;
|
|
704
|
+};
|
|
705
|
+
|
|
706
|
+} // namespace detail
|
|
707
|
+
|
|
708
|
+/// disengaged state tag
|
|
709
|
+
|
|
710
|
+struct nullopt_t
|
|
711
|
+{
|
|
712
|
+ struct init{};
|
|
713
|
+ optional_constexpr nullopt_t( init ) {}
|
|
714
|
+};
|
|
715
|
+
|
|
716
|
+#if optional_HAVE( CONSTEXPR_11 )
|
|
717
|
+constexpr nullopt_t nullopt{ nullopt_t::init{} };
|
|
718
|
+#else
|
|
719
|
+// extra parenthesis to prevent the most vexing parse:
|
|
720
|
+const nullopt_t nullopt(( nullopt_t::init() ));
|
|
721
|
+#endif
|
|
722
|
+
|
|
723
|
+/// optional access error
|
|
724
|
+
|
|
725
|
+class bad_optional_access : public std::logic_error
|
|
726
|
+{
|
|
727
|
+public:
|
|
728
|
+ explicit bad_optional_access()
|
|
729
|
+ : logic_error( "bad optional access" ) {}
|
|
730
|
+};
|
|
731
|
+
|
|
732
|
+/// optional
|
|
733
|
+
|
|
734
|
+template< typename T>
|
|
735
|
+class optional
|
|
736
|
+{
|
|
737
|
+private:
|
|
738
|
+ template< typename > friend class optional;
|
|
739
|
+
|
|
740
|
+ typedef void (optional::*safe_bool)() const;
|
|
741
|
+
|
|
742
|
+public:
|
|
743
|
+ typedef T value_type;
|
|
744
|
+
|
|
745
|
+ // x.x.3.1, constructors
|
|
746
|
+
|
|
747
|
+ // 1a - default construct
|
|
748
|
+ optional_constexpr optional() optional_noexcept
|
|
749
|
+ : has_value_( false )
|
|
750
|
+ , contained()
|
|
751
|
+ {}
|
|
752
|
+
|
|
753
|
+ // 1b - construct explicitly empty
|
|
754
|
+ optional_constexpr optional( nullopt_t ) optional_noexcept
|
|
755
|
+ : has_value_( false )
|
|
756
|
+ , contained()
|
|
757
|
+ {}
|
|
758
|
+
|
|
759
|
+ // 2 - copy-construct
|
|
760
|
+ optional_constexpr14 optional( optional const & other
|
|
761
|
+#if optional_CPP11_OR_GREATER
|
|
762
|
+ optional_REQUIRES_A(
|
|
763
|
+ true || std::is_copy_constructible<T>::value
|
|
764
|
+ )
|
|
765
|
+#endif
|
|
766
|
+ )
|
|
767
|
+ : has_value_( other.has_value() )
|
|
768
|
+ {
|
|
769
|
+ if ( other.has_value() )
|
|
770
|
+ contained.construct_value( other.contained.value() );
|
351
|
771
|
}
|
352
|
|
-#if _CL_OPT_MEMBERS_REF_QUALIFIERS
|
353
|
|
- _CL_OPT_CONSTEXPR const T&& operator*() const && {
|
354
|
|
- return std::move(*pval_);
|
|
772
|
+
|
|
773
|
+#if optional_CPP11_OR_GREATER
|
|
774
|
+
|
|
775
|
+ // 3 (C++11) - move-construct from optional
|
|
776
|
+ optional_constexpr14 optional( optional && other
|
|
777
|
+ optional_REQUIRES_A(
|
|
778
|
+ true || std::is_move_constructible<T>::value
|
|
779
|
+ )
|
|
780
|
+ ) noexcept( std::is_nothrow_move_constructible<T>::value )
|
|
781
|
+ : has_value_( other.has_value() )
|
|
782
|
+ {
|
|
783
|
+ if ( other.has_value() )
|
|
784
|
+ contained.construct_value( std::move( other.contained.value() ) );
|
355
|
785
|
}
|
356
|
|
- _CL_OPT_CONSTEXPR T&& operator*() && {
|
357
|
|
- return std::move(*pval_);
|
|
786
|
+
|
|
787
|
+ // 4 (C++11) - explicit converting copy-construct from optional
|
|
788
|
+ template< typename U >
|
|
789
|
+ explicit optional( optional<U> const & other
|
|
790
|
+ optional_REQUIRES_A(
|
|
791
|
+ std::is_constructible<T, U const &>::value
|
|
792
|
+ && !std::is_constructible<T, optional<U> & >::value
|
|
793
|
+ && !std::is_constructible<T, optional<U> && >::value
|
|
794
|
+ && !std::is_constructible<T, optional<U> const & >::value
|
|
795
|
+ && !std::is_constructible<T, optional<U> const && >::value
|
|
796
|
+ && !std::is_convertible< optional<U> & , T>::value
|
|
797
|
+ && !std::is_convertible< optional<U> && , T>::value
|
|
798
|
+ && !std::is_convertible< optional<U> const & , T>::value
|
|
799
|
+ && !std::is_convertible< optional<U> const &&, T>::value
|
|
800
|
+ && !std::is_convertible< U const & , T>::value /*=> explicit */
|
|
801
|
+ )
|
|
802
|
+ )
|
|
803
|
+ : has_value_( other.has_value() )
|
|
804
|
+ {
|
|
805
|
+ if ( other.has_value() )
|
|
806
|
+ contained.construct_value( other.contained.value() );
|
358
|
807
|
}
|
359
|
|
-#endif // _CL_OPT_MEMBERS_REF_QUALIFIERS
|
|
808
|
+#endif // optional_CPP11_OR_GREATER
|
360
|
809
|
|
361
|
|
- // Value detection
|
362
|
|
- _CL_OPT_CONSTEXPR _CL_OPT_OP_EXPLICIT operator bool() const _CL_OPT_NOEXCEPT {
|
363
|
|
- return has_value_;
|
|
810
|
+ // 4 (C++98 and later) - non-explicit converting copy-construct from optional
|
|
811
|
+ template< typename U >
|
|
812
|
+ optional( optional<U> const & other
|
|
813
|
+#if optional_CPP11_OR_GREATER
|
|
814
|
+ optional_REQUIRES_A(
|
|
815
|
+ std::is_constructible<T, U const &>::value
|
|
816
|
+ && !std::is_constructible<T, optional<U> & >::value
|
|
817
|
+ && !std::is_constructible<T, optional<U> && >::value
|
|
818
|
+ && !std::is_constructible<T, optional<U> const & >::value
|
|
819
|
+ && !std::is_constructible<T, optional<U> const && >::value
|
|
820
|
+ && !std::is_convertible< optional<U> & , T>::value
|
|
821
|
+ && !std::is_convertible< optional<U> && , T>::value
|
|
822
|
+ && !std::is_convertible< optional<U> const & , T>::value
|
|
823
|
+ && !std::is_convertible< optional<U> const &&, T>::value
|
|
824
|
+ && std::is_convertible< U const & , T>::value /*=> non-explicit */
|
|
825
|
+ )
|
|
826
|
+#endif // optional_CPP11_OR_GREATER
|
|
827
|
+ )
|
|
828
|
+ : has_value_( other.has_value() )
|
|
829
|
+ {
|
|
830
|
+ if ( other.has_value() )
|
|
831
|
+ contained.construct_value( other.contained.value() );
|
364
|
832
|
}
|
365
|
|
- _CL_OPT_CONSTEXPR bool has_value() const _CL_OPT_NOEXCEPT {
|
366
|
|
- return has_value_;
|
|
833
|
+
|
|
834
|
+#if optional_CPP11_OR_GREATER
|
|
835
|
+
|
|
836
|
+ // 5a (C++11) - explicit converting move-construct from optional
|
|
837
|
+ template< typename U >
|
|
838
|
+ optional( optional<U> && other
|
|
839
|
+ optional_REQUIRES_A(
|
|
840
|
+ std::is_constructible<T, U const &>::value
|
|
841
|
+ && !std::is_constructible<T, optional<U> & >::value
|
|
842
|
+ && !std::is_constructible<T, optional<U> && >::value
|
|
843
|
+ && !std::is_constructible<T, optional<U> const & >::value
|
|
844
|
+ && !std::is_constructible<T, optional<U> const && >::value
|
|
845
|
+ && !std::is_convertible< optional<U> & , T>::value
|
|
846
|
+ && !std::is_convertible< optional<U> && , T>::value
|
|
847
|
+ && !std::is_convertible< optional<U> const & , T>::value
|
|
848
|
+ && !std::is_convertible< optional<U> const &&, T>::value
|
|
849
|
+ && !std::is_convertible< U &&, T>::value /*=> explicit */
|
|
850
|
+ )
|
|
851
|
+ )
|
|
852
|
+ : has_value_( other.has_value() )
|
|
853
|
+ {
|
|
854
|
+ if ( other.has_value() )
|
|
855
|
+ contained.construct_value( std::move( other.contained.value() ) );
|
367
|
856
|
}
|
368
|
857
|
|
369
|
|
- // Value accessors that throw if optional doesn't have a value
|
370
|
|
- _CL_OPT_CONSTEXPR const T& value() const _CL_OPT_LVALUE_REF_QUALIF {
|
371
|
|
- if (!has_value_) {
|
372
|
|
- throw_bad_optional_access();
|
373
|
|
- }
|
374
|
|
- return *pval_;
|
375
|
|
- }
|
376
|
|
- _CL_OPT_CONSTEXPR T& value() _CL_OPT_LVALUE_REF_QUALIF {
|
377
|
|
- if (!has_value_) {
|
378
|
|
- throw_bad_optional_access();
|
379
|
|
- }
|
380
|
|
- return *pval_;
|
381
|
|
- }
|
382
|
|
-#if _CL_OPT_MEMBERS_REF_QUALIFIERS
|
383
|
|
- _CL_OPT_CONSTEXPR const T&& value() const && {
|
384
|
|
- if (!has_value_) {
|
385
|
|
- throw_bad_optional_access();
|
386
|
|
- }
|
387
|
|
- return std::move(*pval_);
|
388
|
|
- }
|
389
|
|
- _CL_OPT_CONSTEXPR T&& value() && {
|
390
|
|
- if (!has_value_) {
|
391
|
|
- throw_bad_optional_access();
|
392
|
|
- }
|
393
|
|
- return std::move(*pval_);
|
394
|
|
- }
|
395
|
|
-#endif // _CL_OPT_MEMBERS_REF_QUALIFIERS
|
396
|
|
-
|
397
|
|
- // Value accessors with an alternative if optional doesn't have a value
|
398
|
|
- template<typename U>
|
399
|
|
- _CL_OPT_CONSTEXPR T value_or(U&& default_val) const _CL_OPT_LVALUE_REF_QUALIF
|
400
|
|
- _CL_OPT_NOEXCEPTEX(std::is_nothrow_copy_constructible<T>::value &&
|
401
|
|
- std::is_nothrow_constructible<T, U>::value)
|
402
|
|
- {
|
403
|
|
- return has_value_ ? *pval_ : T(std::forward<U>(default_val));
|
404
|
|
- }
|
405
|
|
-#if _CL_OPT_MEMBERS_REF_QUALIFIERS
|
406
|
|
- template<typename U>
|
407
|
|
- _CL_OPT_CONSTEXPR T value_or(U&& default_val) &&
|
408
|
|
- _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value &&
|
409
|
|
- std::is_nothrow_constructible<T, U>::value)
|
410
|
|
- {
|
411
|
|
- return has_value_ ? std::move(*pval_) : T(std::forward<U>(default_val));
|
412
|
|
- }
|
413
|
|
-#endif // _CL_OPT_MEMBERS_REF_QUALIFIERS
|
414
|
|
-
|
415
|
|
- // Swap implementation
|
416
|
|
- void swap(optional& obj) _CL_OPT_NOEXCEPTEX(std::is_nothrow_move_constructible<T>::value &&
|
417
|
|
- std::is_nothrow_destructible<T>::value &&
|
418
|
|
- noexcept(std::swap(std::declval<T&>(), std::declval<T&>()))) // #clp TODO using std::swap here seems wrong, no?
|
419
|
|
- {
|
420
|
|
- if (obj.has_value_) {
|
421
|
|
- if (has_value_) {
|
422
|
|
- using std::swap;
|
423
|
|
- swap(*pval_, *obj.pval_);
|
424
|
|
- } else {
|
425
|
|
- swap_helper(obj, *this);
|
426
|
|
- }
|
427
|
|
- } else if (has_value_) {
|
428
|
|
- swap_helper(*this, obj);
|
429
|
|
- }
|
430
|
|
- }
|
431
|
|
- // Non-member version of swap for ADL
|
432
|
|
- friend void swap(optional& obj1, optional& obj2) {
|
433
|
|
- obj1.swap(obj2);
|
434
|
|
- }
|
435
|
|
-
|
436
|
|
- // Removes any value held
|
437
|
|
- void reset() _CL_OPT_NOEXCEPTEX(std::is_nothrow_destructible<T>::value)
|
438
|
|
- {
|
439
|
|
- if (has_value_) {
|
440
|
|
- pval_->~T();
|
441
|
|
- has_value_ = false;
|
442
|
|
- }
|
443
|
|
- }
|
444
|
|
-
|
445
|
|
-#if _CL_OPT_VARIADIC
|
446
|
|
- // Destroys any held value and constructs a new one in-place
|
447
|
|
- template<typename... Args>
|
448
|
|
- void emplace(Args&&... args) _CL_OPT_NOEXCEPTEX(std::is_nothrow_destructible<T>::value &&
|
449
|
|
- std::is_nothrow_constructible<T, Args...>::value)
|
|
858
|
+ // 5a (C++11) - non-explicit converting move-construct from optional
|
|
859
|
+ template< typename U >
|
|
860
|
+ optional( optional<U> && other
|
|
861
|
+ optional_REQUIRES_A(
|
|
862
|
+ std::is_constructible<T, U const &>::value
|
|
863
|
+ && !std::is_constructible<T, optional<U> & >::value
|
|
864
|
+ && !std::is_constructible<T, optional<U> && >::value
|
|
865
|
+ && !std::is_constructible<T, optional<U> const & >::value
|
|
866
|
+ && !std::is_constructible<T, optional<U> const && >::value
|
|
867
|
+ && !std::is_convertible< optional<U> & , T>::value
|
|
868
|
+ && !std::is_convertible< optional<U> && , T>::value
|
|
869
|
+ && !std::is_convertible< optional<U> const & , T>::value
|
|
870
|
+ && !std::is_convertible< optional<U> const &&, T>::value
|
|
871
|
+ && std::is_convertible< U &&, T>::value /*=> non-explicit */
|
|
872
|
+ )
|
|
873
|
+ )
|
|
874
|
+ : has_value_( other.has_value() )
|
450
|
875
|
{
|
451
|
|
- reset();
|
452
|
|
- new (pval_) T(std::forward<Args>(args)...);
|
453
|
|
- has_value_ = true;
|
|
876
|
+ if ( other.has_value() )
|
|
877
|
+ contained.construct_value( std::move( other.contained.value() ) );
|
|
878
|
+ }
|
|
879
|
+
|
|
880
|
+ // 6 (C++11) - in-place construct
|
|
881
|
+ template< typename... Args
|
|
882
|
+ optional_REQUIRES_T(
|
|
883
|
+ std::is_constructible<T, Args&&...>::value
|
|
884
|
+ )
|
|
885
|
+ >
|
|
886
|
+ optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
|
|
887
|
+ : has_value_( true )
|
|
888
|
+ , contained( T( std::forward<Args>(args)...) )
|
|
889
|
+ {}
|
|
890
|
+
|
|
891
|
+ // 7 (C++11) - in-place construct, initializer-list
|
|
892
|
+ template< typename U, typename... Args
|
|
893
|
+ optional_REQUIRES_T(
|
|
894
|
+ std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
|
|
895
|
+ )
|
|
896
|
+ >
|
|
897
|
+ optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
|
|
898
|
+ : has_value_( true )
|
|
899
|
+ , contained( T( il, std::forward<Args>(args)...) )
|
|
900
|
+ {}
|
|
901
|
+
|
|
902
|
+ // 8a (C++11) - explicit move construct from value
|
|
903
|
+ template< typename U = value_type >
|
|
904
|
+ optional_constexpr explicit optional( U && value
|
|
905
|
+ optional_REQUIRES_A(
|
|
906
|
+ std::is_constructible<T, U&&>::value
|
|
907
|
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
|
|
908
|
+ && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
|
|
909
|
+ && !std::is_convertible<U&&, T>::value /*=> explicit */
|
|
910
|
+ )
|
|
911
|
+ )
|
|
912
|
+ : has_value_( true )
|
|
913
|
+ , contained( std::forward<U>( value ) )
|
|
914
|
+ {}
|
|
915
|
+
|
|
916
|
+ // 8a (C++11) - non-explicit move construct from value
|
|
917
|
+ template< typename U = value_type >
|
|
918
|
+ optional_constexpr optional( U && value
|
|
919
|
+ optional_REQUIRES_A(
|
|
920
|
+ std::is_constructible<T, U&&>::value
|
|
921
|
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
|
|
922
|
+ && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
|
|
923
|
+ && std::is_convertible<U&&, T>::value /*=> non-explicit */
|
|
924
|
+ )
|
|
925
|
+ )
|
|
926
|
+ : has_value_( true )
|
|
927
|
+ , contained( std::forward<U>( value ) )
|
|