diff options
-rw-r--r-- | hkutil/database.h | 213 | ||||
-rw-r--r-- | vendor/variant.hpp | 2457 |
2 files changed, 2670 insertions, 0 deletions
diff --git a/hkutil/database.h b/hkutil/database.h new file mode 100644 index 0000000..c15fa52 --- /dev/null +++ b/hkutil/database.h | |||
@@ -0,0 +1,213 @@ | |||
1 | #ifndef DATABASE_H_0B0A47D2 | ||
2 | #define DATABASE_H_0B0A47D2 | ||
3 | |||
4 | #include <sqlite3.h> | ||
5 | #include <fstream> | ||
6 | #include <sstream> | ||
7 | #include <string> | ||
8 | #include <stdexcept> | ||
9 | #include <list> | ||
10 | #include <memory> | ||
11 | #include "../vendor/variant.hpp" | ||
12 | #include "string.h" | ||
13 | |||
14 | namespace hatkirby { | ||
15 | |||
16 | class sqlite3_error : public std::runtime_error { | ||
17 | public: | ||
18 | |||
19 | sqlite3_error( | ||
20 | const std::string& what, | ||
21 | sqlite3* ppdb) | ||
22 | : std::runtime_error(generateWhat(what, ppdb)) | ||
23 | { | ||
24 | } | ||
25 | |||
26 | private: | ||
27 | |||
28 | static std::string generateWhat( | ||
29 | const std::string& what, | ||
30 | sqlite3* ppdb) | ||
31 | { | ||
32 | std::string errmsg(sqlite3_errmsg(ppdb)); | ||
33 | |||
34 | return what + " (" + errmsg + ")"; | ||
35 | } | ||
36 | |||
37 | }; | ||
38 | |||
39 | enum class dbmode { | ||
40 | read, | ||
41 | readwrite, | ||
42 | create | ||
43 | }; | ||
44 | |||
45 | using binding = | ||
46 | mpark::variant< | ||
47 | std::string, | ||
48 | int>; | ||
49 | |||
50 | using column = | ||
51 | std::tuple< | ||
52 | std::string, | ||
53 | binding>; | ||
54 | |||
55 | class database { | ||
56 | public: | ||
57 | |||
58 | // Constructor | ||
59 | |||
60 | explicit database( | ||
61 | std::string path, | ||
62 | dbmode mode) | ||
63 | { | ||
64 | if (mode == dbmode::create) | ||
65 | { | ||
66 | // If there is already a file at this path, overwrite it. | ||
67 | if (std::ifstream(path)) | ||
68 | { | ||
69 | if (std::remove(path.c_str())) | ||
70 | { | ||
71 | throw std::logic_error("Could not overwrite file at path"); | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | sqlite3* tempDb; | ||
77 | |||
78 | int flags; | ||
79 | |||
80 | if (mode == dbmode::read) | ||
81 | { | ||
82 | flags = SQLITE_OPEN_READONLY; | ||
83 | } else { | ||
84 | flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; | ||
85 | } | ||
86 | |||
87 | int ret = sqlite3_open_v2( | ||
88 | path.c_str(), | ||
89 | &tempDb, | ||
90 | flags, | ||
91 | NULL); | ||
92 | |||
93 | ppdb_ = ppdb_type(tempDb); | ||
94 | |||
95 | if (ret != SQLITE_OK) | ||
96 | { | ||
97 | throw sqlite3_error("Could not create output datafile", ppdb_.get()); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | // Actions | ||
102 | |||
103 | void execute(std::string query) | ||
104 | { | ||
105 | sqlite3_stmt* ppstmt; | ||
106 | |||
107 | if (sqlite3_prepare_v2( | ||
108 | ppdb_.get(), | ||
109 | query.c_str(), | ||
110 | query.length(), | ||
111 | &ppstmt, | ||
112 | NULL) != SQLITE_OK) | ||
113 | { | ||
114 | throw sqlite3_error("Error writing to database", ppdb_.get()); | ||
115 | } | ||
116 | |||
117 | int result = sqlite3_step(ppstmt); | ||
118 | sqlite3_finalize(ppstmt); | ||
119 | |||
120 | if (result != SQLITE_DONE) | ||
121 | { | ||
122 | throw sqlite3_error("Error writing to database", ppdb_.get()); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | void insertIntoTable( | ||
127 | std::string table, | ||
128 | std::list<column> columns) | ||
129 | { | ||
130 | std::list<std::string> fieldNames; | ||
131 | std::list<std::string> qs; | ||
132 | |||
133 | for (const column& c : columns) | ||
134 | { | ||
135 | fieldNames.push_back(std::get<0>(c)); | ||
136 | qs.push_back("?"); | ||
137 | } | ||
138 | |||
139 | std::ostringstream query; | ||
140 | query << "INSERT INTO "; | ||
141 | query << table; | ||
142 | query << " ("; | ||
143 | query << implode(std::begin(fieldNames), std::end(fieldNames), ", "); | ||
144 | query << ") VALUES ("; | ||
145 | query << implode(std::begin(qs), std::end(qs), ", "); | ||
146 | query << ")"; | ||
147 | |||
148 | std::string query_str = query.str(); | ||
149 | |||
150 | sqlite3_stmt* ppstmt; | ||
151 | |||
152 | if (sqlite3_prepare_v2( | ||
153 | ppdb_.get(), | ||
154 | query_str.c_str(), | ||
155 | query_str.length(), | ||
156 | &ppstmt, | ||
157 | NULL) != SQLITE_OK) | ||
158 | { | ||
159 | throw sqlite3_error("Error writing to database", ppdb_.get()); | ||
160 | } | ||
161 | |||
162 | int i = 1; | ||
163 | for (const column& c : columns) | ||
164 | { | ||
165 | const binding& b = std::get<1>(c); | ||
166 | |||
167 | if (mpark::holds_alternative<int>(b)) | ||
168 | { | ||
169 | sqlite3_bind_int(ppstmt, i, mpark::get<int>(b)); | ||
170 | } else if (mpark::holds_alternative<std::string>(b)) | ||
171 | { | ||
172 | const std::string& arg = mpark::get<std::string>(b); | ||
173 | |||
174 | sqlite3_bind_text( | ||
175 | ppstmt, | ||
176 | i, | ||
177 | arg.c_str(), | ||
178 | arg.length(), | ||
179 | SQLITE_TRANSIENT); | ||
180 | } | ||
181 | |||
182 | i++; | ||
183 | } | ||
184 | |||
185 | int result = sqlite3_step(ppstmt); | ||
186 | sqlite3_finalize(ppstmt); | ||
187 | |||
188 | if (result != SQLITE_DONE) | ||
189 | { | ||
190 | throw sqlite3_error("Error writing to database", ppdb_.get()); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | private: | ||
195 | |||
196 | class sqlite3_deleter { | ||
197 | public: | ||
198 | |||
199 | void operator()(sqlite3* ptr) const | ||
200 | { | ||
201 | sqlite3_close_v2(ptr); | ||
202 | } | ||
203 | }; | ||
204 | |||
205 | using ppdb_type = std::unique_ptr<sqlite3, sqlite3_deleter>; | ||
206 | |||
207 | ppdb_type ppdb_; | ||
208 | |||
209 | }; | ||
210 | |||
211 | }; | ||
212 | |||
213 | #endif /* end of include guard: DATABASE_H_0B0A47D2 */ | ||
diff --git a/vendor/variant.hpp b/vendor/variant.hpp new file mode 100644 index 0000000..42f0184 --- /dev/null +++ b/vendor/variant.hpp | |||
@@ -0,0 +1,2457 @@ | |||
1 | // MPark.Variant | ||
2 | // | ||
3 | // Copyright Michael Park, 2015-2017 | ||
4 | // | ||
5 | // Distributed under the Boost Software License, Version 1.0. | ||
6 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | ||
7 | |||
8 | #ifndef MPARK_VARIANT_HPP | ||
9 | #define MPARK_VARIANT_HPP | ||
10 | |||
11 | /* | ||
12 | variant synopsis | ||
13 | |||
14 | namespace std { | ||
15 | |||
16 | // 20.7.2, class template variant | ||
17 | template <class... Types> | ||
18 | class variant { | ||
19 | public: | ||
20 | |||
21 | // 20.7.2.1, constructors | ||
22 | constexpr variant() noexcept(see below); | ||
23 | variant(const variant&); | ||
24 | variant(variant&&) noexcept(see below); | ||
25 | |||
26 | template <class T> constexpr variant(T&&) noexcept(see below); | ||
27 | |||
28 | template <class T, class... Args> | ||
29 | constexpr explicit variant(in_place_type_t<T>, Args&&...); | ||
30 | |||
31 | template <class T, class U, class... Args> | ||
32 | constexpr explicit variant( | ||
33 | in_place_type_t<T>, initializer_list<U>, Args&&...); | ||
34 | |||
35 | template <size_t I, class... Args> | ||
36 | constexpr explicit variant(in_place_index_t<I>, Args&&...); | ||
37 | |||
38 | template <size_t I, class U, class... Args> | ||
39 | constexpr explicit variant( | ||
40 | in_place_index_t<I>, initializer_list<U>, Args&&...); | ||
41 | |||
42 | // 20.7.2.2, destructor | ||
43 | ~variant(); | ||
44 | |||
45 | // 20.7.2.3, assignment | ||
46 | variant& operator=(const variant&); | ||
47 | variant& operator=(variant&&) noexcept(see below); | ||
48 | |||
49 | template <class T> variant& operator=(T&&) noexcept(see below); | ||
50 | |||
51 | // 20.7.2.4, modifiers | ||
52 | template <class T, class... Args> | ||
53 | T& emplace(Args&&...); | ||
54 | |||
55 | template <class T, class U, class... Args> | ||
56 | T& emplace(initializer_list<U>, Args&&...); | ||
57 | |||
58 | template <size_t I, class... Args> | ||
59 | variant_alternative<I, variant>& emplace(Args&&...); | ||
60 | |||
61 | template <size_t I, class U, class... Args> | ||
62 | variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...); | ||
63 | |||
64 | // 20.7.2.5, value status | ||
65 | constexpr bool valueless_by_exception() const noexcept; | ||
66 | constexpr size_t index() const noexcept; | ||
67 | |||
68 | // 20.7.2.6, swap | ||
69 | void swap(variant&) noexcept(see below); | ||
70 | }; | ||
71 | |||
72 | // 20.7.3, variant helper classes | ||
73 | template <class T> struct variant_size; // undefined | ||
74 | |||
75 | template <class T> | ||
76 | constexpr size_t variant_size_v = variant_size<T>::value; | ||
77 | |||
78 | template <class T> struct variant_size<const T>; | ||
79 | template <class T> struct variant_size<volatile T>; | ||
80 | template <class T> struct variant_size<const volatile T>; | ||
81 | |||
82 | template <class... Types> | ||
83 | struct variant_size<variant<Types...>>; | ||
84 | |||
85 | template <size_t I, class T> struct variant_alternative; // undefined | ||
86 | |||
87 | template <size_t I, class T> | ||
88 | using variant_alternative_t = typename variant_alternative<I, T>::type; | ||
89 | |||
90 | template <size_t I, class T> struct variant_alternative<I, const T>; | ||
91 | template <size_t I, class T> struct variant_alternative<I, volatile T>; | ||
92 | template <size_t I, class T> struct variant_alternative<I, const volatile T>; | ||
93 | |||
94 | template <size_t I, class... Types> | ||
95 | struct variant_alternative<I, variant<Types...>>; | ||
96 | |||
97 | constexpr size_t variant_npos = -1; | ||
98 | |||
99 | // 20.7.4, value access | ||
100 | template <class T, class... Types> | ||
101 | constexpr bool holds_alternative(const variant<Types...>&) noexcept; | ||
102 | |||
103 | template <size_t I, class... Types> | ||
104 | constexpr variant_alternative_t<I, variant<Types...>>& | ||
105 | get(variant<Types...>&); | ||
106 | |||
107 | template <size_t I, class... Types> | ||
108 | constexpr variant_alternative_t<I, variant<Types...>>&& | ||
109 | get(variant<Types...>&&); | ||
110 | |||
111 | template <size_t I, class... Types> | ||
112 | constexpr variant_alternative_t<I, variant<Types...>> const& | ||
113 | get(const variant<Types...>&); | ||
114 | |||
115 | template <size_t I, class... Types> | ||
116 | constexpr variant_alternative_t<I, variant<Types...>> const&& | ||
117 | get(const variant<Types...>&&); | ||
118 | |||
119 | template <class T, class... Types> | ||
120 | constexpr T& get(variant<Types...>&); | ||
121 | |||
122 | template <class T, class... Types> | ||
123 | constexpr T&& get(variant<Types...>&&); | ||
124 | |||
125 | template <class T, class... Types> | ||
126 | constexpr const T& get(const variant<Types...>&); | ||
127 | |||
128 | template <class T, class... Types> | ||
129 | constexpr const T&& get(const variant<Types...>&&); | ||
130 | |||
131 | template <size_t I, class... Types> | ||
132 | constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> | ||
133 | get_if(variant<Types...>*) noexcept; | ||
134 | |||
135 | template <size_t I, class... Types> | ||
136 | constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> | ||
137 | get_if(const variant<Types...>*) noexcept; | ||
138 | |||
139 | template <class T, class... Types> | ||
140 | constexpr add_pointer_t<T> | ||
141 | get_if(variant<Types...>*) noexcept; | ||
142 | |||
143 | template <class T, class... Types> | ||
144 | constexpr add_pointer_t<const T> | ||
145 | get_if(const variant<Types...>*) noexcept; | ||
146 | |||
147 | // 20.7.5, relational operators | ||
148 | template <class... Types> | ||
149 | constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); | ||
150 | |||
151 | template <class... Types> | ||
152 | constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); | ||
153 | |||
154 | template <class... Types> | ||
155 | constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); | ||
156 | |||
157 | template <class... Types> | ||
158 | constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); | ||
159 | |||
160 | template <class... Types> | ||
161 | constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); | ||
162 | |||
163 | template <class... Types> | ||
164 | constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); | ||
165 | |||
166 | // 20.7.6, visitation | ||
167 | template <class Visitor, class... Variants> | ||
168 | constexpr see below visit(Visitor&&, Variants&&...); | ||
169 | |||
170 | // 20.7.7, class monostate | ||
171 | struct monostate; | ||
172 | |||
173 | // 20.7.8, monostate relational operators | ||
174 | constexpr bool operator<(monostate, monostate) noexcept; | ||
175 | constexpr bool operator>(monostate, monostate) noexcept; | ||
176 | constexpr bool operator<=(monostate, monostate) noexcept; | ||
177 | constexpr bool operator>=(monostate, monostate) noexcept; | ||
178 | constexpr bool operator==(monostate, monostate) noexcept; | ||
179 | constexpr bool operator!=(monostate, monostate) noexcept; | ||
180 | |||
181 | // 20.7.9, specialized algorithms | ||
182 | template <class... Types> | ||
183 | void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); | ||
184 | |||
185 | // 20.7.10, class bad_variant_access | ||
186 | class bad_variant_access; | ||
187 | |||
188 | // 20.7.11, hash support | ||
189 | template <class T> struct hash; | ||
190 | template <class... Types> struct hash<variant<Types...>>; | ||
191 | template <> struct hash<monostate>; | ||
192 | |||
193 | } // namespace std | ||
194 | |||
195 | */ | ||
196 | |||
197 | #include <cstddef> | ||
198 | #include <exception> | ||
199 | #include <functional> | ||
200 | #include <initializer_list> | ||
201 | #include <new> | ||
202 | #include <type_traits> | ||
203 | #include <utility> | ||
204 | |||
205 | // MPark.Variant | ||
206 | // | ||
207 | // Copyright Michael Park, 2015-2017 | ||
208 | // | ||
209 | // Distributed under the Boost Software License, Version 1.0. | ||
210 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | ||
211 | |||
212 | #ifndef MPARK_CONFIG_HPP | ||
213 | #define MPARK_CONFIG_HPP | ||
214 | |||
215 | // MSVC 2015 Update 3. | ||
216 | #if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) | ||
217 | #error "MPark.Variant requires C++11 support." | ||
218 | #endif | ||
219 | |||
220 | #ifndef __has_builtin | ||
221 | #define __has_builtin(x) 0 | ||
222 | #endif | ||
223 | |||
224 | #ifndef __has_include | ||
225 | #define __has_include(x) 0 | ||
226 | #endif | ||
227 | |||
228 | #ifndef __has_feature | ||
229 | #define __has_feature(x) 0 | ||
230 | #endif | ||
231 | |||
232 | #if __has_builtin(__builtin_addressof) || \ | ||
233 | (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) | ||
234 | #define MPARK_BUILTIN_ADDRESSOF | ||
235 | #endif | ||
236 | |||
237 | #if __has_builtin(__builtin_unreachable) | ||
238 | #define MPARK_BUILTIN_UNREACHABLE | ||
239 | #endif | ||
240 | |||
241 | #if __has_builtin(__type_pack_element) | ||
242 | #define MPARK_TYPE_PACK_ELEMENT | ||
243 | #endif | ||
244 | |||
245 | #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 | ||
246 | #define MPARK_CPP14_CONSTEXPR | ||
247 | #endif | ||
248 | |||
249 | #if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ | ||
250 | (defined(_MSC_VER) && defined(_CPPUNWIND)) | ||
251 | #define MPARK_EXCEPTIONS | ||
252 | #endif | ||
253 | |||
254 | #if defined(__cpp_generic_lambdas) || defined(_MSC_VER) | ||
255 | #define MPARK_GENERIC_LAMBDAS | ||
256 | #endif | ||
257 | |||
258 | #if defined(__cpp_lib_integer_sequence) | ||
259 | #define MPARK_INTEGER_SEQUENCE | ||
260 | #endif | ||
261 | |||
262 | #if defined(__cpp_return_type_deduction) || defined(_MSC_VER) | ||
263 | #define MPARK_RETURN_TYPE_DEDUCTION | ||
264 | #endif | ||
265 | |||
266 | #if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) | ||
267 | #define MPARK_TRANSPARENT_OPERATORS | ||
268 | #endif | ||
269 | |||
270 | #if defined(__cpp_variable_templates) || defined(_MSC_VER) | ||
271 | #define MPARK_VARIABLE_TEMPLATES | ||
272 | #endif | ||
273 | |||
274 | #if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5 | ||
275 | #define MPARK_TRIVIALITY_TYPE_TRAITS | ||
276 | #endif | ||
277 | |||
278 | #endif // MPARK_CONFIG_HPP | ||
279 | |||
280 | // MPark.Variant | ||
281 | // | ||
282 | // Copyright Michael Park, 2015-2017 | ||
283 | // | ||
284 | // Distributed under the Boost Software License, Version 1.0. | ||
285 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | ||
286 | |||
287 | #ifndef MPARK_IN_PLACE_HPP | ||
288 | #define MPARK_IN_PLACE_HPP | ||
289 | |||
290 | #include <cstddef> | ||
291 | |||
292 | |||
293 | namespace mpark { | ||
294 | |||
295 | struct in_place_t { explicit in_place_t() = default; }; | ||
296 | |||
297 | template <std::size_t I> | ||
298 | struct in_place_index_t { explicit in_place_index_t() = default; }; | ||
299 | |||
300 | template <typename T> | ||
301 | struct in_place_type_t { explicit in_place_type_t() = default; }; | ||
302 | |||
303 | #ifdef MPARK_VARIABLE_TEMPLATES | ||
304 | constexpr in_place_t in_place{}; | ||
305 | |||
306 | template <std::size_t I> constexpr in_place_index_t<I> in_place_index{}; | ||
307 | |||
308 | template <typename T> constexpr in_place_type_t<T> in_place_type{}; | ||
309 | #endif | ||
310 | |||
311 | } // namespace mpark | ||
312 | |||
313 | #endif // MPARK_IN_PLACE_HPP | ||
314 | |||
315 | // MPark.Variant | ||
316 | // | ||
317 | // Copyright Michael Park, 2015-2017 | ||
318 | // | ||
319 | // Distributed under the Boost Software License, Version 1.0. | ||
320 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | ||
321 | |||
322 | #ifndef MPARK_LIB_HPP | ||
323 | #define MPARK_LIB_HPP | ||
324 | |||
325 | #include <memory> | ||
326 | #include <functional> | ||
327 | #include <type_traits> | ||
328 | #include <utility> | ||
329 | |||
330 | |||
331 | #define RETURN(...) \ | ||
332 | noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \ | ||
333 | return __VA_ARGS__; \ | ||
334 | } | ||
335 | |||
336 | namespace mpark { | ||
337 | namespace lib { | ||
338 | template <typename T> | ||
339 | struct identity { using type = T; }; | ||
340 | |||
341 | inline namespace cpp14 { | ||
342 | template <typename T, std::size_t N> | ||
343 | struct array { | ||
344 | constexpr const T &operator[](std::size_t index) const { | ||
345 | return data[index]; | ||
346 | } | ||
347 | |||
348 | T data[N == 0 ? 1 : N]; | ||
349 | }; | ||
350 | |||
351 | template <typename T> | ||
352 | using add_pointer_t = typename std::add_pointer<T>::type; | ||
353 | |||
354 | template <typename... Ts> | ||
355 | using common_type_t = typename std::common_type<Ts...>::type; | ||
356 | |||
357 | template <typename T> | ||
358 | using decay_t = typename std::decay<T>::type; | ||
359 | |||
360 | template <bool B, typename T = void> | ||
361 | using enable_if_t = typename std::enable_if<B, T>::type; | ||
362 | |||
363 | template <typename T> | ||
364 | using remove_const_t = typename std::remove_const<T>::type; | ||
365 | |||
366 | template <typename T> | ||
367 | using remove_reference_t = typename std::remove_reference<T>::type; | ||
368 | |||
369 | template <typename T> | ||
370 | inline constexpr T &&forward(remove_reference_t<T> &t) noexcept { | ||
371 | return static_cast<T &&>(t); | ||
372 | } | ||
373 | |||
374 | template <typename T> | ||
375 | inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept { | ||
376 | static_assert(!std::is_lvalue_reference<T>::value, | ||
377 | "can not forward an rvalue as an lvalue"); | ||
378 | return static_cast<T &&>(t); | ||
379 | } | ||
380 | |||
381 | template <typename T> | ||
382 | inline constexpr remove_reference_t<T> &&move(T &&t) noexcept { | ||
383 | return static_cast<remove_reference_t<T> &&>(t); | ||
384 | } | ||
385 | |||
386 | #ifdef MPARK_INTEGER_SEQUENCE | ||
387 | using std::integer_sequence; | ||
388 | using std::index_sequence; | ||
389 | using std::make_index_sequence; | ||
390 | using std::index_sequence_for; | ||
391 | #else | ||
392 | template <typename T, T... Is> | ||
393 | struct integer_sequence { | ||
394 | using value_type = T; | ||
395 | static constexpr std::size_t size() noexcept { return sizeof...(Is); } | ||
396 | }; | ||
397 | |||
398 | template <std::size_t... Is> | ||
399 | using index_sequence = integer_sequence<std::size_t, Is...>; | ||
400 | |||
401 | template <typename Lhs, typename Rhs> | ||
402 | struct make_index_sequence_concat; | ||
403 | |||
404 | template <std::size_t... Lhs, std::size_t... Rhs> | ||
405 | struct make_index_sequence_concat<index_sequence<Lhs...>, | ||
406 | index_sequence<Rhs...>> | ||
407 | : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {}; | ||
408 | |||
409 | template <std::size_t N> | ||
410 | struct make_index_sequence_impl; | ||
411 | |||
412 | template <std::size_t N> | ||
413 | using make_index_sequence = typename make_index_sequence_impl<N>::type; | ||
414 | |||
415 | template <std::size_t N> | ||
416 | struct make_index_sequence_impl | ||
417 | : make_index_sequence_concat<make_index_sequence<N / 2>, | ||
418 | make_index_sequence<N - (N / 2)>> {}; | ||
419 | |||
420 | template <> | ||
421 | struct make_index_sequence_impl<0> : identity<index_sequence<>> {}; | ||
422 | |||
423 | template <> | ||
424 | struct make_index_sequence_impl<1> : identity<index_sequence<0>> {}; | ||
425 | |||
426 | template <typename... Ts> | ||
427 | using index_sequence_for = make_index_sequence<sizeof...(Ts)>; | ||
428 | #endif | ||
429 | |||
430 | // <functional> | ||
431 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
432 | using equal_to = std::equal_to<>; | ||
433 | #else | ||
434 | struct equal_to { | ||
435 | template <typename Lhs, typename Rhs> | ||
436 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
437 | RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs)) | ||
438 | }; | ||
439 | #endif | ||
440 | |||
441 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
442 | using not_equal_to = std::not_equal_to<>; | ||
443 | #else | ||
444 | struct not_equal_to { | ||
445 | template <typename Lhs, typename Rhs> | ||
446 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
447 | RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs)) | ||
448 | }; | ||
449 | #endif | ||
450 | |||
451 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
452 | using less = std::less<>; | ||
453 | #else | ||
454 | struct less { | ||
455 | template <typename Lhs, typename Rhs> | ||
456 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
457 | RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs)) | ||
458 | }; | ||
459 | #endif | ||
460 | |||
461 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
462 | using greater = std::greater<>; | ||
463 | #else | ||
464 | struct greater { | ||
465 | template <typename Lhs, typename Rhs> | ||
466 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
467 | RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs)) | ||
468 | }; | ||
469 | #endif | ||
470 | |||
471 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
472 | using less_equal = std::less_equal<>; | ||
473 | #else | ||
474 | struct less_equal { | ||
475 | template <typename Lhs, typename Rhs> | ||
476 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
477 | RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs)) | ||
478 | }; | ||
479 | #endif | ||
480 | |||
481 | #ifdef MPARK_TRANSPARENT_OPERATORS | ||
482 | using greater_equal = std::greater_equal<>; | ||
483 | #else | ||
484 | struct greater_equal { | ||
485 | template <typename Lhs, typename Rhs> | ||
486 | inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const | ||
487 | RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs)) | ||
488 | }; | ||
489 | #endif | ||
490 | } // namespace cpp14 | ||
491 | |||
492 | inline namespace cpp17 { | ||
493 | |||
494 | // <type_traits> | ||
495 | template <bool B> | ||
496 | using bool_constant = std::integral_constant<bool, B>; | ||
497 | |||
498 | template <typename...> | ||
499 | struct voider : identity<void> {}; | ||
500 | |||
501 | template <typename... Ts> | ||
502 | using void_t = typename voider<Ts...>::type; | ||
503 | |||
504 | namespace detail { | ||
505 | namespace swappable { | ||
506 | |||
507 | using std::swap; | ||
508 | |||
509 | template <typename T> | ||
510 | struct is_swappable { | ||
511 | private: | ||
512 | template <typename U, | ||
513 | typename = decltype(swap(std::declval<U &>(), | ||
514 | std::declval<U &>()))> | ||
515 | inline static std::true_type test(int); | ||
516 | |||
517 | template <typename U> | ||
518 | inline static std::false_type test(...); | ||
519 | |||
520 | public: | ||
521 | static constexpr bool value = decltype(test<T>(0))::value; | ||
522 | }; | ||
523 | |||
524 | template <typename T, bool = is_swappable<T>::value> | ||
525 | struct is_nothrow_swappable { | ||
526 | static constexpr bool value = | ||
527 | noexcept(swap(std::declval<T &>(), std::declval<T &>())); | ||
528 | }; | ||
529 | |||
530 | template <typename T> | ||
531 | struct is_nothrow_swappable<T, false> : std::false_type {}; | ||
532 | |||
533 | } // namespace swappable | ||
534 | } // namespace detail | ||
535 | |||
536 | using detail::swappable::is_swappable; | ||
537 | using detail::swappable::is_nothrow_swappable; | ||
538 | |||
539 | // <functional> | ||
540 | #ifdef _MSC_VER | ||
541 | #pragma warning(push) | ||
542 | #pragma warning(disable : 4100) | ||
543 | #endif | ||
544 | template <typename F, typename... As> | ||
545 | inline constexpr auto invoke(F &&f, As &&... as) | ||
546 | RETURN(lib::forward<F>(f)(lib::forward<As>(as)...)) | ||
547 | #ifdef _MSC_VER | ||
548 | #pragma warning(pop) | ||
549 | #endif | ||
550 | |||
551 | template <typename B, typename T, typename D> | ||
552 | inline constexpr auto invoke(T B::*pmv, D &&d) | ||
553 | RETURN(lib::forward<D>(d).*pmv) | ||
554 | |||
555 | template <typename Pmv, typename Ptr> | ||
556 | inline constexpr auto invoke(Pmv pmv, Ptr &&ptr) | ||
557 | RETURN((*lib::forward<Ptr>(ptr)).*pmv) | ||
558 | |||
559 | template <typename B, typename T, typename D, typename... As> | ||
560 | inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as) | ||
561 | RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...)) | ||
562 | |||
563 | template <typename Pmf, typename Ptr, typename... As> | ||
564 | inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as) | ||
565 | RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...)) | ||
566 | |||
567 | namespace detail { | ||
568 | |||
569 | template <typename Void, typename, typename...> | ||
570 | struct invoke_result {}; | ||
571 | |||
572 | template <typename F, typename... Args> | ||
573 | struct invoke_result<void_t<decltype(lib::invoke( | ||
574 | std::declval<F>(), std::declval<Args>()...))>, | ||
575 | F, | ||
576 | Args...> | ||
577 | : identity<decltype( | ||
578 | lib::invoke(std::declval<F>(), std::declval<Args>()...))> {}; | ||
579 | |||
580 | } // namespace detail | ||
581 | |||
582 | template <typename F, typename... Args> | ||
583 | using invoke_result = detail::invoke_result<void, F, Args...>; | ||
584 | |||
585 | template <typename F, typename... Args> | ||
586 | using invoke_result_t = typename invoke_result<F, Args...>::type; | ||
587 | |||
588 | namespace detail { | ||
589 | |||
590 | template <typename Void, typename, typename...> | ||
591 | struct is_invocable : std::false_type {}; | ||
592 | |||
593 | template <typename F, typename... Args> | ||
594 | struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> | ||
595 | : std::true_type {}; | ||
596 | |||
597 | template <typename Void, typename, typename, typename...> | ||
598 | struct is_invocable_r : std::false_type {}; | ||
599 | |||
600 | template <typename R, typename F, typename... Args> | ||
601 | struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, | ||
602 | R, | ||
603 | F, | ||
604 | Args...> | ||
605 | : std::is_convertible<invoke_result_t<F, Args...>, R> {}; | ||
606 | |||
607 | } // namespace detail | ||
608 | |||
609 | template <typename F, typename... Args> | ||
610 | using is_invocable = detail::is_invocable<void, F, Args...>; | ||
611 | |||
612 | template <typename R, typename F, typename... Args> | ||
613 | using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>; | ||
614 | |||
615 | // <memory> | ||
616 | #ifdef MPARK_BUILTIN_ADDRESSOF | ||
617 | template <typename T> | ||
618 | inline constexpr T *addressof(T &arg) { | ||
619 | return __builtin_addressof(arg); | ||
620 | } | ||
621 | #else | ||
622 | namespace detail { | ||
623 | |||
624 | namespace has_addressof_impl { | ||
625 | |||
626 | struct fail; | ||
627 | |||
628 | template <typename T> | ||
629 | inline fail operator&(T &&); | ||
630 | |||
631 | template <typename T> | ||
632 | inline static constexpr bool impl() { | ||
633 | return (std::is_class<T>::value || std::is_union<T>::value) && | ||
634 | !std::is_same<decltype(&std::declval<T &>()), fail>::value; | ||
635 | } | ||
636 | |||
637 | } // namespace has_addressof_impl | ||
638 | |||
639 | template <typename T> | ||
640 | using has_addressof = bool_constant<has_addressof_impl::impl<T>()>; | ||
641 | |||
642 | template <typename T> | ||
643 | inline constexpr T *addressof(T &arg, std::true_type) { | ||
644 | return std::addressof(arg); | ||
645 | } | ||
646 | |||
647 | template <typename T> | ||
648 | inline constexpr T *addressof(T &arg, std::false_type) { | ||
649 | return &arg; | ||
650 | } | ||
651 | |||
652 | } // namespace detail | ||
653 | |||
654 | template <typename T> | ||
655 | inline constexpr T *addressof(T &arg) { | ||
656 | return detail::addressof(arg, detail::has_addressof<T>{}); | ||
657 | } | ||
658 | #endif | ||
659 | |||
660 | template <typename T> | ||
661 | inline constexpr T *addressof(const T &&) = delete; | ||
662 | |||
663 | } // namespace cpp17 | ||
664 | |||
665 | template <typename T> | ||
666 | struct remove_all_extents : identity<T> {}; | ||
667 | |||
668 | template <typename T, std::size_t N> | ||
669 | struct remove_all_extents<array<T, N>> : remove_all_extents<T> {}; | ||
670 | |||
671 | template <typename T> | ||
672 | using remove_all_extents_t = typename remove_all_extents<T>::type; | ||
673 | |||
674 | template <std::size_t N> | ||
675 | using size_constant = std::integral_constant<std::size_t, N>; | ||
676 | |||
677 | template <std::size_t I, typename T> | ||
678 | struct indexed_type : size_constant<I>, identity<T> {}; | ||
679 | |||
680 | template <bool... Bs> | ||
681 | using all = std::is_same<integer_sequence<bool, true, Bs...>, | ||
682 | integer_sequence<bool, Bs..., true>>; | ||
683 | |||
684 | #ifdef MPARK_TYPE_PACK_ELEMENT | ||
685 | template <std::size_t I, typename... Ts> | ||
686 | using type_pack_element_t = __type_pack_element<I, Ts...>; | ||
687 | #else | ||
688 | template <std::size_t I, typename... Ts> | ||
689 | struct type_pack_element_impl { | ||
690 | private: | ||
691 | template <typename> | ||
692 | struct set; | ||
693 | |||
694 | template <std::size_t... Is> | ||
695 | struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {}; | ||
696 | |||
697 | template <typename T> | ||
698 | inline static std::enable_if<true, T> impl(indexed_type<I, T>); | ||
699 | |||
700 | inline static std::enable_if<false> impl(...); | ||
701 | |||
702 | public: | ||
703 | using type = decltype(impl(set<index_sequence_for<Ts...>>{})); | ||
704 | }; | ||
705 | |||
706 | template <std::size_t I, typename... Ts> | ||
707 | using type_pack_element = typename type_pack_element_impl<I, Ts...>::type; | ||
708 | |||
709 | template <std::size_t I, typename... Ts> | ||
710 | using type_pack_element_t = typename type_pack_element<I, Ts...>::type; | ||
711 | #endif | ||
712 | |||
713 | #ifdef MPARK_TRIVIALITY_TYPE_TRAITS | ||
714 | using std::is_trivially_copy_constructible; | ||
715 | using std::is_trivially_move_constructible; | ||
716 | using std::is_trivially_copy_assignable; | ||
717 | using std::is_trivially_move_assignable; | ||
718 | #else | ||
719 | template <typename T> | ||
720 | struct is_trivially_copy_constructible | ||
721 | : bool_constant< | ||
722 | std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {}; | ||
723 | |||
724 | template <typename T> | ||
725 | struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; | ||
726 | |||
727 | template <typename T> | ||
728 | struct is_trivially_copy_assignable | ||
729 | : bool_constant< | ||
730 | std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {}; | ||
731 | |||
732 | template <typename T> | ||
733 | struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; | ||
734 | #endif | ||
735 | |||
736 | template <typename T, bool> | ||
737 | struct dependent_type : T {}; | ||
738 | |||
739 | template <typename Is, std::size_t J> | ||
740 | struct push_back; | ||
741 | |||
742 | template <typename Is, std::size_t J> | ||
743 | using push_back_t = typename push_back<Is, J>::type; | ||
744 | |||
745 | template <std::size_t... Is, std::size_t J> | ||
746 | struct push_back<index_sequence<Is...>, J> { | ||
747 | using type = index_sequence<Is..., J>; | ||
748 | }; | ||
749 | |||
750 | } // namespace lib | ||
751 | } // namespace mpark | ||
752 | |||
753 | #undef RETURN | ||
754 | |||
755 | #endif // MPARK_LIB_HPP | ||
756 | |||
757 | |||
758 | namespace mpark { | ||
759 | |||
760 | #ifdef MPARK_RETURN_TYPE_DEDUCTION | ||
761 | |||
762 | #define AUTO auto | ||
763 | #define AUTO_RETURN(...) { return __VA_ARGS__; } | ||
764 | |||
765 | #define AUTO_REFREF auto && | ||
766 | #define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } | ||
767 | |||
768 | #define DECLTYPE_AUTO decltype(auto) | ||
769 | #define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } | ||
770 | |||
771 | #else | ||
772 | |||
773 | #define AUTO auto | ||
774 | #define AUTO_RETURN(...) \ | ||
775 | -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; } | ||
776 | |||
777 | #define AUTO_REFREF auto | ||
778 | #define AUTO_REFREF_RETURN(...) \ | ||
779 | -> decltype((__VA_ARGS__)) { \ | ||
780 | static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \ | ||
781 | return __VA_ARGS__; \ | ||
782 | } | ||
783 | |||
784 | #define DECLTYPE_AUTO auto | ||
785 | #define DECLTYPE_AUTO_RETURN(...) \ | ||
786 | -> decltype(__VA_ARGS__) { return __VA_ARGS__; } | ||
787 | |||
788 | #endif | ||
789 | |||
790 | class bad_variant_access : public std::exception { | ||
791 | public: | ||
792 | virtual const char *what() const noexcept { return "bad_variant_access"; } | ||
793 | }; | ||
794 | |||
795 | [[noreturn]] inline void throw_bad_variant_access() { | ||
796 | #ifdef MPARK_EXCEPTIONS | ||
797 | throw bad_variant_access{}; | ||
798 | #else | ||
799 | std::terminate(); | ||
800 | #ifdef MPARK_BUILTIN_UNREACHABLE | ||
801 | __builtin_unreachable(); | ||
802 | #endif | ||
803 | #endif | ||
804 | } | ||
805 | |||
806 | template <typename... Ts> | ||
807 | class variant; | ||
808 | |||
809 | template <typename T> | ||
810 | struct variant_size; | ||
811 | |||
812 | #ifdef MPARK_VARIABLE_TEMPLATES | ||
813 | template <typename T> | ||
814 | constexpr std::size_t variant_size_v = variant_size<T>::value; | ||
815 | #endif | ||
816 | |||
817 | template <typename T> | ||
818 | struct variant_size<const T> : variant_size<T> {}; | ||
819 | |||
820 | template <typename T> | ||
821 | struct variant_size<volatile T> : variant_size<T> {}; | ||
822 | |||
823 | template <typename T> | ||
824 | struct variant_size<const volatile T> : variant_size<T> {}; | ||
825 | |||
826 | template <typename... Ts> | ||
827 | struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {}; | ||
828 | |||
829 | template <std::size_t I, typename T> | ||
830 | struct variant_alternative; | ||
831 | |||
832 | template <std::size_t I, typename T> | ||
833 | using variant_alternative_t = typename variant_alternative<I, T>::type; | ||
834 | |||
835 | template <std::size_t I, typename T> | ||
836 | struct variant_alternative<I, const T> | ||
837 | : std::add_const<variant_alternative_t<I, T>> {}; | ||
838 | |||
839 | template <std::size_t I, typename T> | ||
840 | struct variant_alternative<I, volatile T> | ||
841 | : std::add_volatile<variant_alternative_t<I, T>> {}; | ||
842 | |||
843 | template <std::size_t I, typename T> | ||
844 | struct variant_alternative<I, const volatile T> | ||
845 | : std::add_cv<variant_alternative_t<I, T>> {}; | ||
846 | |||
847 | template <std::size_t I, typename... Ts> | ||
848 | struct variant_alternative<I, variant<Ts...>> { | ||
849 | static_assert(I < sizeof...(Ts), | ||
850 | "Index out of bounds in std::variant_alternative<>"); | ||
851 | using type = lib::type_pack_element_t<I, Ts...>; | ||
852 | }; | ||
853 | |||
854 | constexpr std::size_t variant_npos = static_cast<std::size_t>(-1); | ||
855 | |||
856 | namespace detail { | ||
857 | |||
858 | constexpr std::size_t not_found = static_cast<std::size_t>(-1); | ||
859 | constexpr std::size_t ambiguous = static_cast<std::size_t>(-2); | ||
860 | |||
861 | #ifdef MPARK_CPP14_CONSTEXPR | ||
862 | template <typename T, typename... Ts> | ||
863 | inline constexpr std::size_t find_index() { | ||
864 | constexpr lib::array<bool, sizeof...(Ts)> matches = { | ||
865 | {std::is_same<T, Ts>::value...} | ||
866 | }; | ||
867 | std::size_t result = not_found; | ||
868 | for (std::size_t i = 0; i < sizeof...(Ts); ++i) { | ||
869 | if (matches[i]) { | ||
870 | if (result != not_found) { | ||
871 | return ambiguous; | ||
872 | } | ||
873 | result = i; | ||
874 | } | ||
875 | } | ||
876 | return result; | ||
877 | } | ||
878 | #else | ||
879 | inline constexpr std::size_t find_index_impl(std::size_t result, | ||
880 | std::size_t) { | ||
881 | return result; | ||
882 | } | ||
883 | |||
884 | template <typename... Bs> | ||
885 | inline constexpr std::size_t find_index_impl(std::size_t result, | ||
886 | std::size_t idx, | ||
887 | bool b, | ||
888 | Bs... bs) { | ||
889 | return b ? (result != not_found ? ambiguous | ||
890 | : find_index_impl(idx, idx + 1, bs...)) | ||
891 | : find_index_impl(result, idx + 1, bs...); | ||
892 | } | ||
893 | |||
894 | template <typename T, typename... Ts> | ||
895 | inline constexpr std::size_t find_index() { | ||
896 | return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...); | ||
897 | } | ||
898 | #endif | ||
899 | |||
900 | template <std::size_t I> | ||
901 | using find_index_sfinae_impl = | ||
902 | lib::enable_if_t<I != not_found && I != ambiguous, | ||
903 | lib::size_constant<I>>; | ||
904 | |||
905 | template <typename T, typename... Ts> | ||
906 | using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>; | ||
907 | |||
908 | template <std::size_t I> | ||
909 | struct find_index_checked_impl : lib::size_constant<I> { | ||
910 | static_assert(I != not_found, "the specified type is not found."); | ||
911 | static_assert(I != ambiguous, "the specified type is ambiguous."); | ||
912 | }; | ||
913 | |||
914 | template <typename T, typename... Ts> | ||
915 | using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>; | ||
916 | |||
917 | struct valueless_t {}; | ||
918 | |||
919 | enum class Trait { TriviallyAvailable, Available, Unavailable }; | ||
920 | |||
921 | template <typename T, | ||
922 | template <typename> class IsTriviallyAvailable, | ||
923 | template <typename> class IsAvailable> | ||
924 | inline constexpr Trait trait() { | ||
925 | return IsTriviallyAvailable<T>::value | ||
926 | ? Trait::TriviallyAvailable | ||
927 | : IsAvailable<T>::value ? Trait::Available | ||
928 | : Trait::Unavailable; | ||
929 | } | ||
930 | |||
931 | #ifdef MPARK_CPP14_CONSTEXPR | ||
932 | template <typename... Traits> | ||
933 | inline constexpr Trait common_trait(Traits... traits) { | ||
934 | Trait result = Trait::TriviallyAvailable; | ||
935 | for (Trait t : {traits...}) { | ||
936 | if (static_cast<int>(t) > static_cast<int>(result)) { | ||
937 | result = t; | ||
938 | } | ||
939 | } | ||
940 | return result; | ||
941 | } | ||
942 | #else | ||
943 | inline constexpr Trait common_trait_impl(Trait result) { return result; } | ||
944 | |||
945 | template <typename... Traits> | ||
946 | inline constexpr Trait common_trait_impl(Trait result, | ||
947 | Trait t, | ||
948 | Traits... ts) { | ||
949 | return static_cast<int>(t) > static_cast<int>(result) | ||
950 | ? common_trait_impl(t, ts...) | ||
951 | : common_trait_impl(result, ts...); | ||
952 | } | ||
953 | |||
954 | template <typename... Traits> | ||
955 | inline constexpr Trait common_trait(Traits... ts) { | ||
956 | return common_trait_impl(Trait::TriviallyAvailable, ts...); | ||
957 | } | ||
958 | #endif | ||
959 | |||
960 | template <typename... Ts> | ||
961 | struct traits { | ||
962 | static constexpr Trait copy_constructible_trait = | ||
963 | common_trait(trait<Ts, | ||
964 | lib::is_trivially_copy_constructible, | ||
965 | std::is_copy_constructible>()...); | ||
966 | |||
967 | static constexpr Trait move_constructible_trait = | ||
968 | common_trait(trait<Ts, | ||
969 | lib::is_trivially_move_constructible, | ||
970 | std::is_move_constructible>()...); | ||
971 | |||
972 | static constexpr Trait copy_assignable_trait = | ||
973 | common_trait(copy_constructible_trait, | ||
974 | trait<Ts, | ||
975 | lib::is_trivially_copy_assignable, | ||
976 | std::is_copy_assignable>()...); | ||
977 | |||
978 | static constexpr Trait move_assignable_trait = | ||
979 | common_trait(move_constructible_trait, | ||
980 | trait<Ts, | ||
981 | lib::is_trivially_move_assignable, | ||
982 | std::is_move_assignable>()...); | ||
983 | |||
984 | static constexpr Trait destructible_trait = | ||
985 | common_trait(trait<Ts, | ||
986 | std::is_trivially_destructible, | ||
987 | std::is_destructible>()...); | ||
988 | }; | ||
989 | |||
990 | namespace access { | ||
991 | |||
992 | struct recursive_union { | ||
993 | #ifdef MPARK_RETURN_TYPE_DEDUCTION | ||
994 | template <typename V> | ||
995 | inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { | ||
996 | return lib::forward<V>(v).head_; | ||
997 | } | ||
998 | |||
999 | template <typename V, std::size_t I> | ||
1000 | inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) { | ||
1001 | return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{}); | ||
1002 | } | ||
1003 | #else | ||
1004 | template <std::size_t I, bool Dummy = true> | ||
1005 | struct get_alt_impl { | ||
1006 | template <typename V> | ||
1007 | inline constexpr AUTO_REFREF operator()(V &&v) const | ||
1008 | AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_)) | ||
1009 | }; | ||
1010 | |||
1011 | template <bool Dummy> | ||
1012 | struct get_alt_impl<0, Dummy> { | ||
1013 | template <typename V> | ||
1014 | inline constexpr AUTO_REFREF operator()(V &&v) const | ||
1015 | AUTO_REFREF_RETURN(lib::forward<V>(v).head_) | ||
1016 | }; | ||
1017 | |||
1018 | template <typename V, std::size_t I> | ||
1019 | inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>) | ||
1020 | AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v))) | ||
1021 | #endif | ||
1022 | }; | ||
1023 | |||
1024 | struct base { | ||
1025 | template <std::size_t I, typename V> | ||
1026 | inline static constexpr AUTO_REFREF get_alt(V &&v) | ||
1027 | AUTO_REFREF_RETURN(recursive_union::get_alt( | ||
1028 | data(lib::forward<V>(v)), in_place_index_t<I>{})) | ||
1029 | }; | ||
1030 | |||
1031 | struct variant { | ||
1032 | template <std::size_t I, typename V> | ||
1033 | inline static constexpr AUTO_REFREF get_alt(V &&v) | ||
1034 | AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_)) | ||
1035 | }; | ||
1036 | |||
1037 | } // namespace access | ||
1038 | |||
1039 | namespace visitation { | ||
1040 | |||
1041 | struct base { | ||
1042 | template <typename T> | ||
1043 | inline static constexpr const T &at(const T &elem) { | ||
1044 | return elem; | ||
1045 | } | ||
1046 | |||
1047 | template <typename T, std::size_t N, typename... Is> | ||
1048 | inline static constexpr const lib::remove_all_extents_t<T> &at( | ||
1049 | const lib::array<T, N> &elems, std::size_t i, Is... is) { | ||
1050 | return at(elems[i], is...); | ||
1051 | } | ||
1052 | |||
1053 | template <typename F, typename... Fs> | ||
1054 | inline static constexpr int visit_visitor_return_type_check() { | ||
1055 | static_assert(lib::all<std::is_same<F, Fs>::value...>::value, | ||
1056 | "`mpark::visit` requires the visitor to have a single " | ||
1057 | "return type."); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | template <typename... Fs> | ||
1062 | inline static constexpr lib::array< | ||
1063 | lib::common_type_t<lib::decay_t<Fs>...>, | ||
1064 | sizeof...(Fs)> | ||
1065 | make_farray(Fs &&... fs) { | ||
1066 | using result = lib::array<lib::common_type_t<lib::decay_t<Fs>...>, | ||
1067 | sizeof...(Fs)>; | ||
1068 | return visit_visitor_return_type_check<lib::decay_t<Fs>...>(), | ||
1069 | result{{lib::forward<Fs>(fs)...}}; | ||
1070 | } | ||
1071 | |||
1072 | template <std::size_t... Is> | ||
1073 | struct dispatcher { | ||
1074 | template <typename F, typename... Vs> | ||
1075 | struct impl { | ||
1076 | inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs) | ||
1077 | DECLTYPE_AUTO_RETURN(lib::invoke( | ||
1078 | static_cast<F>(f), | ||
1079 | access::base::get_alt<Is>(static_cast<Vs>(vs))...)) | ||
1080 | }; | ||
1081 | }; | ||
1082 | |||
1083 | template <typename F, typename... Vs, std::size_t... Is> | ||
1084 | inline static constexpr AUTO make_dispatch(lib::index_sequence<Is...>) | ||
1085 | AUTO_RETURN(&dispatcher<Is...>::template impl<F, Vs...>::dispatch) | ||
1086 | |||
1087 | template <std::size_t I, typename F, typename... Vs> | ||
1088 | inline static constexpr AUTO make_fdiagonal_impl() | ||
1089 | AUTO_RETURN(make_dispatch<F, Vs...>( | ||
1090 | lib::index_sequence<lib::indexed_type<I, Vs>::value...>{})) | ||
1091 | |||
1092 | template <typename F, typename... Vs, std::size_t... Is> | ||
1093 | inline static constexpr AUTO make_fdiagonal_impl( | ||
1094 | lib::index_sequence<Is...>) | ||
1095 | AUTO_RETURN(make_farray(make_fdiagonal_impl<Is, F, Vs...>()...)) | ||
1096 | |||
1097 | template <typename F, typename V, typename... Vs> | ||
1098 | inline static constexpr /* auto * */ auto make_fdiagonal() | ||
1099 | -> decltype(make_fdiagonal_impl<F, V, Vs...>( | ||
1100 | lib::make_index_sequence<lib::decay_t<V>::size()>{})) { | ||
1101 | static_assert(lib::all<(lib::decay_t<V>::size() == | ||
1102 | lib::decay_t<Vs>::size())...>::value, | ||
1103 | "all of the variants must be the same size."); | ||
1104 | return make_fdiagonal_impl<F, V, Vs...>( | ||
1105 | lib::make_index_sequence<lib::decay_t<V>::size()>{}); | ||
1106 | } | ||
1107 | |||
1108 | #ifdef MPARK_RETURN_TYPE_DEDUCTION | ||
1109 | template <typename F, typename... Vs, typename Is> | ||
1110 | inline static constexpr auto make_fmatrix_impl(Is is) { | ||
1111 | return make_dispatch<F, Vs...>(is); | ||
1112 | } | ||
1113 | |||
1114 | template <typename F, | ||
1115 | typename... Vs, | ||
1116 | typename Is, | ||
1117 | std::size_t... Js, | ||
1118 | typename... Ls> | ||
1119 | inline static constexpr auto make_fmatrix_impl( | ||
1120 | Is, lib::index_sequence<Js...>, Ls... ls) { | ||
1121 | return make_farray(make_fmatrix_impl<F, Vs...>( | ||
1122 | lib::push_back_t<Is, Js>{}, ls...)...); | ||
1123 | } | ||
1124 | |||
1125 | template <typename F, typename... Vs> | ||
1126 | inline static constexpr auto make_fmatrix() { | ||
1127 | return make_fmatrix_impl<F, Vs...>( | ||
1128 | lib::index_sequence<>{}, | ||
1129 | lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...); | ||
1130 | } | ||
1131 | #else | ||
1132 | template <typename F, typename... Vs> | ||
1133 | struct make_fmatrix_impl { | ||
1134 | template <typename...> | ||
1135 | struct impl; | ||
1136 | |||
1137 | template <typename Is> | ||
1138 | struct impl<Is> { | ||
1139 | inline constexpr AUTO operator()() const | ||
1140 | AUTO_RETURN(make_dispatch<F, Vs...>(Is{})) | ||
1141 | }; | ||
1142 | |||
1143 | template <typename Is, std::size_t... Js, typename... Ls> | ||
1144 | struct impl<Is, lib::index_sequence<Js...>, Ls...> { | ||
1145 | inline constexpr AUTO operator()() const | ||
1146 | AUTO_RETURN( | ||
1147 | make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...)) | ||
1148 | }; | ||
1149 | }; | ||
1150 | |||
1151 | template <typename F, typename... Vs> | ||
1152 | inline static constexpr AUTO make_fmatrix() | ||
1153 | AUTO_RETURN( | ||
1154 | typename make_fmatrix_impl<F, Vs...>::template impl< | ||
1155 | lib::index_sequence<>, | ||
1156 | lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}()) | ||
1157 | #endif | ||
1158 | }; // namespace base | ||
1159 | |||
1160 | template <typename F, typename... Vs> | ||
1161 | using FDiagonal = decltype(base::make_fdiagonal<F, Vs...>()); | ||
1162 | |||
1163 | template <typename F, typename... Vs> | ||
1164 | struct fdiagonal { | ||
1165 | #ifdef _MSC_VER | ||
1166 | #pragma warning(push) | ||
1167 | #pragma warning(disable : 4268) | ||
1168 | #endif | ||
1169 | static constexpr FDiagonal<F, Vs...> value = | ||
1170 | base::make_fdiagonal<F, Vs...>(); | ||
1171 | #ifdef _MSC_VER | ||
1172 | #pragma warning(pop) | ||
1173 | #endif | ||
1174 | }; | ||
1175 | |||
1176 | template <typename F, typename... Vs> | ||
1177 | constexpr FDiagonal<F, Vs...> fdiagonal<F, Vs...>::value; | ||
1178 | |||
1179 | template <typename F, typename... Vs> | ||
1180 | using FMatrix = decltype(base::make_fmatrix<F, Vs...>()); | ||
1181 | |||
1182 | template <typename F, typename... Vs> | ||
1183 | struct fmatrix { | ||
1184 | #ifdef _MSC_VER | ||
1185 | #pragma warning(push) | ||
1186 | #pragma warning(disable : 4268) | ||
1187 | #endif | ||
1188 | static constexpr FMatrix<F, Vs...> value = | ||
1189 | base::make_fmatrix<F, Vs...>(); | ||
1190 | #ifdef _MSC_VER | ||
1191 | #pragma warning(pop) | ||
1192 | #endif | ||
1193 | }; | ||
1194 | |||
1195 | template <typename F, typename... Vs> | ||
1196 | constexpr FMatrix<F, Vs...> fmatrix<F, Vs...>::value; | ||
1197 | |||
1198 | struct alt { | ||
1199 | template <typename Visitor, typename... Vs> | ||
1200 | inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, | ||
1201 | Visitor &&visitor, | ||
1202 | Vs &&... vs) | ||
1203 | DECLTYPE_AUTO_RETURN(base::at( | ||
1204 | fdiagonal<Visitor &&, | ||
1205 | decltype(as_base(lib::forward<Vs>(vs)))...>::value, | ||
1206 | index)(lib::forward<Visitor>(visitor), | ||
1207 | as_base(lib::forward<Vs>(vs))...)) | ||
1208 | |||
1209 | template <typename Visitor, typename... Vs> | ||
1210 | inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, | ||
1211 | Vs &&... vs) | ||
1212 | DECLTYPE_AUTO_RETURN(base::at( | ||
1213 | fmatrix<Visitor &&, | ||
1214 | decltype(as_base(lib::forward<Vs>(vs)))...>::value, | ||
1215 | vs.index()...)(lib::forward<Visitor>(visitor), | ||
1216 | as_base(lib::forward<Vs>(vs))...)) | ||
1217 | }; | ||
1218 | |||
1219 | struct variant { | ||
1220 | private: | ||
1221 | template <typename Visitor, typename... Values> | ||
1222 | struct visit_exhaustive_visitor_check { | ||
1223 | static_assert( | ||
1224 | lib::is_invocable<Visitor, Values...>::value, | ||
1225 | "`mpark::visit` requires the visitor to be exhaustive."); | ||
1226 | |||
1227 | #ifdef _MSC_VER | ||
1228 | #pragma warning(push) | ||
1229 | #pragma warning(disable : 4100) | ||
1230 | #endif | ||
1231 | inline constexpr DECLTYPE_AUTO operator()(Visitor &&visitor, | ||
1232 | Values &&... values) const | ||
1233 | DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor), | ||
1234 | lib::forward<Values>(values)...)) | ||
1235 | #ifdef _MSC_VER | ||
1236 | #pragma warning(pop) | ||
1237 | #endif | ||
1238 | }; | ||
1239 | |||
1240 | template <typename Visitor> | ||
1241 | struct value_visitor { | ||
1242 | Visitor &&visitor_; | ||
1243 | |||
1244 | template <typename... Alts> | ||
1245 | inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const | ||
1246 | DECLTYPE_AUTO_RETURN( | ||
1247 | visit_exhaustive_visitor_check< | ||
1248 | Visitor, | ||
1249 | decltype((lib::forward<Alts>(alts).value))...>{}( | ||
1250 | lib::forward<Visitor>(visitor_), | ||
1251 | lib::forward<Alts>(alts).value...)) | ||
1252 | }; | ||
1253 | |||
1254 | template <typename Visitor> | ||
1255 | inline static constexpr AUTO make_value_visitor(Visitor &&visitor) | ||
1256 | AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)}) | ||
1257 | |||
1258 | public: | ||
1259 | template <typename Visitor, typename... Vs> | ||
1260 | inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, | ||
1261 | Visitor &&visitor, | ||
1262 | Vs &&... vs) | ||
1263 | DECLTYPE_AUTO_RETURN( | ||
1264 | alt::visit_alt_at(index, | ||
1265 | lib::forward<Visitor>(visitor), | ||
1266 | lib::forward<Vs>(vs).impl_...)) | ||
1267 | |||
1268 | template <typename Visitor, typename... Vs> | ||
1269 | inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, | ||
1270 | Vs &&... vs) | ||
1271 | DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor), | ||
1272 | lib::forward<Vs>(vs).impl_...)) | ||
1273 | |||
1274 | template <typename Visitor, typename... Vs> | ||
1275 | inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, | ||
1276 | Visitor &&visitor, | ||
1277 | Vs &&... vs) | ||
1278 | DECLTYPE_AUTO_RETURN( | ||
1279 | visit_alt_at(index, | ||
1280 | make_value_visitor(lib::forward<Visitor>(visitor)), | ||
1281 | lib::forward<Vs>(vs)...)) | ||
1282 | |||
1283 | template <typename Visitor, typename... Vs> | ||
1284 | inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, | ||
1285 | Vs &&... vs) | ||
1286 | DECLTYPE_AUTO_RETURN( | ||
1287 | visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)), | ||
1288 | lib::forward<Vs>(vs)...)) | ||
1289 | }; | ||
1290 | |||
1291 | } // namespace visitation | ||
1292 | |||
1293 | template <std::size_t Index, typename T> | ||
1294 | struct alt { | ||
1295 | using value_type = T; | ||
1296 | |||
1297 | #ifdef _MSC_VER | ||
1298 | #pragma warning(push) | ||
1299 | #pragma warning(disable : 4244) | ||
1300 | #endif | ||
1301 | template <typename... Args> | ||
1302 | inline explicit constexpr alt(in_place_t, Args &&... args) | ||
1303 | : value(lib::forward<Args>(args)...) {} | ||
1304 | #ifdef _MSC_VER | ||
1305 | #pragma warning(pop) | ||
1306 | #endif | ||
1307 | |||
1308 | T value; | ||
1309 | }; | ||
1310 | |||
1311 | template <Trait DestructibleTrait, std::size_t Index, typename... Ts> | ||
1312 | union recursive_union; | ||
1313 | |||
1314 | template <Trait DestructibleTrait, std::size_t Index> | ||
1315 | union recursive_union<DestructibleTrait, Index> {}; | ||
1316 | |||
1317 | #define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ | ||
1318 | template <std::size_t Index, typename T, typename... Ts> \ | ||
1319 | union recursive_union<destructible_trait, Index, T, Ts...> { \ | ||
1320 | public: \ | ||
1321 | inline explicit constexpr recursive_union(valueless_t) noexcept \ | ||
1322 | : dummy_{} {} \ | ||
1323 | \ | ||
1324 | template <typename... Args> \ | ||
1325 | inline explicit constexpr recursive_union(in_place_index_t<0>, \ | ||
1326 | Args &&... args) \ | ||
1327 | : head_(in_place_t{}, lib::forward<Args>(args)...) {} \ | ||
1328 | \ | ||
1329 | template <std::size_t I, typename... Args> \ | ||
1330 | inline explicit constexpr recursive_union(in_place_index_t<I>, \ | ||
1331 | Args &&... args) \ | ||
1332 | : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \ | ||
1333 | \ | ||
1334 | recursive_union(const recursive_union &) = default; \ | ||
1335 | recursive_union(recursive_union &&) = default; \ | ||
1336 | \ | ||
1337 | destructor \ | ||
1338 | \ | ||
1339 | recursive_union &operator=(const recursive_union &) = default; \ | ||
1340 | recursive_union &operator=(recursive_union &&) = default; \ | ||
1341 | \ | ||
1342 | private: \ | ||
1343 | char dummy_; \ | ||
1344 | alt<Index, T> head_; \ | ||
1345 | recursive_union<destructible_trait, Index + 1, Ts...> tail_; \ | ||
1346 | \ | ||
1347 | friend struct access::recursive_union; \ | ||
1348 | } | ||
1349 | |||
1350 | MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, | ||
1351 | ~recursive_union() = default;); | ||
1352 | MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, | ||
1353 | ~recursive_union() {}); | ||
1354 | MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, | ||
1355 | ~recursive_union() = delete;); | ||
1356 | |||
1357 | #undef MPARK_VARIANT_RECURSIVE_UNION | ||
1358 | |||
1359 | using index_t = unsigned int; | ||
1360 | |||
1361 | template <Trait DestructibleTrait, typename... Ts> | ||
1362 | class base { | ||
1363 | public: | ||
1364 | inline explicit constexpr base(valueless_t tag) noexcept | ||
1365 | : data_(tag), index_(static_cast<index_t>(-1)) {} | ||
1366 | |||
1367 | template <std::size_t I, typename... Args> | ||
1368 | inline explicit constexpr base(in_place_index_t<I>, Args &&... args) | ||
1369 | : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...), | ||
1370 | index_(I) {} | ||
1371 | |||
1372 | inline constexpr bool valueless_by_exception() const noexcept { | ||
1373 | return index_ == static_cast<index_t>(-1); | ||
1374 | } | ||
1375 | |||
1376 | inline constexpr std::size_t index() const noexcept { | ||
1377 | return valueless_by_exception() ? variant_npos : index_; | ||
1378 | } | ||
1379 | |||
1380 | protected: | ||
1381 | using data_t = recursive_union<DestructibleTrait, 0, Ts...>; | ||
1382 | |||
1383 | friend inline constexpr base &as_base(base &b) { return b; } | ||
1384 | friend inline constexpr const base &as_base(const base &b) { return b; } | ||
1385 | friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } | ||
1386 | friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } | ||
1387 | |||
1388 | friend inline constexpr data_t &data(base &b) { return b.data_; } | ||
1389 | friend inline constexpr const data_t &data(const base &b) { return b.data_; } | ||
1390 | friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } | ||
1391 | friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } | ||
1392 | |||
1393 | inline static constexpr std::size_t size() { return sizeof...(Ts); } | ||
1394 | |||
1395 | data_t data_; | ||
1396 | index_t index_; | ||
1397 | |||
1398 | friend struct access::base; | ||
1399 | friend struct visitation::base; | ||
1400 | }; | ||
1401 | |||
1402 | struct dtor { | ||
1403 | #ifdef _MSC_VER | ||
1404 | #pragma warning(push) | ||
1405 | #pragma warning(disable : 4100) | ||
1406 | #endif | ||
1407 | template <typename Alt> | ||
1408 | inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } | ||
1409 | #ifdef _MSC_VER | ||
1410 | #pragma warning(pop) | ||
1411 | #endif | ||
1412 | }; | ||
1413 | |||
1414 | #if defined(_MSC_VER) && _MSC_VER < 1910 | ||
1415 | #define INHERITING_CTOR(type, base) \ | ||
1416 | template <typename... Args> \ | ||
1417 | inline explicit constexpr type(Args &&... args) \ | ||
1418 | : base(lib::forward<Args>(args)...) {} | ||
1419 | #else | ||
1420 | #define INHERITING_CTOR(type, base) using base::base; | ||
1421 | #endif | ||
1422 | |||
1423 | template <typename Traits, Trait = Traits::destructible_trait> | ||
1424 | class destructor; | ||
1425 | |||
1426 | #define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ | ||
1427 | template <typename... Ts> \ | ||
1428 | class destructor<traits<Ts...>, destructible_trait> \ | ||
1429 | : public base<destructible_trait, Ts...> { \ | ||
1430 | using super = base<destructible_trait, Ts...>; \ | ||
1431 | \ | ||
1432 | public: \ | ||
1433 | INHERITING_CTOR(destructor, super) \ | ||
1434 | using super::operator=; \ | ||
1435 | \ | ||
1436 | destructor(const destructor &) = default; \ | ||
1437 | destructor(destructor &&) = default; \ | ||
1438 | definition \ | ||
1439 | destructor &operator=(const destructor &) = default; \ | ||
1440 | destructor &operator=(destructor &&) = default; \ | ||
1441 | \ | ||
1442 | protected: \ | ||
1443 | destroy \ | ||
1444 | } | ||
1445 | |||
1446 | MPARK_VARIANT_DESTRUCTOR( | ||
1447 | Trait::TriviallyAvailable, | ||
1448 | ~destructor() = default;, | ||
1449 | inline void destroy() noexcept { | ||
1450 | this->index_ = static_cast<index_t>(-1); | ||
1451 | }); | ||
1452 | |||
1453 | MPARK_VARIANT_DESTRUCTOR( | ||
1454 | Trait::Available, | ||
1455 | ~destructor() { destroy(); }, | ||
1456 | inline void destroy() noexcept { | ||
1457 | if (!this->valueless_by_exception()) { | ||
1458 | visitation::alt::visit_alt(dtor{}, *this); | ||
1459 | } | ||
1460 | this->index_ = static_cast<index_t>(-1); | ||
1461 | }); | ||
1462 | |||
1463 | MPARK_VARIANT_DESTRUCTOR( | ||
1464 | Trait::Unavailable, | ||
1465 | ~destructor() = delete;, | ||
1466 | inline void destroy() noexcept = delete;); | ||
1467 | |||
1468 | #undef MPARK_VARIANT_DESTRUCTOR | ||
1469 | |||
1470 | template <typename Traits> | ||
1471 | class constructor : public destructor<Traits> { | ||
1472 | using super = destructor<Traits>; | ||
1473 | |||
1474 | public: | ||
1475 | INHERITING_CTOR(constructor, super) | ||
1476 | using super::operator=; | ||
1477 | |||
1478 | protected: | ||
1479 | #ifndef MPARK_GENERIC_LAMBDAS | ||
1480 | struct ctor { | ||
1481 | template <typename LhsAlt, typename RhsAlt> | ||
1482 | inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { | ||
1483 | constructor::construct_alt(lhs_alt, | ||
1484 | lib::forward<RhsAlt>(rhs_alt).value); | ||
1485 | } | ||
1486 | }; | ||
1487 | #endif | ||
1488 | |||
1489 | template <std::size_t I, typename T, typename... Args> | ||
1490 | inline static T &construct_alt(alt<I, T> &a, Args &&... args) { | ||
1491 | ::new (static_cast<void *>(lib::addressof(a))) | ||
1492 | alt<I, T>(in_place_t{}, lib::forward<Args>(args)...); | ||
1493 | return a.value; | ||
1494 | } | ||
1495 | |||
1496 | template <typename Rhs> | ||
1497 | inline static void generic_construct(constructor &lhs, Rhs &&rhs) { | ||
1498 | lhs.destroy(); | ||
1499 | if (!rhs.valueless_by_exception()) { | ||
1500 | visitation::alt::visit_alt_at( | ||
1501 | rhs.index(), | ||
1502 | #ifdef MPARK_GENERIC_LAMBDAS | ||
1503 | [](auto &lhs_alt, auto &&rhs_alt) { | ||
1504 | constructor::construct_alt( | ||
1505 | lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value); | ||
1506 | } | ||
1507 | #else | ||
1508 | ctor{} | ||
1509 | #endif | ||
1510 | , | ||
1511 | lhs, | ||
1512 | lib::forward<Rhs>(rhs)); | ||
1513 | lhs.index_ = rhs.index_; | ||
1514 | } | ||
1515 | } | ||
1516 | }; | ||
1517 | |||
1518 | template <typename Traits, Trait = Traits::move_constructible_trait> | ||
1519 | class move_constructor; | ||
1520 | |||
1521 | #define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ | ||
1522 | template <typename... Ts> \ | ||
1523 | class move_constructor<traits<Ts...>, move_constructible_trait> \ | ||
1524 | : public constructor<traits<Ts...>> { \ | ||
1525 | using super = constructor<traits<Ts...>>; \ | ||
1526 | \ | ||
1527 | public: \ | ||
1528 | INHERITING_CTOR(move_constructor, super) \ | ||
1529 | using super::operator=; \ | ||
1530 | \ | ||
1531 | move_constructor(const move_constructor &) = default; \ | ||
1532 | definition \ | ||
1533 | ~move_constructor() = default; \ | ||
1534 | move_constructor &operator=(const move_constructor &) = default; \ | ||
1535 | move_constructor &operator=(move_constructor &&) = default; \ | ||
1536 | } | ||
1537 | |||
1538 | MPARK_VARIANT_MOVE_CONSTRUCTOR( | ||
1539 | Trait::TriviallyAvailable, | ||
1540 | move_constructor(move_constructor &&that) = default;); | ||
1541 | |||
1542 | MPARK_VARIANT_MOVE_CONSTRUCTOR( | ||
1543 | Trait::Available, | ||
1544 | move_constructor(move_constructor &&that) noexcept( | ||
1545 | lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value) | ||
1546 | : move_constructor(valueless_t{}) { | ||
1547 | this->generic_construct(*this, lib::move(that)); | ||
1548 | }); | ||
1549 | |||
1550 | MPARK_VARIANT_MOVE_CONSTRUCTOR( | ||
1551 | Trait::Unavailable, | ||
1552 | move_constructor(move_constructor &&) = delete;); | ||
1553 | |||
1554 | #undef MPARK_VARIANT_MOVE_CONSTRUCTOR | ||
1555 | |||
1556 | template <typename Traits, Trait = Traits::copy_constructible_trait> | ||
1557 | class copy_constructor; | ||
1558 | |||
1559 | #define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ | ||
1560 | template <typename... Ts> \ | ||
1561 | class copy_constructor<traits<Ts...>, copy_constructible_trait> \ | ||
1562 | : public move_constructor<traits<Ts...>> { \ | ||
1563 | using super = move_constructor<traits<Ts...>>; \ | ||
1564 | \ | ||
1565 | public: \ | ||
1566 | INHERITING_CTOR(copy_constructor, super) \ | ||
1567 | using super::operator=; \ | ||
1568 | \ | ||
1569 | definition \ | ||
1570 | copy_constructor(copy_constructor &&) = default; \ | ||
1571 | ~copy_constructor() = default; \ | ||
1572 | copy_constructor &operator=(const copy_constructor &) = default; \ | ||
1573 | copy_constructor &operator=(copy_constructor &&) = default; \ | ||
1574 | } | ||
1575 | |||
1576 | MPARK_VARIANT_COPY_CONSTRUCTOR( | ||
1577 | Trait::TriviallyAvailable, | ||
1578 | copy_constructor(const copy_constructor &that) = default;); | ||
1579 | |||
1580 | MPARK_VARIANT_COPY_CONSTRUCTOR( | ||
1581 | Trait::Available, | ||
1582 | copy_constructor(const copy_constructor &that) | ||
1583 | : copy_constructor(valueless_t{}) { | ||
1584 | this->generic_construct(*this, that); | ||
1585 | }); | ||
1586 | |||
1587 | MPARK_VARIANT_COPY_CONSTRUCTOR( | ||
1588 | Trait::Unavailable, | ||
1589 | copy_constructor(const copy_constructor &) = delete;); | ||
1590 | |||
1591 | #undef MPARK_VARIANT_COPY_CONSTRUCTOR | ||
1592 | |||
1593 | template <typename Traits> | ||
1594 | class assignment : public copy_constructor<Traits> { | ||
1595 | using super = copy_constructor<Traits>; | ||
1596 | |||
1597 | public: | ||
1598 | INHERITING_CTOR(assignment, super) | ||
1599 | using super::operator=; | ||
1600 | |||
1601 | template <std::size_t I, typename... Args> | ||
1602 | inline /* auto & */ auto emplace(Args &&... args) | ||
1603 | -> decltype(this->construct_alt(access::base::get_alt<I>(*this), | ||
1604 | lib::forward<Args>(args)...)) { | ||
1605 | this->destroy(); | ||
1606 | auto &result = this->construct_alt(access::base::get_alt<I>(*this), | ||
1607 | lib::forward<Args>(args)...); | ||
1608 | this->index_ = I; | ||
1609 | return result; | ||
1610 | } | ||
1611 | |||
1612 | protected: | ||
1613 | #ifndef MPARK_GENERIC_LAMBDAS | ||
1614 | template <typename That> | ||
1615 | struct assigner { | ||
1616 | template <typename ThisAlt, typename ThatAlt> | ||
1617 | inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { | ||
1618 | self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value); | ||
1619 | } | ||
1620 | assignment *self; | ||
1621 | }; | ||
1622 | #endif | ||
1623 | |||
1624 | template <std::size_t I, typename T, typename Arg> | ||
1625 | inline void assign_alt(alt<I, T> &a, Arg &&arg) { | ||
1626 | if (this->index() == I) { | ||
1627 | #ifdef _MSC_VER | ||
1628 | #pragma warning(push) | ||
1629 | #pragma warning(disable : 4244) | ||
1630 | #endif | ||
1631 | a.value = lib::forward<Arg>(arg); | ||
1632 | #ifdef _MSC_VER | ||
1633 | #pragma warning(pop) | ||
1634 | #endif | ||
1635 | } else { | ||
1636 | struct { | ||
1637 | void operator()(std::true_type) const { | ||
1638 | this_->emplace<I>(lib::forward<Arg>(arg_)); | ||
1639 | } | ||
1640 | void operator()(std::false_type) const { | ||
1641 | this_->emplace<I>(T(lib::forward<Arg>(arg_))); | ||
1642 | } | ||
1643 | assignment *this_; | ||
1644 | Arg &&arg_; | ||
1645 | } impl{this, lib::forward<Arg>(arg)}; | ||
1646 | impl(lib::bool_constant< | ||
1647 | std::is_nothrow_constructible<T, Arg>::value || | ||
1648 | !std::is_nothrow_move_constructible<T>::value>{}); | ||
1649 | } | ||
1650 | } | ||
1651 | |||
1652 | template <typename That> | ||
1653 | inline void generic_assign(That &&that) { | ||
1654 | if (this->valueless_by_exception() && that.valueless_by_exception()) { | ||
1655 | // do nothing. | ||
1656 | } else if (that.valueless_by_exception()) { | ||
1657 | this->destroy(); | ||
1658 | } else { | ||
1659 | visitation::alt::visit_alt_at( | ||
1660 | that.index(), | ||
1661 | #ifdef MPARK_GENERIC_LAMBDAS | ||
1662 | [this](auto &this_alt, auto &&that_alt) { | ||
1663 | this->assign_alt( | ||
1664 | this_alt, lib::forward<decltype(that_alt)>(that_alt).value); | ||
1665 | } | ||
1666 | #else | ||
1667 | assigner<That>{this} | ||
1668 | #endif | ||
1669 | , | ||
1670 | *this, | ||
1671 | lib::forward<That>(that)); | ||
1672 | } | ||
1673 | } | ||
1674 | }; | ||
1675 | |||
1676 | template <typename Traits, Trait = Traits::move_assignable_trait> | ||
1677 | class move_assignment; | ||
1678 | |||
1679 | #define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ | ||
1680 | template <typename... Ts> \ | ||
1681 | class move_assignment<traits<Ts...>, move_assignable_trait> \ | ||
1682 | : public assignment<traits<Ts...>> { \ | ||
1683 | using super = assignment<traits<Ts...>>; \ | ||
1684 | \ | ||
1685 | public: \ | ||
1686 | INHERITING_CTOR(move_assignment, super) \ | ||
1687 | using super::operator=; \ | ||
1688 | \ | ||
1689 | move_assignment(const move_assignment &) = default; \ | ||
1690 | move_assignment(move_assignment &&) = default; \ | ||
1691 | ~move_assignment() = default; \ | ||
1692 | move_assignment &operator=(const move_assignment &) = default; \ | ||
1693 | definition \ | ||
1694 | } | ||
1695 | |||
1696 | MPARK_VARIANT_MOVE_ASSIGNMENT( | ||
1697 | Trait::TriviallyAvailable, | ||
1698 | move_assignment &operator=(move_assignment &&that) = default;); | ||
1699 | |||
1700 | MPARK_VARIANT_MOVE_ASSIGNMENT( | ||
1701 | Trait::Available, | ||
1702 | move_assignment & | ||
1703 | operator=(move_assignment &&that) noexcept( | ||
1704 | lib::all<(std::is_nothrow_move_constructible<Ts>::value && | ||
1705 | std::is_nothrow_move_assignable<Ts>::value)...>::value) { | ||
1706 | this->generic_assign(lib::move(that)); | ||
1707 | return *this; | ||
1708 | }); | ||
1709 | |||
1710 | MPARK_VARIANT_MOVE_ASSIGNMENT( | ||
1711 | Trait::Unavailable, | ||
1712 | move_assignment &operator=(move_assignment &&) = delete;); | ||
1713 | |||
1714 | #undef MPARK_VARIANT_MOVE_ASSIGNMENT | ||
1715 | |||
1716 | template <typename Traits, Trait = Traits::copy_assignable_trait> | ||
1717 | class copy_assignment; | ||
1718 | |||
1719 | #define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ | ||
1720 | template <typename... Ts> \ | ||
1721 | class copy_assignment<traits<Ts...>, copy_assignable_trait> \ | ||
1722 | : public move_assignment<traits<Ts...>> { \ | ||
1723 | using super = move_assignment<traits<Ts...>>; \ | ||
1724 | \ | ||
1725 | public: \ | ||
1726 | INHERITING_CTOR(copy_assignment, super) \ | ||
1727 | using super::operator=; \ | ||
1728 | \ | ||
1729 | copy_assignment(const copy_assignment &) = default; \ | ||
1730 | copy_assignment(copy_assignment &&) = default; \ | ||
1731 | ~copy_assignment() = default; \ | ||
1732 | definition \ | ||
1733 | copy_assignment &operator=(copy_assignment &&) = default; \ | ||
1734 | } | ||
1735 | |||
1736 | MPARK_VARIANT_COPY_ASSIGNMENT( | ||
1737 | Trait::TriviallyAvailable, | ||
1738 | copy_assignment &operator=(const copy_assignment &that) = default;); | ||
1739 | |||
1740 | MPARK_VARIANT_COPY_ASSIGNMENT( | ||
1741 | Trait::Available, | ||
1742 | copy_assignment &operator=(const copy_assignment &that) { | ||
1743 | this->generic_assign(that); | ||
1744 | return *this; | ||
1745 | }); | ||
1746 | |||
1747 | MPARK_VARIANT_COPY_ASSIGNMENT( | ||
1748 | Trait::Unavailable, | ||
1749 | copy_assignment &operator=(const copy_assignment &) = delete;); | ||
1750 | |||
1751 | #undef MPARK_VARIANT_COPY_ASSIGNMENT | ||
1752 | |||
1753 | template <typename... Ts> | ||
1754 | class impl : public copy_assignment<traits<Ts...>> { | ||
1755 | using super = copy_assignment<traits<Ts...>>; | ||
1756 | |||
1757 | public: | ||
1758 | INHERITING_CTOR(impl, super) | ||
1759 | using super::operator=; | ||
1760 | |||
1761 | template <std::size_t I, typename Arg> | ||
1762 | inline void assign(Arg &&arg) { | ||
1763 | this->assign_alt(access::base::get_alt<I>(*this), | ||
1764 | lib::forward<Arg>(arg)); | ||
1765 | } | ||
1766 | |||
1767 | inline void swap(impl &that) { | ||
1768 | if (this->valueless_by_exception() && that.valueless_by_exception()) { | ||
1769 | // do nothing. | ||
1770 | } else if (this->index() == that.index()) { | ||
1771 | visitation::alt::visit_alt_at(this->index(), | ||
1772 | #ifdef MPARK_GENERIC_LAMBDAS | ||
1773 | [](auto &this_alt, auto &that_alt) { | ||
1774 | using std::swap; | ||
1775 | swap(this_alt.value, | ||
1776 | that_alt.value); | ||
1777 | } | ||
1778 | #else | ||
1779 | swapper{} | ||
1780 | #endif | ||
1781 | , | ||
1782 | *this, | ||
1783 | that); | ||
1784 | } else { | ||
1785 | impl *lhs = this; | ||
1786 | impl *rhs = lib::addressof(that); | ||
1787 | if (lhs->move_nothrow() && !rhs->move_nothrow()) { | ||
1788 | std::swap(lhs, rhs); | ||
1789 | } | ||
1790 | impl tmp(lib::move(*rhs)); | ||
1791 | #ifdef MPARK_EXCEPTIONS | ||
1792 | // EXTENSION: When the move construction of `lhs` into `rhs` throws | ||
1793 | // and `tmp` is nothrow move constructible then we move `tmp` back | ||
1794 | // into `rhs` and provide the strong exception safety guarantee. | ||
1795 | try { | ||
1796 | this->generic_construct(*rhs, lib::move(*lhs)); | ||
1797 | } catch (...) { | ||
1798 | if (tmp.move_nothrow()) { | ||
1799 | this->generic_construct(*rhs, lib::move(tmp)); | ||
1800 | } | ||
1801 | throw; | ||
1802 | } | ||
1803 | #else | ||
1804 | this->generic_construct(*rhs, lib::move(*lhs)); | ||
1805 | #endif | ||
1806 | this->generic_construct(*lhs, lib::move(tmp)); | ||
1807 | } | ||
1808 | } | ||
1809 | |||
1810 | private: | ||
1811 | #ifndef MPARK_GENERIC_LAMBDAS | ||
1812 | struct swapper { | ||
1813 | template <typename ThisAlt, typename ThatAlt> | ||
1814 | inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { | ||
1815 | using std::swap; | ||
1816 | swap(this_alt.value, that_alt.value); | ||
1817 | } | ||
1818 | }; | ||
1819 | #endif | ||
1820 | |||
1821 | inline constexpr bool move_nothrow() const { | ||
1822 | return this->valueless_by_exception() || | ||
1823 | lib::array<bool, sizeof...(Ts)>{ | ||
1824 | {std::is_nothrow_move_constructible<Ts>::value...} | ||
1825 | }[this->index()]; | ||
1826 | } | ||
1827 | }; | ||
1828 | |||
1829 | template <std::size_t I, typename T> | ||
1830 | struct overload_leaf { | ||
1831 | using F = lib::size_constant<I> (*)(T); | ||
1832 | operator F() const { return nullptr; } | ||
1833 | }; | ||
1834 | |||
1835 | template <typename... Ts> | ||
1836 | struct overload_impl { | ||
1837 | private: | ||
1838 | template <typename> | ||
1839 | struct impl; | ||
1840 | |||
1841 | template <std::size_t... Is> | ||
1842 | struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>... {}; | ||
1843 | |||
1844 | public: | ||
1845 | using type = impl<lib::index_sequence_for<Ts...>>; | ||
1846 | }; | ||
1847 | |||
1848 | template <typename... Ts> | ||
1849 | using overload = typename overload_impl<Ts...>::type; | ||
1850 | |||
1851 | template <typename T, typename... Ts> | ||
1852 | using best_match = lib::invoke_result_t<overload<Ts...>, T &&>; | ||
1853 | |||
1854 | template <typename T> | ||
1855 | struct is_in_place_index : std::false_type {}; | ||
1856 | |||
1857 | template <std::size_t I> | ||
1858 | struct is_in_place_index<in_place_index_t<I>> : std::true_type {}; | ||
1859 | |||
1860 | template <typename T> | ||
1861 | struct is_in_place_type : std::false_type {}; | ||
1862 | |||
1863 | template <typename T> | ||
1864 | struct is_in_place_type<in_place_type_t<T>> : std::true_type {}; | ||
1865 | |||
1866 | } // detail | ||
1867 | |||
1868 | template <typename... Ts> | ||
1869 | class variant { | ||
1870 | static_assert(0 < sizeof...(Ts), | ||
1871 | "variant must consist of at least one alternative."); | ||
1872 | |||
1873 | static_assert(lib::all<!std::is_array<Ts>::value...>::value, | ||
1874 | "variant can not have an array type as an alternative."); | ||
1875 | |||
1876 | static_assert(lib::all<!std::is_reference<Ts>::value...>::value, | ||
1877 | "variant can not have a reference type as an alternative."); | ||
1878 | |||
1879 | static_assert(lib::all<!std::is_void<Ts>::value...>::value, | ||
1880 | "variant can not have a void type as an alternative."); | ||
1881 | |||
1882 | public: | ||
1883 | template < | ||
1884 | typename Front = lib::type_pack_element_t<0, Ts...>, | ||
1885 | lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0> | ||
1886 | inline constexpr variant() noexcept( | ||
1887 | std::is_nothrow_default_constructible<Front>::value) | ||
1888 | : impl_(in_place_index_t<0>{}) {} | ||
1889 | |||
1890 | variant(const variant &) = default; | ||
1891 | variant(variant &&) = default; | ||
1892 | |||
1893 | template < | ||
1894 | typename Arg, | ||
1895 | typename Decayed = lib::decay_t<Arg>, | ||
1896 | lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0, | ||
1897 | lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0, | ||
1898 | lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0, | ||
1899 | std::size_t I = detail::best_match<Arg, Ts...>::value, | ||
1900 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
1901 | lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0> | ||
1902 | inline constexpr variant(Arg &&arg) noexcept( | ||
1903 | std::is_nothrow_constructible<T, Arg>::value) | ||
1904 | : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {} | ||
1905 | |||
1906 | template < | ||
1907 | std::size_t I, | ||
1908 | typename... Args, | ||
1909 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
1910 | lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> | ||
1911 | inline explicit constexpr variant( | ||
1912 | in_place_index_t<I>, | ||
1913 | Args &&... args) noexcept(std::is_nothrow_constructible<T, | ||
1914 | Args...>::value) | ||
1915 | : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {} | ||
1916 | |||
1917 | template < | ||
1918 | std::size_t I, | ||
1919 | typename Up, | ||
1920 | typename... Args, | ||
1921 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
1922 | lib::enable_if_t<std::is_constructible<T, | ||
1923 | std::initializer_list<Up> &, | ||
1924 | Args...>::value, | ||
1925 | int> = 0> | ||
1926 | inline explicit constexpr variant( | ||
1927 | in_place_index_t<I>, | ||
1928 | std::initializer_list<Up> il, | ||
1929 | Args &&... args) noexcept(std:: | ||
1930 | is_nothrow_constructible< | ||
1931 | T, | ||
1932 | std::initializer_list<Up> &, | ||
1933 | Args...>::value) | ||
1934 | : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {} | ||
1935 | |||
1936 | template < | ||
1937 | typename T, | ||
1938 | typename... Args, | ||
1939 | std::size_t I = detail::find_index_sfinae<T, Ts...>::value, | ||
1940 | lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> | ||
1941 | inline explicit constexpr variant( | ||
1942 | in_place_type_t<T>, | ||
1943 | Args &&... args) noexcept(std::is_nothrow_constructible<T, | ||
1944 | Args...>::value) | ||
1945 | : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {} | ||
1946 | |||
1947 | template < | ||
1948 | typename T, | ||
1949 | typename Up, | ||
1950 | typename... Args, | ||
1951 | std::size_t I = detail::find_index_sfinae<T, Ts...>::value, | ||
1952 | lib::enable_if_t<std::is_constructible<T, | ||
1953 | std::initializer_list<Up> &, | ||
1954 | Args...>::value, | ||
1955 | int> = 0> | ||
1956 | inline explicit constexpr variant( | ||
1957 | in_place_type_t<T>, | ||
1958 | std::initializer_list<Up> il, | ||
1959 | Args &&... args) noexcept(std:: | ||
1960 | is_nothrow_constructible< | ||
1961 | T, | ||
1962 | std::initializer_list<Up> &, | ||
1963 | Args...>::value) | ||
1964 | : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {} | ||
1965 | |||
1966 | ~variant() = default; | ||
1967 | |||
1968 | variant &operator=(const variant &) = default; | ||
1969 | variant &operator=(variant &&) = default; | ||
1970 | |||
1971 | template <typename Arg, | ||
1972 | lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value, | ||
1973 | int> = 0, | ||
1974 | std::size_t I = detail::best_match<Arg, Ts...>::value, | ||
1975 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
1976 | lib::enable_if_t<(std::is_assignable<T &, Arg>::value && | ||
1977 | std::is_constructible<T, Arg>::value), | ||
1978 | int> = 0> | ||
1979 | inline variant &operator=(Arg &&arg) noexcept( | ||
1980 | (std::is_nothrow_assignable<T &, Arg>::value && | ||
1981 | std::is_nothrow_constructible<T, Arg>::value)) { | ||
1982 | impl_.template assign<I>(lib::forward<Arg>(arg)); | ||
1983 | return *this; | ||
1984 | } | ||
1985 | |||
1986 | template < | ||
1987 | std::size_t I, | ||
1988 | typename... Args, | ||
1989 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
1990 | lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> | ||
1991 | inline T &emplace(Args &&... args) { | ||
1992 | return impl_.template emplace<I>(lib::forward<Args>(args)...); | ||
1993 | } | ||
1994 | |||
1995 | template < | ||
1996 | std::size_t I, | ||
1997 | typename Up, | ||
1998 | typename... Args, | ||
1999 | typename T = lib::type_pack_element_t<I, Ts...>, | ||
2000 | lib::enable_if_t<std::is_constructible<T, | ||
2001 | std::initializer_list<Up> &, | ||
2002 | Args...>::value, | ||
2003 | int> = 0> | ||
2004 | inline T &emplace(std::initializer_list<Up> il, Args &&... args) { | ||
2005 | return impl_.template emplace<I>(il, lib::forward<Args>(args)...); | ||
2006 | } | ||
2007 | |||
2008 | template < | ||
2009 | typename T, | ||
2010 | typename... Args, | ||
2011 | std::size_t I = detail::find_index_sfinae<T, Ts...>::value, | ||
2012 | lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0> | ||
2013 | inline T &emplace(Args &&... args) { | ||
2014 | return impl_.template emplace<I>(lib::forward<Args>(args)...); | ||
2015 | } | ||
2016 | |||
2017 | template < | ||
2018 | typename T, | ||
2019 | typename Up, | ||
2020 | typename... Args, | ||
2021 | std::size_t I = detail::find_index_sfinae<T, Ts...>::value, | ||
2022 | lib::enable_if_t<std::is_constructible<T, | ||
2023 | std::initializer_list<Up> &, | ||
2024 | Args...>::value, | ||
2025 | int> = 0> | ||
2026 | inline T &emplace(std::initializer_list<Up> il, Args &&... args) { | ||
2027 | return impl_.template emplace<I>(il, lib::forward<Args>(args)...); | ||
2028 | } | ||
2029 | |||
2030 | inline constexpr bool valueless_by_exception() const noexcept { | ||
2031 | return impl_.valueless_by_exception(); | ||
2032 | } | ||
2033 | |||
2034 | inline constexpr std::size_t index() const noexcept { | ||
2035 | return impl_.index(); | ||
2036 | } | ||
2037 | |||
2038 | template <bool Dummy = true, | ||
2039 | lib::enable_if_t< | ||
2040 | lib::all<Dummy, | ||
2041 | (lib::dependent_type<std::is_move_constructible<Ts>, | ||
2042 | Dummy>::value && | ||
2043 | lib::dependent_type<lib::is_swappable<Ts>, | ||
2044 | Dummy>::value)...>::value, | ||
2045 | int> = 0> | ||
2046 | inline void swap(variant &that) noexcept( | ||
2047 | lib::all<(std::is_nothrow_move_constructible<Ts>::value && | ||
2048 | lib::is_nothrow_swappable<Ts>::value)...>::value) { | ||
2049 | impl_.swap(that.impl_); | ||
2050 | } | ||
2051 | |||
2052 | private: | ||
2053 | detail::impl<Ts...> impl_; | ||
2054 | |||
2055 | friend struct detail::access::variant; | ||
2056 | friend struct detail::visitation::variant; | ||
2057 | }; | ||
2058 | |||
2059 | template <std::size_t I, typename... Ts> | ||
2060 | inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept { | ||
2061 | return v.index() == I; | ||
2062 | } | ||
2063 | |||
2064 | template <typename T, typename... Ts> | ||
2065 | inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept { | ||
2066 | return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v); | ||
2067 | } | ||
2068 | |||
2069 | namespace detail { | ||
2070 | template <std::size_t I, typename V> | ||
2071 | struct generic_get_impl { | ||
2072 | constexpr generic_get_impl(int) {} | ||
2073 | |||
2074 | constexpr AUTO_REFREF operator()(V &&v) const | ||
2075 | AUTO_REFREF_RETURN( | ||
2076 | access::variant::get_alt<I>(lib::forward<V>(v)).value) | ||
2077 | }; | ||
2078 | |||
2079 | template <std::size_t I, typename V> | ||
2080 | inline constexpr AUTO_REFREF generic_get(V &&v) | ||
2081 | AUTO_REFREF_RETURN(generic_get_impl<I, V>( | ||
2082 | holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))( | ||
2083 | lib::forward<V>(v))) | ||
2084 | } // namespace detail | ||
2085 | |||
2086 | template <std::size_t I, typename... Ts> | ||
2087 | inline constexpr variant_alternative_t<I, variant<Ts...>> &get( | ||
2088 | variant<Ts...> &v) { | ||
2089 | return detail::generic_get<I>(v); | ||
2090 | } | ||
2091 | |||
2092 | template <std::size_t I, typename... Ts> | ||
2093 | inline constexpr variant_alternative_t<I, variant<Ts...>> &&get( | ||
2094 | variant<Ts...> &&v) { | ||
2095 | return detail::generic_get<I>(lib::move(v)); | ||
2096 | } | ||
2097 | |||
2098 | template <std::size_t I, typename... Ts> | ||
2099 | inline constexpr const variant_alternative_t<I, variant<Ts...>> &get( | ||
2100 | const variant<Ts...> &v) { | ||
2101 | return detail::generic_get<I>(v); | ||
2102 | } | ||
2103 | |||
2104 | template <std::size_t I, typename... Ts> | ||
2105 | inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get( | ||
2106 | const variant<Ts...> &&v) { | ||
2107 | return detail::generic_get<I>(lib::move(v)); | ||
2108 | } | ||
2109 | |||
2110 | template <typename T, typename... Ts> | ||
2111 | inline constexpr T &get(variant<Ts...> &v) { | ||
2112 | return get<detail::find_index_checked<T, Ts...>::value>(v); | ||
2113 | } | ||
2114 | |||
2115 | template <typename T, typename... Ts> | ||
2116 | inline constexpr T &&get(variant<Ts...> &&v) { | ||
2117 | return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v)); | ||
2118 | } | ||
2119 | |||
2120 | template <typename T, typename... Ts> | ||
2121 | inline constexpr const T &get(const variant<Ts...> &v) { | ||
2122 | return get<detail::find_index_checked<T, Ts...>::value>(v); | ||
2123 | } | ||
2124 | |||
2125 | template <typename T, typename... Ts> | ||
2126 | inline constexpr const T &&get(const variant<Ts...> &&v) { | ||
2127 | return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v)); | ||
2128 | } | ||
2129 | |||
2130 | namespace detail { | ||
2131 | |||
2132 | template <std::size_t I, typename V> | ||
2133 | inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept | ||
2134 | AUTO_RETURN(v && holds_alternative<I>(*v) | ||
2135 | ? lib::addressof(access::variant::get_alt<I>(*v).value) | ||
2136 | : nullptr) | ||
2137 | |||
2138 | } // namespace detail | ||
2139 | |||
2140 | template <std::size_t I, typename... Ts> | ||
2141 | inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>> | ||
2142 | get_if(variant<Ts...> *v) noexcept { | ||
2143 | return detail::generic_get_if<I>(v); | ||
2144 | } | ||
2145 | |||
2146 | template <std::size_t I, typename... Ts> | ||
2147 | inline constexpr lib::add_pointer_t< | ||
2148 | const variant_alternative_t<I, variant<Ts...>>> | ||
2149 | get_if(const variant<Ts...> *v) noexcept { | ||
2150 | return detail::generic_get_if<I>(v); | ||
2151 | } | ||
2152 | |||
2153 | template <typename T, typename... Ts> | ||
2154 | inline constexpr lib::add_pointer_t<T> | ||
2155 | get_if(variant<Ts...> *v) noexcept { | ||
2156 | return get_if<detail::find_index_checked<T, Ts...>::value>(v); | ||
2157 | } | ||
2158 | |||
2159 | template <typename T, typename... Ts> | ||
2160 | inline constexpr lib::add_pointer_t<const T> | ||
2161 | get_if(const variant<Ts...> *v) noexcept { | ||
2162 | return get_if<detail::find_index_checked<T, Ts...>::value>(v); | ||
2163 | } | ||
2164 | |||
2165 | template <typename... Ts> | ||
2166 | inline constexpr bool operator==(const variant<Ts...> &lhs, | ||
2167 | const variant<Ts...> &rhs) { | ||
2168 | using detail::visitation::variant; | ||
2169 | using lib::equal_to; | ||
2170 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2171 | if (lhs.index() != rhs.index()) return false; | ||
2172 | if (lhs.valueless_by_exception()) return true; | ||
2173 | return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); | ||
2174 | #else | ||
2175 | return lhs.index() == rhs.index() && | ||
2176 | (lhs.valueless_by_exception() || | ||
2177 | variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); | ||
2178 | #endif | ||
2179 | } | ||
2180 | |||
2181 | template <typename... Ts> | ||
2182 | inline constexpr bool operator!=(const variant<Ts...> &lhs, | ||
2183 | const variant<Ts...> &rhs) { | ||
2184 | using detail::visitation::variant; | ||
2185 | using lib::not_equal_to; | ||
2186 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2187 | if (lhs.index() != rhs.index()) return true; | ||
2188 | if (lhs.valueless_by_exception()) return false; | ||
2189 | return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); | ||
2190 | #else | ||
2191 | return lhs.index() != rhs.index() || | ||
2192 | (!lhs.valueless_by_exception() && | ||
2193 | variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); | ||
2194 | #endif | ||
2195 | } | ||
2196 | |||
2197 | template <typename... Ts> | ||
2198 | inline constexpr bool operator<(const variant<Ts...> &lhs, | ||
2199 | const variant<Ts...> &rhs) { | ||
2200 | using detail::visitation::variant; | ||
2201 | using lib::less; | ||
2202 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2203 | if (rhs.valueless_by_exception()) return false; | ||
2204 | if (lhs.valueless_by_exception()) return true; | ||
2205 | if (lhs.index() < rhs.index()) return true; | ||
2206 | if (lhs.index() > rhs.index()) return false; | ||
2207 | return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); | ||
2208 | #else | ||
2209 | return !rhs.valueless_by_exception() && | ||
2210 | (lhs.valueless_by_exception() || lhs.index() < rhs.index() || | ||
2211 | (lhs.index() == rhs.index() && | ||
2212 | variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); | ||
2213 | #endif | ||
2214 | } | ||
2215 | |||
2216 | template <typename... Ts> | ||
2217 | inline constexpr bool operator>(const variant<Ts...> &lhs, | ||
2218 | const variant<Ts...> &rhs) { | ||
2219 | using detail::visitation::variant; | ||
2220 | using lib::greater; | ||
2221 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2222 | if (lhs.valueless_by_exception()) return false; | ||
2223 | if (rhs.valueless_by_exception()) return true; | ||
2224 | if (lhs.index() > rhs.index()) return true; | ||
2225 | if (lhs.index() < rhs.index()) return false; | ||
2226 | return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); | ||
2227 | #else | ||
2228 | return !lhs.valueless_by_exception() && | ||
2229 | (rhs.valueless_by_exception() || lhs.index() > rhs.index() || | ||
2230 | (lhs.index() == rhs.index() && | ||
2231 | variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); | ||
2232 | #endif | ||
2233 | } | ||
2234 | |||
2235 | template <typename... Ts> | ||
2236 | inline constexpr bool operator<=(const variant<Ts...> &lhs, | ||
2237 | const variant<Ts...> &rhs) { | ||
2238 | using detail::visitation::variant; | ||
2239 | using lib::less_equal; | ||
2240 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2241 | if (lhs.valueless_by_exception()) return true; | ||
2242 | if (rhs.valueless_by_exception()) return false; | ||
2243 | if (lhs.index() < rhs.index()) return true; | ||
2244 | if (lhs.index() > rhs.index()) return false; | ||
2245 | return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); | ||
2246 | #else | ||
2247 | return lhs.valueless_by_exception() || | ||
2248 | (!rhs.valueless_by_exception() && | ||
2249 | (lhs.index() < rhs.index() || | ||
2250 | (lhs.index() == rhs.index() && | ||
2251 | variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); | ||
2252 | #endif | ||
2253 | } | ||
2254 | |||
2255 | template <typename... Ts> | ||
2256 | inline constexpr bool operator>=(const variant<Ts...> &lhs, | ||
2257 | const variant<Ts...> &rhs) { | ||
2258 | using detail::visitation::variant; | ||
2259 | using lib::greater_equal; | ||
2260 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2261 | if (rhs.valueless_by_exception()) return true; | ||
2262 | if (lhs.valueless_by_exception()) return false; | ||
2263 | if (lhs.index() > rhs.index()) return true; | ||
2264 | if (lhs.index() < rhs.index()) return false; | ||
2265 | return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); | ||
2266 | #else | ||
2267 | return rhs.valueless_by_exception() || | ||
2268 | (!lhs.valueless_by_exception() && | ||
2269 | (lhs.index() > rhs.index() || | ||
2270 | (lhs.index() == rhs.index() && | ||
2271 | variant::visit_value_at( | ||
2272 | lhs.index(), greater_equal{}, lhs, rhs)))); | ||
2273 | #endif | ||
2274 | } | ||
2275 | |||
2276 | struct monostate {}; | ||
2277 | |||
2278 | inline constexpr bool operator<(monostate, monostate) noexcept { | ||
2279 | return false; | ||
2280 | } | ||
2281 | |||
2282 | inline constexpr bool operator>(monostate, monostate) noexcept { | ||
2283 | return false; | ||
2284 | } | ||
2285 | |||
2286 | inline constexpr bool operator<=(monostate, monostate) noexcept { | ||
2287 | return true; | ||
2288 | } | ||
2289 | |||
2290 | inline constexpr bool operator>=(monostate, monostate) noexcept { | ||
2291 | return true; | ||
2292 | } | ||
2293 | |||
2294 | inline constexpr bool operator==(monostate, monostate) noexcept { | ||
2295 | return true; | ||
2296 | } | ||
2297 | |||
2298 | inline constexpr bool operator!=(monostate, monostate) noexcept { | ||
2299 | return false; | ||
2300 | } | ||
2301 | |||
2302 | #ifdef MPARK_CPP14_CONSTEXPR | ||
2303 | namespace detail { | ||
2304 | |||
2305 | inline constexpr bool all(std::initializer_list<bool> bs) { | ||
2306 | for (bool b : bs) { | ||
2307 | if (!b) { | ||
2308 | return false; | ||
2309 | } | ||
2310 | } | ||
2311 | return true; | ||
2312 | } | ||
2313 | |||
2314 | } // namespace detail | ||
2315 | |||
2316 | template <typename Visitor, typename... Vs> | ||
2317 | inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { | ||
2318 | return (detail::all({!vs.valueless_by_exception()...}) | ||
2319 | ? (void)0 | ||
2320 | : throw_bad_variant_access()), | ||
2321 | detail::visitation::variant::visit_value( | ||
2322 | lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...); | ||
2323 | } | ||
2324 | #else | ||
2325 | namespace detail { | ||
2326 | |||
2327 | template <std::size_t N> | ||
2328 | inline constexpr bool all_impl(const lib::array<bool, N> &bs, | ||
2329 | std::size_t idx) { | ||
2330 | return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); | ||
2331 | } | ||
2332 | |||
2333 | template <std::size_t N> | ||
2334 | inline constexpr bool all(const lib::array<bool, N> &bs) { | ||
2335 | return all_impl(bs, 0); | ||
2336 | } | ||
2337 | |||
2338 | } // namespace detail | ||
2339 | |||
2340 | template <typename Visitor, typename... Vs> | ||
2341 | inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) | ||
2342 | DECLTYPE_AUTO_RETURN( | ||
2343 | (detail::all( | ||
2344 | lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}}) | ||
2345 | ? (void)0 | ||
2346 | : throw_bad_variant_access()), | ||
2347 | detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor), | ||
2348 | lib::forward<Vs>(vs)...)) | ||
2349 | #endif | ||
2350 | |||
2351 | template <typename... Ts> | ||
2352 | inline auto swap(variant<Ts...> &lhs, | ||
2353 | variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs))) | ||
2354 | -> decltype(lhs.swap(rhs)) { | ||
2355 | lhs.swap(rhs); | ||
2356 | } | ||
2357 | |||
2358 | namespace detail { | ||
2359 | |||
2360 | template <typename T, typename...> | ||
2361 | using enabled_type = T; | ||
2362 | |||
2363 | namespace hash { | ||
2364 | |||
2365 | template <typename H, typename K> | ||
2366 | constexpr bool meets_requirements() { | ||
2367 | return std::is_copy_constructible<H>::value && | ||
2368 | std::is_move_constructible<H>::value && | ||
2369 | lib::is_invocable_r<std::size_t, H, const K &>::value; | ||
2370 | } | ||
2371 | |||
2372 | template <typename K> | ||
2373 | constexpr bool is_enabled() { | ||
2374 | using H = std::hash<K>; | ||
2375 | return meets_requirements<H, K>() && | ||
2376 | std::is_default_constructible<H>::value && | ||
2377 | std::is_copy_assignable<H>::value && | ||
2378 | std::is_move_assignable<H>::value; | ||
2379 | } | ||
2380 | |||
2381 | } // namespace hash | ||
2382 | |||
2383 | } // namespace detail | ||
2384 | |||
2385 | #undef AUTO | ||
2386 | #undef AUTO_RETURN | ||
2387 | |||
2388 | #undef AUTO_REFREF | ||
2389 | #undef AUTO_REFREF_RETURN | ||
2390 | |||
2391 | #undef DECLTYPE_AUTO | ||
2392 | #undef DECLTYPE_AUTO_RETURN | ||
2393 | |||
2394 | } // namespace mpark | ||
2395 | |||
2396 | namespace std { | ||
2397 | |||
2398 | template <typename... Ts> | ||
2399 | struct hash<mpark::detail::enabled_type< | ||
2400 | mpark::variant<Ts...>, | ||
2401 | mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled< | ||
2402 | mpark::lib::remove_const_t<Ts>>()...>::value>>> { | ||
2403 | using argument_type = mpark::variant<Ts...>; | ||
2404 | using result_type = std::size_t; | ||
2405 | |||
2406 | inline result_type operator()(const argument_type &v) const { | ||
2407 | using mpark::detail::visitation::variant; | ||
2408 | std::size_t result = | ||
2409 | v.valueless_by_exception() | ||
2410 | ? 299792458 // Random value chosen by the universe upon creation | ||
2411 | : variant::visit_alt( | ||
2412 | #ifdef MPARK_GENERIC_LAMBDAS | ||
2413 | [](const auto &alt) { | ||
2414 | using alt_type = mpark::lib::decay_t<decltype(alt)>; | ||
2415 | using value_type = mpark::lib::remove_const_t< | ||
2416 | typename alt_type::value_type>; | ||
2417 | return hash<value_type>{}(alt.value); | ||
2418 | } | ||
2419 | #else | ||
2420 | hasher{} | ||
2421 | #endif | ||
2422 | , | ||
2423 | v); | ||
2424 | return hash_combine(result, hash<std::size_t>{}(v.index())); | ||
2425 | } | ||
2426 | |||
2427 | private: | ||
2428 | #ifndef MPARK_GENERIC_LAMBDAS | ||
2429 | struct hasher { | ||
2430 | template <typename Alt> | ||
2431 | inline std::size_t operator()(const Alt &alt) const { | ||
2432 | using alt_type = mpark::lib::decay_t<Alt>; | ||
2433 | using value_type = | ||
2434 | mpark::lib::remove_const_t<typename alt_type::value_type>; | ||
2435 | return hash<value_type>{}(alt.value); | ||
2436 | } | ||
2437 | }; | ||
2438 | #endif | ||
2439 | |||
2440 | static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { | ||
2441 | return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); | ||
2442 | } | ||
2443 | }; | ||
2444 | |||
2445 | template <> | ||
2446 | struct hash<mpark::monostate> { | ||
2447 | using argument_type = mpark::monostate; | ||
2448 | using result_type = std::size_t; | ||
2449 | |||
2450 | inline result_type operator()(const argument_type &) const noexcept { | ||
2451 | return 66740831; // return a fundamentally attractive random value. | ||
2452 | } | ||
2453 | }; | ||
2454 | |||
2455 | } // namespace std | ||
2456 | |||
2457 | #endif // MPARK_VARIANT_HPP | ||