about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-03-27 16:06:21 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-03-27 16:06:21 -0400
commita20b0e6c9cd6d697607948d6eb4a579b79aa455b (patch)
tree5e8b8c564812b812e4920ecfe3e8b92401bbb6d9
parentef708dd1307c7b2146eb3ab518b3c932dd8b6996 (diff)
downloadhkutil-a20b0e6c9cd6d697607948d6eb4a579b79aa455b.tar.gz
hkutil-a20b0e6c9cd6d697607948d6eb4a579b79aa455b.tar.bz2
hkutil-a20b0e6c9cd6d697607948d6eb4a579b79aa455b.zip
Wrote write-only database class
-rw-r--r--hkutil/database.h213
-rw-r--r--vendor/variant.hpp2457
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
14namespace 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
14namespace 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
293namespace 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
336namespace 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
758namespace 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
2396namespace 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