summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2017-12-25 22:35:08 +0100
committerLéo Lam <leo@innovatetechnologi.es>2019-05-04 23:04:18 +0200
commit04c8201c323bd5cb7fd09beb456e4e77608270f7 (patch)
treef5089bf107a783068cbb54fc03a3fcdfc5a6d372 /Source/Core
parent99a4ca8de7111c8554b50217744e24bc71912cfe (diff)
Enable C++17
All supported platforms now have easy access to a compiler with C++17 support. C++17 potentially allows for some nice cleanups and removes the need for standard library backports (optional/variant). See discussion at https://dolp.in/pr6264#discussion_r158134178
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Compat/in_place.h45
-rw-r--r--Source/Core/Common/Compat/optional907
-rw-r--r--Source/Core/Common/Compat/variant2523
3 files changed, 0 insertions, 3475 deletions
diff --git a/Source/Core/Common/Compat/in_place.h b/Source/Core/Common/Compat/in_place.h
deleted file mode 100644
index bded66c019..0000000000
--- a/Source/Core/Common/Compat/in_place.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#include <cstddef>
-
-namespace mpark
-{
-struct in_place_t
-{
- explicit in_place_t() = default;
-};
-
-template <std::size_t I>
-struct in_place_index_t
-{
- explicit in_place_index_t() = default;
-};
-
-template <typename T>
-struct in_place_type_t
-{
- explicit in_place_type_t() = default;
-};
-
-#ifdef MPARK_VARIABLE_TEMPLATES
-constexpr in_place_t in_place{};
-
-template <std::size_t I>
-constexpr in_place_index_t<I> in_place_index{};
-
-template <typename T>
-constexpr in_place_type_t<T> in_place_type{};
-#endif
-
-} // namespace mpark
diff --git a/Source/Core/Common/Compat/optional b/Source/Core/Common/Compat/optional
deleted file mode 100644
index 1da42ff4d2..0000000000
--- a/Source/Core/Common/Compat/optional
+++ /dev/null
@@ -1,907 +0,0 @@
-// Copyright 2017 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#if __cplusplus >= 201703L && __has_include_next(<optional>)
-#include_next <optional>
-#else
-/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include <cassert>
-#include <functional>
-#include <initializer_list>
-#include <type_traits>
-#include <utility>
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions)
-#define GTL_HAS_EXCEPTIONS
-#endif
-
-namespace gtl {
-
-// A value of type gtl::optional<T> holds either a value of T or an
-// "empty" value. When it holds a value of T, it stores it as a direct
-// subobject, so sizeof(optional<T>) is approximately sizeof(T)+1. The interface
-// is based on the upcoming std::optional<T>, and gtl::optional<T> is
-// designed to be cheaply drop-in replaceable by std::optional<T>, once it is
-// rolled out.
-//
-// This implementation is based on the specification in the latest draft as of
-// 2017-01-05, section 20.6.
-//
-// Differences between gtl::optional<T> and std::optional<T> include:
-// - constexpr not used for nonconst member functions.
-// (dependency on some differences between C++11 and C++14.)
-// - nullopt and in_place are not constexpr. We need the inline variable
-// support in C++17 for external linkage.
-// - optional::swap() and swap() relies on std::is_(nothrow_)swappable
-// which is introduced in C++17. So we assume is_swappable is always true
-// and is_nothrow_swappable is same as std::is_trivial.
-// - make_optional cannot be constexpr due to absence of guaranteed copy
-// elision.
-//
-// Synopsis:
-//
-// #include "tensorflow/core/lib/gtl/optional.h"
-//
-// tensorflow::gtl::optional<string> f() {
-// string result;
-// if (...) {
-// ...
-// result = ...;
-// return result;
-// } else {
-// ...
-// return tensorflow::gtl::nullopt;
-// }
-// }
-//
-// int main() {
-// tensorflow::gtl::optional<string> optstr = f();
-// if (optstr) {
-// // non-empty
-// print(optstr.value());
-// } else {
-// // empty
-// error();
-// }
-// }
-template <typename T>
-class optional;
-
-// The tag constant `in_place` is used as the first parameter of an optional<T>
-// constructor to indicate that the remaining arguments should be forwarded
-// to the underlying T constructor.
-struct in_place_t {};
-extern const in_place_t in_place;
-
-// The tag constant `nullopt` is used to indicate an empty optional<T> in
-// certain functions, such as construction or assignment.
-struct nullopt_t {
- struct init_t {};
- static init_t init;
- // It must not be default-constructible to avoid ambiguity for opt = {}.
- // Note the non-const reference, it is to eliminate ambiguity for code like:
- // struct S { int value; };
- //
- // void Test() {
- // optional<S> opt;
- // opt = {{}};
- // }
- explicit constexpr nullopt_t(init_t& /*unused*/) {} // NOLINT
-};
-extern const nullopt_t nullopt;
-
-class bad_optional_access : public std::exception
-{
-public:
- virtual const char* what() const noexcept { return "bad_optional_access"; }
-};
-
-[[noreturn]] inline void throw_bad_optional_access()
-{
-#ifdef GTL_HAS_EXCEPTIONS
- throw bad_optional_access{};
-#else
- std::terminate();
-#endif
-}
-
-namespace internal_optional {
-
-// define forward locally because std::forward is not constexpr until C++14
-template <typename T>
-constexpr T&& forward(typename std::remove_reference<T>::type&
- t) noexcept { // NOLINT(runtime/references)
- return static_cast<T&&>(t);
-}
-
-struct empty_struct {};
-// This class stores the data in optional<T>.
-// It is specialized based on whether T is trivially destructible.
-// This is the specialization for non trivially destructible type.
-template <typename T, bool = std::is_trivially_destructible<T>::value>
-class optional_data_dtor_base {
- protected:
- // Whether there is data or not.
- bool engaged_;
- // data storage
- union {
- empty_struct dummy_;
- T data_;
- };
-
- void destruct() noexcept {
- if (engaged_) {
- data_.~T();
- engaged_ = false;
- }
- }
-
- // dummy_ must be initialized for constexpr constructor
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(internal_optional::forward<Args>(args)...) {}
-
- ~optional_data_dtor_base() { destruct(); }
-};
-
-// Specialization for trivially destructible type.
-template <typename T>
-class optional_data_dtor_base<T, true> {
- protected:
- // Whether there is data or not.
- bool engaged_;
- // data storage
- union {
- empty_struct dummy_;
- T data_;
- };
- void destruct() noexcept { engaged_ = false; }
-
- // dummy_ must be initialized for constexpr constructor
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(internal_optional::forward<Args>(args)...) {}
-
- ~optional_data_dtor_base() = default;
-};
-
-template <typename T>
-class optional_data : public optional_data_dtor_base<T> {
- protected:
- using base = optional_data_dtor_base<T>;
- using base::base;
-
- T* pointer() { return &this->data_; }
-
- constexpr const T* pointer() const { return &this->data_; }
-
- template <typename... Args>
- void construct(Args&&... args) {
- new (pointer()) T(std::forward<Args>(args)...);
- this->engaged_ = true;
- }
-
- template <typename U>
- void assign(U&& u) {
- if (this->engaged_) {
- this->data_ = std::forward<U>(u);
- } else {
- construct(std::forward<U>(u));
- }
- }
-
- optional_data() = default;
-
- optional_data(const optional_data& rhs) {
- if (rhs.engaged_) {
- construct(rhs.data_);
- }
- }
-
- optional_data(optional_data&& rhs) noexcept(
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- construct(std::move(rhs.data_));
- }
- }
-
- optional_data& operator=(const optional_data& rhs) {
- if (rhs.engaged_) {
- assign(rhs.data_);
- } else {
- this->destruct();
- }
- return *this;
- }
-
- optional_data& operator=(optional_data&& rhs) noexcept(
- std::is_nothrow_move_assignable<T>::value&&
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- assign(std::move(rhs.data_));
- } else {
- this->destruct();
- }
- return *this;
- }
-};
-
-// ordered by level of restriction, from low to high.
-// copyable implies movable.
-enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
-
-// base class for enabling/disabling copy/move constructor.
-template <copy_traits>
-class optional_ctor_base;
-
-template <>
-class optional_ctor_base<copy_traits::copyable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = default;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::non_movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = delete;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-// base class for enabling/disabling copy/move assignment.
-template <copy_traits>
-class optional_assign_base;
-
-template <>
-class optional_assign_base<copy_traits::copyable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = default;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::non_movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = delete;
-};
-
-template <typename T>
-constexpr copy_traits get_ctor_copy_traits() {
- return std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : std::is_move_constructible<T>::value ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-template <typename T>
-constexpr copy_traits get_assign_copy_traits() {
- return std::is_copy_assignable<T>::value &&
- std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : std::is_move_assignable<T>::value &&
- std::is_move_constructible<T>::value
- ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-// Whether T is constructible or convertible from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_from_optional
- : std::integral_constant<
- bool, std::is_constructible<T, optional<U>&>::value ||
- std::is_constructible<T, optional<U>&&>::value ||
- std::is_constructible<T, const optional<U>&>::value ||
- std::is_constructible<T, const optional<U>&&>::value ||
- std::is_convertible<optional<U>&, T>::value ||
- std::is_convertible<optional<U>&&, T>::value ||
- std::is_convertible<const optional<U>&, T>::value ||
- std::is_convertible<const optional<U>&&, T>::value> {};
-
-// Whether T is constructible or convertible or assignable from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_assignable_from_optional
- : std::integral_constant<
- bool, is_constructible_convertible_from_optional<T, U>::value ||
- std::is_assignable<T&, optional<U>&>::value ||
- std::is_assignable<T&, optional<U>&&>::value ||
- std::is_assignable<T&, const optional<U>&>::value ||
- std::is_assignable<T&, const optional<U>&&>::value> {};
-
-} // namespace internal_optional
-
-template <typename T>
-class optional : private internal_optional::optional_data<T>,
- private internal_optional::optional_ctor_base<
- internal_optional::get_ctor_copy_traits<T>()>,
- private internal_optional::optional_assign_base<
- internal_optional::get_assign_copy_traits<T>()> {
- using data_base = internal_optional::optional_data<T>;
-
- public:
- typedef T value_type;
-
- // [optional.ctor], constructors
-
- // A default constructed optional holds the empty value, NOT a default
- // constructed T.
- constexpr optional() noexcept {}
-
- // An optional initialized with `nullopt` holds the empty value.
- constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit)
-
- // Copy constructor, standard semantics.
- optional(const optional& src) = default;
-
- // Move constructor, standard semantics.
- optional(optional&& src) = default;
-
- // optional<T>(in_place, arg1, arg2, arg3) constructs a non-empty optional
- // with an in-place constructed value of T(arg1,arg2,arg3).
- // TODO(b/34201852): Add std::is_constructible<T, Args&&...> SFINAE.
- template <typename... Args>
- constexpr explicit optional(in_place_t, Args&&... args)
- : data_base(in_place_t(), internal_optional::forward<Args>(args)...) {}
-
- // optional<T>(in_place, {arg1, arg2, arg3}) constructs a non-empty optional
- // with an in-place list-initialized value of T({arg1, arg2, arg3}).
- template <typename U, typename... Args,
- typename = typename std::enable_if<std::is_constructible<
- T, std::initializer_list<U>&, Args&&...>::value>::type>
- constexpr explicit optional(in_place_t, std::initializer_list<U> il,
- Args&&... args)
- : data_base(in_place_t(), il, internal_optional::forward<Args>(args)...) {
- }
-
- template <
- typename U = T,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
- !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
- std::is_convertible<U&&, T>::value,
- bool>::type = false>
- constexpr optional(U&& v) // NOLINT
- : data_base(in_place_t(), internal_optional::forward<U>(v)) {}
-
- template <
- typename U = T,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !std::is_same<in_place_t, typename std::decay<U>::type>::value &&
- !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
- !std::is_convertible<U&&, T>::value,
- bool>::type = false>
- explicit constexpr optional(U&& v)
- : data_base(in_place_t(), internal_optional::forward<U>(v)) {}
-
- // Converting copy constructor (implicit)
- template <
- typename U,
- typename std::enable_if<
- std::is_constructible<T, const U&>::value &&
- !internal_optional::is_constructible_convertible_from_optional<
- T, U>::value &&
- std::is_convertible<const U&, T>::value,
- bool>::type = false>
- optional(const optional<U>& rhs) { // NOLINT
- if (rhs) {
- this->construct(*rhs);
- }
- }
-
- // Converting copy constructor (explicit)
- template <
- typename U,
- typename std::enable_if<
- std::is_constructible<T, const U&>::value &&
- !internal_optional::is_constructible_convertible_from_optional<
- T, U>::value &&
- !std::is_convertible<const U&, T>::value,
- bool>::type = false>
- explicit optional(const optional<U>& rhs) {
- if (rhs) {
- this->construct(*rhs);
- }
- }
-
- // Converting move constructor (implicit)
- template <
- typename U,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !internal_optional::is_constructible_convertible_from_optional<
- T, U>::value &&
- std::is_convertible<U&&, T>::value,
- bool>::type = false>
- optional(optional<U>&& rhs) { // NOLINT
- if (rhs) {
- this->construct(std::move(*rhs));
- }
- }
-
- // Converting move constructor (explicit)
- template <
- typename U,
- typename std::enable_if<
- std::is_constructible<T, U&&>::value &&
- !internal_optional::is_constructible_convertible_from_optional<
- T, U>::value &&
- !std::is_convertible<U&&, T>::value,
- bool>::type = false>
- explicit optional(optional<U>&& rhs) {
- if (rhs) {
- this->construct(std::move(*rhs));
- }
- }
-
- // [optional.dtor], destructor, trivial if T is trivially destructible.
- ~optional() = default;
-
- // [optional.assign], assignment
-
- // Assignment from nullopt: opt = nullopt
- optional& operator=(nullopt_t) noexcept {
- this->destruct();
- return *this;
- }
-
- // Copy assigment, standard semantics.
- optional& operator=(const optional& src) = default;
-
- // Move assignment, standard semantics.
- optional& operator=(optional&& src) = default;
-
- // Value assignment
- template <
- typename U = T,
- typename = typename std::enable_if<
- !std::is_same<optional<T>, typename std::decay<U>::type>::value &&
- (!std::is_scalar<T>::value ||
- !std::is_same<T, typename std::decay<U>::type>::value) &&
- std::is_constructible<T, U>::value &&
- std::is_assignable<T&, U>::value>::type>
- optional& operator=(U&& v) {
- this->assign(std::forward<U>(v));
- return *this;
- }
-
- template <typename U,
- typename = typename std::enable_if<
- std::is_constructible<T, const U&>::value &&
- std::is_assignable<T&, const U&>::value &&
- !internal_optional::
- is_constructible_convertible_assignable_from_optional<
- T, U>::value>::type>
- optional& operator=(const optional<U>& rhs) {
- if (rhs) {
- this->assign(*rhs);
- } else {
- this->destruct();
- }
- return *this;
- }
-
- template <typename U,
- typename = typename std::enable_if<
- std::is_constructible<T, U>::value &&
- std::is_assignable<T&, U>::value &&
- !internal_optional::
- is_constructible_convertible_assignable_from_optional<
- T, U>::value>::type>
- optional& operator=(optional<U>&& rhs) {
- if (rhs) {
- this->assign(std::move(*rhs));
- } else {
- this->destruct();
- }
- return *this;
- }
-
- // [optional.mod], modifiers
- // Destroys the inner T value if one is present.
- void reset() noexcept { this->destruct(); }
-
- // Emplace reconstruction. (Re)constructs the underlying T in-place with the
- // given arguments forwarded:
- //
- // optional<Foo> opt;
- // opt.emplace(arg1,arg2,arg3); (Constructs Foo(arg1,arg2,arg3))
- //
- // If the optional is non-empty, and the `args` refer to subobjects of the
- // current object, then behavior is undefined. This is because the current
- // object will be destructed before the new object is constructed with `args`.
- //
- template <typename... Args,
- typename = typename std::enable_if<
- std::is_constructible<T, Args&&...>::value>::type>
- void emplace(Args&&... args) {
- this->destruct();
- this->construct(std::forward<Args>(args)...);
- }
-
- // Emplace reconstruction with initializer-list. See immediately above.
- template <class U, class... Args,
- typename = typename std::enable_if<std::is_constructible<
- T, std::initializer_list<U>&, Args&&...>::value>::type>
- void emplace(std::initializer_list<U> il, Args&&... args) {
- this->destruct();
- this->construct(il, std::forward<Args>(args)...);
- }
-
- // [optional.swap], swap
- // Swap, standard semantics.
- void swap(optional& rhs) noexcept(
- std::is_nothrow_move_constructible<T>::value&&
- std::is_trivial<T>::value) {
- if (*this) {
- if (rhs) {
- using std::swap;
- swap(**this, *rhs);
- } else {
- rhs.construct(std::move(**this));
- this->destruct();
- }
- } else {
- if (rhs) {
- this->construct(std::move(*rhs));
- rhs.destruct();
- } else {
- // no effect (swap(disengaged, disengaged))
- }
- }
- }
-
- // [optional.observe], observers
- // You may use `*opt`, and `opt->m`, to access the underlying T value and T's
- // member `m`, respectively. If the optional is empty, behavior is
- // undefined.
- constexpr const T* operator->() const { return this->pointer(); }
- T* operator->() {
- assert(this->engaged_);
- return this->pointer();
- }
- constexpr const T& operator*() const & { return reference(); }
- T& operator*() & {
- assert(this->engaged_);
- return reference();
- }
- constexpr const T&& operator*() const && { return std::move(reference()); }
- T&& operator*() && {
- assert(this->engaged_);
- return std::move(reference());
- }
-
- // In a bool context an optional<T> will return false if and only if it is
- // empty.
- //
- // if (opt) {
- // // do something with opt.value();
- // } else {
- // // opt is empty
- // }
- //
- constexpr explicit operator bool() const noexcept { return this->engaged_; }
-
- // Returns false if and only if *this is empty.
- constexpr bool has_value() const noexcept { return this->engaged_; }
-
- // Use `opt.value()` to get a reference to underlying value. The constness
- // and lvalue/rvalue-ness of `opt` is preserved to the view of the T
- // subobject.
- const T& value() const & {
- if (!*this)
- throw_bad_optional_access();
- return reference();
- }
- T& value() & {
- if (!*this)
- throw_bad_optional_access();
- return reference();
- }
- T&& value() && { // NOLINT(build/c++11)
- if (!*this)
- throw_bad_optional_access();
- return std::move(reference());
- }
- const T&& value() const && { // NOLINT(build/c++11)
- if (!*this)
- throw_bad_optional_access();
- return std::move(reference());
- }
-
- // Use `opt.value_or(val)` to get either the value of T or the given default
- // `val` in the empty case.
- template <class U>
- constexpr T value_or(U&& v) const & {
- return static_cast<bool>(*this) ? **this
- : static_cast<T>(std::forward<U>(v));
- }
- template <class U>
- T value_or(U&& v) && { // NOLINT(build/c++11)
- return static_cast<bool>(*this) ? std::move(**this)
- : static_cast<T>(std::forward<U>(v));
- }
-
- private:
- // Private accessors for internal storage viewed as reference to T.
- constexpr const T& reference() const { return *this->pointer(); }
- T& reference() { return *(this->pointer()); }
-
- // T constaint checks. You can't have an optional of nullopt_t, in_place_t or
- // a reference.
- static_assert(
- !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
- "optional<nullopt_t> is not allowed.");
- static_assert(
- !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
- "optional<in_place_t> is not allowed.");
- static_assert(!std::is_reference<T>::value,
- "optional<reference> is not allowed.");
-};
-
-// [optional.specalg]
-// Swap, standard semantics.
-// This function shall not participate in overload resolution unless
-// is_move_constructible_v<T> is true and is_swappable_v<T> is true.
-// NOTE: we assume is_swappable is always true. There will be a compiling error
-// if T is actually not Swappable.
-template <typename T,
- typename std::enable_if<std::is_move_constructible<T>::value,
- bool>::type = false>
-void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
- a.swap(b);
-}
-
-// NOTE: make_optional cannot be constexpr in C++11 because the copy/move
-// constructor is not constexpr and we don't have guaranteed copy elision
-// util C++17. But they are still declared constexpr for consistency with
-// the standard.
-
-// make_optional(v) creates a non-empty optional<T> where the type T is deduced
-// from v. Can also be explicitly instantiated as make_optional<T>(v).
-template <typename T>
-constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
- return optional<typename std::decay<T>::type>(std::forward<T>(v));
-}
-
-template <typename T, typename... Args>
-constexpr optional<T> make_optional(Args&&... args) {
- return optional<T>(in_place_t(), internal_optional::forward<Args>(args)...);
-}
-
-template <typename T, typename U, typename... Args>
-constexpr optional<T> make_optional(std::initializer_list<U> il,
- Args&&... args) {
- return optional<T>(in_place_t(), il,
- internal_optional::forward<Args>(args)...);
-}
-
-// Relational operators. Empty optionals are considered equal to each
-// other and less than non-empty optionals. Supports relations between
-// optional<T> and optional<T>, between optional<T> and T, and between
-// optional<T> and nullopt.
-// Note: We're careful to support T having non-bool relationals.
-
-// Relational operators [optional.relops]
-// The C++17 (N4606) "Returns:" statements are translated into code
-// in an obvious way here, and the original text retained as function docs.
-// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true;
-// otherwise *x == *y.
-template <class T>
-constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
- return static_cast<bool>(x) != static_cast<bool>(y)
- ? false
- : static_cast<bool>(x) == false ? true : *x == *y;
-}
-// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false;
-// otherwise *x != *y.
-template <class T>
-constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
- return static_cast<bool>(x) != static_cast<bool>(y)
- ? true
- : static_cast<bool>(x) == false ? false : *x != *y;
-}
-// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
-template <class T>
-constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
- return !y ? false : !x ? true : *x < *y;
-}
-// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
-template <class T>
-constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
- return !x ? false : !y ? true : *x > *y;
-}
-// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
-template <class T>
-constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
- return !x ? true : !y ? false : *x <= *y;
-}
-// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
-template <class T>
-constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
- return !y ? true : !x ? false : *x >= *y;
-}
-
-// Comparison with nullopt [optional.nullops]
-// The C++17 (N4606) "Returns:" statements are used directly here.
-template <class T>
-constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
- return !x;
-}
-template <class T>
-constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
- return !x;
-}
-template <class T>
-constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
- return static_cast<bool>(x);
-}
-template <class T>
-constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
- return static_cast<bool>(x);
-}
-template <class T>
-constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept {
- return false;
-}
-template <class T>
-constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
- return static_cast<bool>(x);
-}
-template <class T>
-constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
- return !x;
-}
-template <class T>
-constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept {
- return true;
-}
-template <class T>
-constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
- return static_cast<bool>(x);
-}
-template <class T>
-constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept {
- return false;
-}
-template <class T>
-constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept {
- return true;
-}
-template <class T>
-constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
- return !x;
-}
-
-// Comparison with T [optional.comp_with_t]
-// The C++17 (N4606) "Equivalent to:" statements are used directly here.
-template <class T>
-constexpr bool operator==(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x == v : false;
-}
-template <class T>
-constexpr bool operator==(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v == *x : false;
-}
-template <class T>
-constexpr bool operator!=(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x != v : true;
-}
-template <class T>
-constexpr bool operator!=(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v != *x : true;
-}
-template <class T>
-constexpr bool operator<(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x < v : true;
-}
-template <class T>
-constexpr bool operator<(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v < *x : false;
-}
-template <class T>
-constexpr bool operator<=(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x <= v : true;
-}
-template <class T>
-constexpr bool operator<=(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v <= *x : false;
-}
-template <class T>
-constexpr bool operator>(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x > v : false;
-}
-template <class T>
-constexpr bool operator>(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v > *x : true;
-}
-template <class T>
-constexpr bool operator>=(const optional<T>& x, const T& v) {
- return static_cast<bool>(x) ? *x >= v : false;
-}
-template <class T>
-constexpr bool operator>=(const T& v, const optional<T>& x) {
- return static_cast<bool>(x) ? v >= *x : true;
-}
-
-} // namespace gtl
-
-namespace std {
-
-template <class T>
-struct hash<::gtl::optional<T>> {
- size_t operator()(const ::gtl::optional<T>& opt) const {
- if (opt) {
- return hash<T>()(*opt);
- } else {
- return static_cast<size_t>(0x297814aaad196e6dULL);
- }
- }
-};
-
-using ::gtl::optional;
-using ::gtl::bad_optional_access;
-using ::gtl::nullopt_t;
-using ::gtl::nullopt;
-using ::gtl::make_optional;
-} // namespace std
-
-#endif
diff --git a/Source/Core/Common/Compat/variant b/Source/Core/Common/Compat/variant
deleted file mode 100644
index 45d8b81d15..0000000000
--- a/Source/Core/Common/Compat/variant
+++ /dev/null
@@ -1,2523 +0,0 @@
-// Copyright 2017 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#if __cplusplus >= 201703L && __has_include_next(<variant>)
-#include_next <variant>
-#else
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-/*
- variant synopsis
-
-namespace std {
-
- // 20.7.2, class template variant
- template <class... Types>
- class variant {
- public:
-
- // 20.7.2.1, constructors
- constexpr variant() noexcept(see below);
- variant(const variant&);
- variant(variant&&) noexcept(see below);
-
- template <class T> constexpr variant(T&&) noexcept(see below);
-
- template <class T, class... Args>
- constexpr explicit variant(in_place_type_t<T>, Args&&...);
-
- template <class T, class U, class... Args>
- constexpr explicit variant(
- in_place_type_t<T>, initializer_list<U>, Args&&...);
-
- template <size_t I, class... Args>
- constexpr explicit variant(in_place_index_t<I>, Args&&...);
-
- template <size_t I, class U, class... Args>
- constexpr explicit variant(
- in_place_index_t<I>, initializer_list<U>, Args&&...);
-
- // 20.7.2.2, destructor
- ~variant();
-
- // 20.7.2.3, assignment
- variant& operator=(const variant&);
- variant& operator=(variant&&) noexcept(see below);
-
- template <class T> variant& operator=(T&&) noexcept(see below);
-
- // 20.7.2.4, modifiers
- template <class T, class... Args>
- T& emplace(Args&&...);
-
- template <class T, class U, class... Args>
- T& emplace(initializer_list<U>, Args&&...);
-
- template <size_t I, class... Args>
- variant_alternative<I, variant>& emplace(Args&&...);
-
- template <size_t I, class U, class... Args>
- variant_alternative<I, variant>& emplace(initializer_list<U>, Args&&...);
-
- // 20.7.2.5, value status
- constexpr bool valueless_by_exception() const noexcept;
- constexpr size_t index() const noexcept;
-
- // 20.7.2.6, swap
- void swap(variant&) noexcept(see below);
- };
-
- // 20.7.3, variant helper classes
- template <class T> struct variant_size; // undefined
-
- template <class T>
- constexpr size_t variant_size_v = variant_size<T>::value;
-
- template <class T> struct variant_size<const T>;
- template <class T> struct variant_size<volatile T>;
- template <class T> struct variant_size<const volatile T>;
-
- template <class... Types>
- struct variant_size<variant<Types...>>;
-
- template <size_t I, class T> struct variant_alternative; // undefined
-
- template <size_t I, class T>
- using variant_alternative_t = typename variant_alternative<I, T>::type;
-
- template <size_t I, class T> struct variant_alternative<I, const T>;
- template <size_t I, class T> struct variant_alternative<I, volatile T>;
- template <size_t I, class T> struct variant_alternative<I, const volatile T>;
-
- template <size_t I, class... Types>
- struct variant_alternative<I, variant<Types...>>;
-
- constexpr size_t variant_npos = -1;
-
- // 20.7.4, value access
- template <class T, class... Types>
- constexpr bool holds_alternative(const variant<Types...>&) noexcept;
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>>&
- get(variant<Types...>&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>>&&
- get(variant<Types...>&&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>> const&
- get(const variant<Types...>&);
-
- template <size_t I, class... Types>
- constexpr variant_alternative_t<I, variant<Types...>> const&&
- get(const variant<Types...>&&);
-
- template <class T, class... Types>
- constexpr T& get(variant<Types...>&);
-
- template <class T, class... Types>
- constexpr T&& get(variant<Types...>&&);
-
- template <class T, class... Types>
- constexpr const T& get(const variant<Types...>&);
-
- template <class T, class... Types>
- constexpr const T&& get(const variant<Types...>&&);
-
- template <size_t I, class... Types>
- constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
- get_if(variant<Types...>*) noexcept;
-
- template <size_t I, class... Types>
- constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
- get_if(const variant<Types...>*) noexcept;
-
- template <class T, class... Types>
- constexpr add_pointer_t<T>
- get_if(variant<Types...>*) noexcept;
-
- template <class T, class... Types>
- constexpr add_pointer_t<const T>
- get_if(const variant<Types...>*) noexcept;
-
- // 20.7.5, relational operators
- template <class... Types>
- constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
-
- template <class... Types>
- constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
-
- // 20.7.6, visitation
- template <class Visitor, class... Variants>
- constexpr see below visit(Visitor&&, Variants&&...);
-
- // 20.7.7, class monostate
- struct monostate;
-
- // 20.7.8, monostate relational operators
- constexpr bool operator<(monostate, monostate) noexcept;
- constexpr bool operator>(monostate, monostate) noexcept;
- constexpr bool operator<=(monostate, monostate) noexcept;
- constexpr bool operator>=(monostate, monostate) noexcept;
- constexpr bool operator==(monostate, monostate) noexcept;
- constexpr bool operator!=(monostate, monostate) noexcept;
-
- // 20.7.9, specialized algorithms
- template <class... Types>
- void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
-
- // 20.7.10, class bad_variant_access
- class bad_variant_access;
-
- // 20.7.11, hash support
- template <class T> struct hash;
- template <class... Types> struct hash<variant<Types...>>;
- template <> struct hash<monostate>;
-
-} // namespace std
-
-*/
-
-#include <cstddef>
-#include <exception>
-#include <functional>
-#include <initializer_list>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_CONFIG_HPP
-#define MPARK_CONFIG_HPP
-
-// MSVC 2015 Update 3.
-#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
-#error "MPark.Variant requires C++11 support."
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#ifndef __has_include
-#define __has_include(x) 0
-#endif
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if __has_builtin(__builtin_addressof) || (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
-#define MPARK_BUILTIN_ADDRESSOF
-#endif
-
-#if __has_builtin(__builtin_unreachable)
-#define MPARK_BUILTIN_UNREACHABLE
-#endif
-
-#if __has_builtin(__type_pack_element)
-#define MPARK_TYPE_PACK_ELEMENT
-#endif
-
-#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
-#define MPARK_CPP14_CONSTEXPR
-#endif
-
-#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
- (defined(_MSC_VER) && defined(_CPPUNWIND))
-#define MPARK_EXCEPTIONS
-#endif
-
-#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
-#define MPARK_GENERIC_LAMBDAS
-#endif
-
-#if defined(__cpp_lib_integer_sequence)
-#define MPARK_INTEGER_SEQUENCE
-#endif
-
-#if defined(__cpp_return_type_deduction) || defined(_MSC_VER)
-#define MPARK_RETURN_TYPE_DEDUCTION
-#endif
-
-#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
-#define MPARK_TRANSPARENT_OPERATORS
-#endif
-
-#if defined(__cpp_variable_templates) || defined(_MSC_VER)
-#define MPARK_VARIABLE_TEMPLATES
-#endif
-
-#if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5
-#define MPARK_TRIVIALITY_TYPE_TRAITS
-#endif
-
-#endif // MPARK_CONFIG_HPP
-
-#include "in_place.h"
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#ifndef MPARK_LIB_HPP
-#define MPARK_LIB_HPP
-
-#include <functional>
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-#define RETURN(...) \
- noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; }
-
-namespace mpark
-{
-namespace lib
-{
-template <typename T>
-struct identity
-{
- using type = T;
-};
-
-inline namespace cpp14
-{
-template <typename T, std::size_t N>
-struct array
-{
- constexpr const T& operator[](std::size_t index) const { return data[index]; }
-
- T data[N == 0 ? 1 : N];
-};
-
-template <typename T>
-using add_pointer_t = typename std::add_pointer<T>::type;
-
-template <typename... Ts>
-using common_type_t = typename std::common_type<Ts...>::type;
-
-template <typename T>
-using decay_t = typename std::decay<T>::type;
-
-template <bool B, typename T = void>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-template <typename T>
-using remove_const_t = typename std::remove_const<T>::type;
-
-template <typename T>
-using remove_reference_t = typename std::remove_reference<T>::type;
-
-template <typename T>
-inline constexpr T&& forward(remove_reference_t<T>& t) noexcept
-{
- return static_cast<T&&>(t);
-}
-
-template <typename T>
-inline constexpr T&& forward(remove_reference_t<T>&& t) noexcept
-{
- static_assert(!std::is_lvalue_reference<T>::value, "can not forward an rvalue as an lvalue");
- return static_cast<T&&>(t);
-}
-
-template <typename T>
-inline constexpr remove_reference_t<T>&& move(T&& t) noexcept
-{
- return static_cast<remove_reference_t<T>&&>(t);
-}
-
-#ifdef MPARK_INTEGER_SEQUENCE
-using std::index_sequence;
-using std::index_sequence_for;
-using std::integer_sequence;
-using std::make_index_sequence;
-#else
-template <typename T, T... Is>
-struct integer_sequence
-{
- using value_type = T;
- static constexpr std::size_t size() noexcept { return sizeof...(Is); }
-};
-
-template <std::size_t... Is>
-using index_sequence = integer_sequence<std::size_t, Is...>;
-
-template <typename Lhs, typename Rhs>
-struct make_index_sequence_concat;
-
-template <std::size_t... Lhs, std::size_t... Rhs>
-struct make_index_sequence_concat<index_sequence<Lhs...>, index_sequence<Rhs...>>
- : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>>
-{
-};
-
-template <std::size_t N>
-struct make_index_sequence_impl;
-
-template <std::size_t N>
-using make_index_sequence = typename make_index_sequence_impl<N>::type;
-
-template <std::size_t N>
-struct make_index_sequence_impl
- : make_index_sequence_concat<make_index_sequence<N / 2>, make_index_sequence<N - (N / 2)>>
-{
-};
-
-template <>
-struct make_index_sequence_impl<0> : identity<index_sequence<>>
-{
-};
-
-template <>
-struct make_index_sequence_impl<1> : identity<index_sequence<0>>
-{
-};
-
-template <typename... Ts>
-using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
-#endif
-
-// <functional>
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using equal_to = std::equal_to<>;
-#else
-struct equal_to
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
-};
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using not_equal_to = std::not_equal_to<>;
-#else
-struct not_equal_to
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
-};
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using less = std::less<>;
-#else
-struct less
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
-};
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using greater = std::greater<>;
-#else
-struct greater
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
-};
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using less_equal = std::less_equal<>;
-#else
-struct less_equal
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
-};
-#endif
-
-#ifdef MPARK_TRANSPARENT_OPERATORS
-using greater_equal = std::greater_equal<>;
-#else
-struct greater_equal
-{
- template <typename Lhs, typename Rhs>
- inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const
- RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
-};
-#endif
-} // namespace cpp14
-
-inline namespace cpp17
-{
-// <type_traits>
-template <bool B>
-using bool_constant = std::integral_constant<bool, B>;
-
-template <typename...>
-struct voider : identity<void>
-{
-};
-
-template <typename... Ts>
-using void_t = typename voider<Ts...>::type;
-
-namespace detail
-{
-namespace swappable
-{
-using std::swap;
-
-template <typename T>
-struct is_swappable
-{
-private:
- template <typename U, typename = decltype(swap(std::declval<U&>(), std::declval<U&>()))>
- inline static std::true_type test(int);
-
- template <typename U>
- inline static std::false_type test(...);
-
-public:
- static constexpr bool value = decltype(test<T>(0))::value;
-};
-
-template <typename T, bool = is_swappable<T>::value>
-struct is_nothrow_swappable
-{
- static constexpr bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
-};
-
-template <typename T>
-struct is_nothrow_swappable<T, false> : std::false_type
-{
-};
-
-} // namespace swappable
-} // namespace detail
-
-using detail::swappable::is_nothrow_swappable;
-using detail::swappable::is_swappable;
-
-// <functional>
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
-template <typename F, typename... As>
-inline constexpr auto invoke(F&& f, As&&... as) RETURN(lib::forward<F>(f)(lib::forward<As>(as)...))
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
- template <typename B, typename T, typename D>
- inline constexpr auto invoke(T B::*pmv, D&& d) RETURN(lib::forward<D>(d).*pmv)
-
- template <typename Pmv, typename Ptr>
- inline constexpr auto invoke(Pmv pmv, Ptr&& ptr) RETURN((*lib::forward<Ptr>(ptr)).*pmv)
-
- template <typename B, typename T, typename D, typename... As>
- inline constexpr auto invoke(T B::*pmf, D&& d, As&&... as)
- RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...))
-
- template <typename Pmf, typename Ptr, typename... As>
- inline constexpr auto invoke(Pmf pmf, Ptr&& ptr, As&&... as)
- RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...))
-
- namespace detail
-{
- template <typename Void, typename, typename...>
- struct invoke_result
- {
- };
-
- template <typename F, typename... Args>
- struct invoke_result<void_t<decltype(lib::invoke(std::declval<F>(), std::declval<Args>()...))>, F,
- Args...>
- : identity<decltype(lib::invoke(std::declval<F>(), std::declval<Args>()...))>
- {
- };
-
-} // namespace detail
-
-template <typename F, typename... Args>
-using invoke_result = detail::invoke_result<void, F, Args...>;
-
-template <typename F, typename... Args>
-using invoke_result_t = typename invoke_result<F, Args...>::type;
-
-namespace detail
-{
-template <typename Void, typename, typename...>
-struct is_invocable : std::false_type
-{
-};
-
-template <typename F, typename... Args>
-struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...> : std::true_type
-{
-};
-
-template <typename Void, typename, typename, typename...>
-struct is_invocable_r : std::false_type
-{
-};
-
-template <typename R, typename F, typename... Args>
-struct is_invocable_r<void_t<invoke_result_t<F, Args...>>, R, F, Args...>
- : std::is_convertible<invoke_result_t<F, Args...>, R>
-{
-};
-
-} // namespace detail
-
-template <typename F, typename... Args>
-using is_invocable = detail::is_invocable<void, F, Args...>;
-
-template <typename R, typename F, typename... Args>
-using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
-
-// <memory>
-#ifdef MPARK_BUILTIN_ADDRESSOF
-template <typename T>
-inline constexpr T* addressof(T& arg)
-{
- return __builtin_addressof(arg);
-}
-#else
-namespace detail
-{
-namespace has_addressof_impl
-{
-struct fail;
-
-template <typename T>
-inline fail operator&(T&&);
-
-template <typename T>
-inline static constexpr bool impl()
-{
- return (std::is_class<T>::value || std::is_union<T>::value) &&
- !std::is_same<decltype(&std::declval<T&>()), fail>::value;
-}
-
-} // namespace has_addressof_impl
-
-template <typename T>
-using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
-
-template <typename T>
-inline constexpr T* addressof(T& arg, std::true_type)
-{
- return std::addressof(arg);
-}
-
-template <typename T>
-inline constexpr T* addressof(T& arg, std::false_type)
-{
- return &arg;
-}
-
-} // namespace detail
-
-template <typename T>
-inline constexpr T* addressof(T& arg)
-{
- return detail::addressof(arg, detail::has_addressof<T>{});
-}
-#endif
-
-template <typename T>
-inline constexpr T* addressof(const T&&) = delete;
-
-} // namespace cpp17
-
-template <typename T>
-struct remove_all_extents : identity<T>
-{
-};
-
-template <typename T, std::size_t N>
-struct remove_all_extents<array<T, N>> : remove_all_extents<T>
-{
-};
-
-template <typename T>
-using remove_all_extents_t = typename remove_all_extents<T>::type;
-
-template <std::size_t N>
-using size_constant = std::integral_constant<std::size_t, N>;
-
-template <std::size_t I, typename T>
-struct indexed_type : size_constant<I>, identity<T>
-{
-};
-
-template <bool... Bs>
-using all = std::is_same<integer_sequence<bool, true, Bs...>, integer_sequence<bool, Bs..., true>>;
-
-#ifdef MPARK_TYPE_PACK_ELEMENT
-template <std::size_t I, typename... Ts>
-using type_pack_element_t = __type_pack_element<I, Ts...>;
-#else
-template <std::size_t I, typename... Ts>
-struct type_pack_element_impl
-{
-private:
- template <typename>
- struct set;
-
- template <std::size_t... Is>
- struct set<index_sequence<Is...>> : indexed_type<Is, Ts>...
- {
- };
-
- template <typename T>
- inline static std::enable_if<true, T> impl(indexed_type<I, T>);
-
- inline static std::enable_if<false> impl(...);
-
-public:
- using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
-};
-
-template <std::size_t I, typename... Ts>
-using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
-
-template <std::size_t I, typename... Ts>
-using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
-#endif
-
-#ifdef MPARK_TRIVIALITY_TYPE_TRAITS
-using std::is_trivially_copy_assignable;
-using std::is_trivially_copy_constructible;
-using std::is_trivially_move_assignable;
-using std::is_trivially_move_constructible;
-#else
-template <typename T>
-struct is_trivially_copy_constructible
- : bool_constant<std::is_copy_constructible<T>::value&& __has_trivial_copy(T)>
-{
-};
-
-template <typename T>
-struct is_trivially_move_constructible : bool_constant<__is_trivial(T)>
-{
-};
-
-template <typename T>
-struct is_trivially_copy_assignable
- : bool_constant<std::is_copy_assignable<T>::value&& __has_trivial_assign(T)>
-{
-};
-
-template <typename T>
-struct is_trivially_move_assignable : bool_constant<__is_trivial(T)>
-{
-};
-#endif
-
-template <typename T, bool>
-struct dependent_type : T
-{
-};
-
-template <typename Is, std::size_t J>
-struct push_back;
-
-template <typename Is, std::size_t J>
-using push_back_t = typename push_back<Is, J>::type;
-
-template <std::size_t... Is, std::size_t J>
-struct push_back<index_sequence<Is...>, J>
-{
- using type = index_sequence<Is..., J>;
-};
-
-} // namespace lib
-} // namespace mpark
-
-#undef RETURN
-
-#endif // MPARK_LIB_HPP
-
-namespace mpark
-{
-
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
-
-#define AUTO auto
-#define AUTO_RETURN(...) \
- { \
- return __VA_ARGS__; \
- }
-
-#define AUTO_REFREF auto&&
-#define AUTO_REFREF_RETURN(...) \
- { \
- return __VA_ARGS__; \
- }
-
-#define DECLTYPE_AUTO decltype(auto)
-#define DECLTYPE_AUTO_RETURN(...) \
- { \
- return __VA_ARGS__; \
- }
-
-#else
-
-#define AUTO auto
-#define AUTO_RETURN(...) \
- ->lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
-
-#define AUTO_REFREF auto
-#define AUTO_REFREF_RETURN(...) \
- ->decltype((__VA_ARGS__)) \
- { \
- static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
- return __VA_ARGS__; \
- }
-
-#define DECLTYPE_AUTO auto
-#define DECLTYPE_AUTO_RETURN(...) \
- ->decltype(__VA_ARGS__) { return __VA_ARGS__; }
-
-#endif
-
-class bad_variant_access : public std::exception
-{
-public:
- virtual const char* what() const noexcept { return "bad_variant_access"; }
-};
-
-[[noreturn]] inline void throw_bad_variant_access()
-{
-#ifdef MPARK_EXCEPTIONS
- throw bad_variant_access{};
-#else
- std::terminate();
-#ifdef MPARK_BUILTIN_UNREACHABLE
- __builtin_unreachable();
-#endif
-#endif
-}
-
-template <typename... Ts>
-class variant;
-
-template <typename T>
-struct variant_size;
-
-#ifdef MPARK_VARIABLE_TEMPLATES
-template <typename T>
-constexpr std::size_t variant_size_v = variant_size<T>::value;
-#endif
-
-template <typename T>
-struct variant_size<const T> : variant_size<T>
-{
-};
-
-template <typename T>
-struct variant_size<volatile T> : variant_size<T>
-{
-};
-
-template <typename T>
-struct variant_size<const volatile T> : variant_size<T>
-{
-};
-
-template <typename... Ts>
-struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)>
-{
-};
-
-template <std::size_t I, typename T>
-struct variant_alternative;
-
-template <std::size_t I, typename T>
-using variant_alternative_t = typename variant_alternative<I, T>::type;
-
-template <std::size_t I, typename T>
-struct variant_alternative<I, const T> : std::add_const<variant_alternative_t<I, T>>
-{
-};
-
-template <std::size_t I, typename T>
-struct variant_alternative<I, volatile T> : std::add_volatile<variant_alternative_t<I, T>>
-{
-};
-
-template <std::size_t I, typename T>
-struct variant_alternative<I, const volatile T> : std::add_cv<variant_alternative_t<I, T>>
-{
-};
-
-template <std::size_t I, typename... Ts>
-struct variant_alternative<I, variant<Ts...>>
-{
- static_assert(I < sizeof...(Ts), "Index out of bounds in std::variant_alternative<>");
- using type = lib::type_pack_element_t<I, Ts...>;
-};
-
-constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
-
-namespace detail
-{
-constexpr std::size_t not_found = static_cast<std::size_t>(-1);
-constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);
-
-#ifdef MPARK_CPP14_CONSTEXPR
-template <typename T, typename... Ts>
-inline constexpr std::size_t find_index()
-{
- constexpr lib::array<bool, sizeof...(Ts)> matches = {{std::is_same<T, Ts>::value...}};
- std::size_t result = not_found;
- for (std::size_t i = 0; i < sizeof...(Ts); ++i)
- {
- if (matches[i])
- {
- if (result != not_found)
- {
- return ambiguous;
- }
- result = i;
- }
- }
- return result;
-}
-#else
-inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t)
-{
- return result;
-}
-
-template <typename... Bs>
-inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t idx, bool b, Bs... bs)
-{
- return b ? (result != not_found ? ambiguous : find_index_impl(idx, idx + 1, bs...)) :
- find_index_impl(result, idx + 1, bs...);
-}
-
-template <typename T, typename... Ts>
-inline constexpr std::size_t find_index()
-{
- return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);
-}
-#endif
-
-template <std::size_t I>
-using find_index_sfinae_impl =
- lib::enable_if_t<I != not_found && I != ambiguous, lib::size_constant<I>>;
-
-template <typename T, typename... Ts>
-using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
-
-template <std::size_t I>
-struct find_index_checked_impl : lib::size_constant<I>
-{
- static_assert(I != not_found, "the specified type is not found.");
- static_assert(I != ambiguous, "the specified type is ambiguous.");
-};
-
-template <typename T, typename... Ts>
-using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
-
-struct valueless_t
-{
-};
-
-enum class Trait
-{
- TriviallyAvailable,
- Available,
- Unavailable
-};
-
-template <typename T, template <typename> class IsTriviallyAvailable,
- template <typename> class IsAvailable>
-inline constexpr Trait trait()
-{
- return IsTriviallyAvailable<T>::value ?
- Trait::TriviallyAvailable :
- IsAvailable<T>::value ? Trait::Available : Trait::Unavailable;
-}
-
-#ifdef MPARK_CPP14_CONSTEXPR
-template <typename... Traits>
-inline constexpr Trait common_trait(Traits... traits)
-{
- Trait result = Trait::TriviallyAvailable;
- for (Trait t : {traits...})
- {
- if (static_cast<int>(t) > static_cast<int>(result))
- {
- result = t;
- }
- }
- return result;
-}
-#else
-inline constexpr Trait common_trait_impl(Trait result)
-{
- return result;
-}
-
-template <typename... Traits>
-inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts)
-{
- return static_cast<int>(t) > static_cast<int>(result) ? common_trait_impl(t, ts...) :
- common_trait_impl(result, ts...);
-}
-
-template <typename... Traits>
-inline constexpr Trait common_trait(Traits... ts)
-{
- return common_trait_impl(Trait::TriviallyAvailable, ts...);
-}
-#endif
-
-template <typename... Ts>
-struct traits
-{
- static constexpr Trait copy_constructible_trait = common_trait(
- trait<Ts, lib::is_trivially_copy_constructible, std::is_copy_constructible>()...);
-
- static constexpr Trait move_constructible_trait = common_trait(
- trait<Ts, lib::is_trivially_move_constructible, std::is_move_constructible>()...);
-
- static constexpr Trait copy_assignable_trait =
- common_trait(copy_constructible_trait,
- trait<Ts, lib::is_trivially_copy_assignable, std::is_copy_assignable>()...);
-
- static constexpr Trait move_assignable_trait =
- common_trait(move_constructible_trait,
- trait<Ts, lib::is_trivially_move_assignable, std::is_move_assignable>()...);
-
- static constexpr Trait destructible_trait =
- common_trait(trait<Ts, std::is_trivially_destructible, std::is_destructible>()...);
-};
-
-namespace access
-{
-struct recursive_union
-{
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
- template <typename V>
- inline static constexpr auto&& get_alt(V&& v, in_place_index_t<0>)
- {
- return lib::forward<V>(v).head_;
- }
-
- template <typename V, std::size_t I>
- inline static constexpr auto&& get_alt(V&& v, in_place_index_t<I>)
- {
- return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{});
- }
-#else
- template <std::size_t I, bool Dummy = true>
- struct get_alt_impl
- {
- template <typename V>
- inline constexpr AUTO_REFREF operator()(V&& v) const
- AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_))
- };
-
- template <bool Dummy>
- struct get_alt_impl<0, Dummy>
- {
- template <typename V>
- inline constexpr AUTO_REFREF operator()(V&& v) const
- AUTO_REFREF_RETURN(lib::forward<V>(v).head_)
- };
-
- template <typename V, std::size_t I>
- inline static constexpr AUTO_REFREF get_alt(V&& v, in_place_index_t<I>)
- AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v)))
-#endif
-};
-
-struct base
-{
- template <std::size_t I, typename V>
- inline static constexpr AUTO_REFREF get_alt(V&& v)
- AUTO_REFREF_RETURN(recursive_union::get_alt(data(lib::forward<V>(v)), in_place_index_t<I>{}))
-};
-
-struct variant
-{
- template <std::size_t I, typename V>
- inline static constexpr AUTO_REFREF get_alt(V&& v)
- AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))
-};
-
-} // namespace access
-
-namespace visitation
-{
-struct base
-{
- template <typename T>
- inline static constexpr const T& at(const T& elem)
- {
- return elem;
- }
-
- template <typename T, std::size_t N, typename... Is>
- inline static constexpr const lib::remove_all_extents_t<T>& at(const lib::array<T, N>& elems,
- std::size_t i, Is... is)
- {
- return at(elems[i], is...);
- }
-
- template <typename F, typename... Fs>
- inline static constexpr int visit_visitor_return_type_check()
- {
- static_assert(lib::all<std::is_same<F, Fs>::value...>::value,
- "`mpark::visit` requires the visitor to have a single "
- "return type.");
- return 0;
- }
-
- template <typename... Fs>
- inline static constexpr lib::array<lib::common_type_t<lib::decay_t<Fs>...>, sizeof...(Fs)>
- make_farray(Fs&&... fs)
- {
- using result = lib::array<lib::common_type_t<lib::decay_t<Fs>...>, sizeof...(Fs)>;
- return visit_visitor_return_type_check<lib::decay_t<Fs>...>(),
- result{{lib::forward<Fs>(fs)...}};
- }
-
- template <std::size_t... Is>
- struct dispatcher
- {
- template <typename F, typename... Vs>
- struct impl
- {
- inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
- DECLTYPE_AUTO_RETURN(lib::invoke(static_cast<F>(f),
- access::base::get_alt<Is>(static_cast<Vs>(vs))...))
- };
- };
-
- template <typename F, typename... Vs, std::size_t... Is>
- inline static constexpr AUTO make_dispatch(lib::index_sequence<Is...>)
- AUTO_RETURN(&dispatcher<Is...>::template impl<F, Vs...>::dispatch)
-
- template <std::size_t I, typename F, typename... Vs>
- inline static constexpr AUTO make_fdiagonal_impl() AUTO_RETURN(
- make_dispatch<F, Vs...>(lib::index_sequence<lib::indexed_type<I, Vs>::value...>{}))
-
- template <typename F, typename... Vs, std::size_t... Is>
- inline static constexpr AUTO make_fdiagonal_impl(lib::index_sequence<Is...>)
- AUTO_RETURN(make_farray(make_fdiagonal_impl<Is, F, Vs...>()...))
-
- template <typename F, typename V, typename... Vs>
- inline static constexpr /* auto * */ auto make_fdiagonal()
- -> decltype(make_fdiagonal_impl<F, V, Vs...>(
- lib::make_index_sequence<lib::decay_t<V>::size()>{}))
- {
- static_assert(lib::all<(lib::decay_t<V>::size() == lib::decay_t<Vs>::size())...>::value,
- "all of the variants must be the same size.");
- return make_fdiagonal_impl<F, V, Vs...>(lib::make_index_sequence<lib::decay_t<V>::size()>{});
- }
-
-#ifdef MPARK_RETURN_TYPE_DEDUCTION
- template <typename F, typename... Vs, typename Is>
- inline static constexpr auto make_fmatrix_impl(Is is)
- {
- return make_dispatch<F, Vs...>(is);
- }
-
- template <typename F, typename... Vs, typename Is, std::size_t... Js, typename... Ls>
- inline static constexpr auto make_fmatrix_impl(Is, lib::index_sequence<Js...>, Ls... ls)
- {
- return make_farray(make_fmatrix_impl<F, Vs...>(lib::push_back_t<Is, Js>{}, ls...)...);
- }
-
- template <typename F, typename... Vs>
- inline static constexpr auto make_fmatrix()
- {
- return make_fmatrix_impl<F, Vs...>(lib::index_sequence<>{},
- lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);
- }
-#else
- template <typename F, typename... Vs>
- struct make_fmatrix_impl
- {
- template <typename...>
- struct impl;
-
- template <typename Is>
- struct impl<Is>
- {
- inline constexpr AUTO operator()() const AUTO_RETURN(make_dispatch<F, Vs...>(Is{}))
- };
-
- template <typename Is, std::size_t... Js, typename... Ls>
- struct impl<Is, lib::index_sequence<Js...>, Ls...>
- {
- inline constexpr AUTO operator()() const
- AUTO_RETURN(make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...))
- };
- };
-
- template <typename F, typename... Vs>
- inline static constexpr AUTO make_fmatrix()
- AUTO_RETURN(typename make_fmatrix_impl<F, Vs...>::template impl<
- lib::index_sequence<>, lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
-#endif
-}; // namespace base
-
-template <typename F, typename... Vs>
-using FDiagonal = decltype(base::make_fdiagonal<F, Vs...>());
-
-template <typename F, typename... Vs>
-struct fdiagonal
-{
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4268)
-#endif
- static constexpr FDiagonal<F, Vs...> value = base::make_fdiagonal<F, Vs...>();
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-};
-
-template <typename F, typename... Vs>
-constexpr FDiagonal<F, Vs...> fdiagonal<F, Vs...>::value;
-
-template <typename F, typename... Vs>
-using FMatrix = decltype(base::make_fmatrix<F, Vs...>());
-
-template <typename F, typename... Vs>
-struct fmatrix
-{
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4268)
-#endif
- static constexpr FMatrix<F, Vs...> value = base::make_fmatrix<F, Vs...>();
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-};
-
-template <typename F, typename... Vs>
-constexpr FMatrix<F, Vs...> fmatrix<F, Vs...>::value;
-
-struct alt
-{
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor&& visitor,
- Vs&&... vs)
- DECLTYPE_AUTO_RETURN(
- base::at(fdiagonal<Visitor&&, decltype(as_base(lib::forward<Vs>(vs)))...>::value,
- index)(lib::forward<Visitor>(visitor), as_base(lib::forward<Vs>(vs))...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO
- visit_alt(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN(
- base::at(fmatrix<Visitor&&, decltype(as_base(lib::forward<Vs>(vs)))...>::value,
- vs.index()...)(lib::forward<Visitor>(visitor), as_base(lib::forward<Vs>(vs))...))
-};
-
-struct variant
-{
-private:
- template <typename Visitor, typename... Values>
- struct visit_exhaustive_visitor_check
- {
- static_assert(lib::is_invocable<Visitor, Values...>::value,
- "`mpark::visit` requires the visitor to be exhaustive.");
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
- inline constexpr DECLTYPE_AUTO operator()(Visitor&& visitor, Values&&... values) const
- DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
- lib::forward<Values>(values)...))
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- };
-
- template <typename Visitor>
- struct value_visitor
- {
- Visitor&& visitor_;
-
- template <typename... Alts>
- inline constexpr DECLTYPE_AUTO operator()(Alts&&... alts) const DECLTYPE_AUTO_RETURN(
- visit_exhaustive_visitor_check<Visitor, decltype((lib::forward<Alts>(alts).value))...>{}(
- lib::forward<Visitor>(visitor_), lib::forward<Alts>(alts).value...))
- };
-
- template <typename Visitor>
- inline static constexpr AUTO make_value_visitor(Visitor&& visitor)
- AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})
-
- public
- : template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO
- visit_alt_at(std::size_t index, Visitor&& visitor, Vs&&... vs)
- DECLTYPE_AUTO_RETURN(alt::visit_alt_at(index, lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs).impl_...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO visit_alt(Visitor&& visitor, Vs&&... vs)
- DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs).impl_...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO
- visit_value_at(std::size_t index, Visitor&& visitor, Vs&&... vs)
- DECLTYPE_AUTO_RETURN(visit_alt_at(index,
- make_value_visitor(lib::forward<Visitor>(visitor)),
- lib::forward<Vs>(vs)...))
-
- template <typename Visitor, typename... Vs>
- inline static constexpr DECLTYPE_AUTO
- visit_value(Visitor&& visitor, Vs&&... vs)
- DECLTYPE_AUTO_RETURN(visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),
- lib::forward<Vs>(vs)...))
-};
-
-} // namespace visitation
-
-template <std::size_t Index, typename T>
-struct alt
-{
- using value_type = T;
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
- template <typename... Args>
- inline explicit constexpr alt(in_place_t, Args&&... args) : value(lib::forward<Args>(args)...)
- {
- }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
- T value;
-};
-
-template <Trait DestructibleTrait, std::size_t Index, typename... Ts>
-union recursive_union;
-
-template <Trait DestructibleTrait, std::size_t Index>
-union recursive_union<DestructibleTrait, Index>
-{
-};
-
-#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \
- template <std::size_t Index, typename T, typename... Ts> \
- union recursive_union<destructible_trait, Index, T, Ts...> \
- { \
- public: \
- inline explicit constexpr recursive_union(valueless_t) noexcept : dummy_{} {} \
- \
- template <typename... Args> \
- inline explicit constexpr recursive_union(in_place_index_t<0>, Args&&... args) \
- : head_(in_place_t{}, lib::forward<Args>(args)...) \
- { \
- } \
- \
- template <std::size_t I, typename... Args> \
- inline explicit constexpr recursive_union(in_place_index_t<I>, Args&&... args) \
- : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) \
- { \
- } \
- \
- recursive_union(const recursive_union&) = default; \
- recursive_union(recursive_union&&) = default; \
- \
- destructor \
- \
- recursive_union& \
- operator=(const recursive_union&) = default; \
- recursive_union& operator=(recursive_union&&) = default; \
- \
- private: \
- char dummy_; \
- alt<Index, T> head_; \
- recursive_union<destructible_trait, Index + 1, Ts...> tail_; \
- \
- friend struct access::recursive_union; \
- }
-
-MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;);
-MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){});
-MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;);
-
-#undef MPARK_VARIANT_RECURSIVE_UNION
-
-using index_t = unsigned int;
-
-template <Trait DestructibleTrait, typename... Ts>
-class base
-{
-public:
- inline explicit constexpr base(valueless_t tag) noexcept
- : data_(tag), index_(static_cast<index_t>(-1))
- {
- }
-
- template <std::size_t I, typename... Args>
- inline explicit constexpr base(in_place_index_t<I>, Args&&... args)
- : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...), index_(I)
- {
- }
-
- inline constexpr bool valueless_by_exception() const noexcept
- {
- return index_ == static_cast<index_t>(-1);
- }
-
- inline constexpr std::size_t index() const noexcept
- {
- return valueless_by_exception() ? variant_npos : index_;
- }
-
-protected:
- using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
-
- friend inline constexpr base& as_base(base& b) { return b; }
- friend inline constexpr const base& as_base(const base& b) { return b; }
- friend inline constexpr base&& as_base(base&& b) { return lib::move(b); }
- friend inline constexpr const base&& as_base(const base&& b) { return lib::move(b); }
-
- friend inline constexpr data_t& data(base& b) { return b.data_; }
- friend inline constexpr const data_t& data(const base& b) { return b.data_; }
- friend inline constexpr data_t&& data(base&& b) { return lib::move(b).data_; }
- friend inline constexpr const data_t&& data(const base&& b) { return lib::move(b).data_; }
-
- inline static constexpr std::size_t size() { return sizeof...(Ts); }
-
- data_t data_;
- index_t index_;
-
- friend struct access::base;
- friend struct visitation::base;
-};
-
-struct dtor
-{
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
- template <typename Alt>
- inline void operator()(Alt& alt) const noexcept
- {
- alt.~Alt();
- }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-};
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
-#define INHERITING_CTOR(type, base) \
- template <typename... Args> \
- inline explicit constexpr type(Args&&... args) : base(lib::forward<Args>(args)...) \
- { \
- }
-#else
-#define INHERITING_CTOR(type, base) using base::base;
-#endif
-
-template <typename Traits, Trait = Traits::destructible_trait>
-class destructor;
-
-#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
- template <typename... Ts> \
- class destructor<traits<Ts...>, destructible_trait> : public base<destructible_trait, Ts...> \
- { \
- using super = base<destructible_trait, Ts...>; \
- \
- public: \
- INHERITING_CTOR(destructor, super) \
- using super::operator=; \
- \
- destructor(const destructor&) = default; \
- destructor(destructor&&) = default; \
- definition destructor& operator=(const destructor&) = default; \
- destructor& operator=(destructor&&) = default; \
- \
- protected: \
- destroy \
- }
-
-MPARK_VARIANT_DESTRUCTOR(Trait::TriviallyAvailable, ~destructor() = default;
- , inline void destroy() noexcept {
- this->index_ = static_cast<index_t>(-1);
- });
-
-MPARK_VARIANT_DESTRUCTOR(Trait::Available, ~destructor() { destroy(); },
- inline void destroy() noexcept {
- if (!this->valueless_by_exception())
- {
- visitation::alt::visit_alt(dtor{}, *this);
- }
- this->index_ = static_cast<index_t>(-1);
- });
-
-MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete;
- , inline void destroy() noexcept = delete;);
-
-#undef MPARK_VARIANT_DESTRUCTOR
-
-template <typename Traits>
-class constructor : public destructor<Traits>
-{
- using super = destructor<Traits>;
-
-public:
- INHERITING_CTOR(constructor, super)
- using super::operator=;
-
-protected:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct ctor
- {
- template <typename LhsAlt, typename RhsAlt>
- inline void operator()(LhsAlt& lhs_alt, RhsAlt&& rhs_alt) const
- {
- constructor::construct_alt(lhs_alt, lib::forward<RhsAlt>(rhs_alt).value);
- }
- };
-#endif
-
- template <std::size_t I, typename T, typename... Args>
- inline static T& construct_alt(alt<I, T>& a, Args&&... args)
- {
- ::new (static_cast<void*>(lib::addressof(a)))
- alt<I, T>(in_place_t{}, lib::forward<Args>(args)...);
- return a.value;
- }
-
- template <typename Rhs>
- inline static void generic_construct(constructor& lhs, Rhs&& rhs)
- {
- lhs.destroy();
- if (!rhs.valueless_by_exception())
- {
- visitation::alt::visit_alt_at(rhs.index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [](auto& lhs_alt, auto&& rhs_alt) {
- constructor::construct_alt(
- lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);
- }
-#else
- ctor {}
-#endif
- ,
- lhs, lib::forward<Rhs>(rhs));
- lhs.index_ = rhs.index_;
- }
- }
-};
-
-template <typename Traits, Trait = Traits::move_constructible_trait>
-class move_constructor;
-
-#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
- template <typename... Ts> \
- class move_constructor<traits<Ts...>, move_constructible_trait> \
- : public constructor<traits<Ts...>> \
- { \
- using super = constructor<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(move_constructor, super) \
- using super::operator=; \
- \
- move_constructor(const move_constructor&) = default; \
- definition ~move_constructor() = default; \
- move_constructor& operator=(const move_constructor&) = default; \
- move_constructor& operator=(move_constructor&&) = default; \
- }
-
-MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable,
- move_constructor(move_constructor&& that) = default;);
-
-MPARK_VARIANT_MOVE_CONSTRUCTOR(
- Trait::Available, move_constructor(move_constructor&& that) noexcept(
- lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
- : move_constructor(valueless_t{}) { this->generic_construct(*this, lib::move(that)); });
-
-MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor&&) = delete;);
-
-#undef MPARK_VARIANT_MOVE_CONSTRUCTOR
-
-template <typename Traits, Trait = Traits::copy_constructible_trait>
-class copy_constructor;
-
-#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
- template <typename... Ts> \
- class copy_constructor<traits<Ts...>, copy_constructible_trait> \
- : public move_constructor<traits<Ts...>> \
- { \
- using super = move_constructor<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(copy_constructor, super) \
- using super::operator=; \
- \
- definition copy_constructor(copy_constructor&&) = default; \
- ~copy_constructor() = default; \
- copy_constructor& operator=(const copy_constructor&) = default; \
- copy_constructor& operator=(copy_constructor&&) = default; \
- }
-
-MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable,
- copy_constructor(const copy_constructor& that) = default;);
-
-MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Available, copy_constructor(const copy_constructor& that)
- : copy_constructor(valueless_t{}) {
- this->generic_construct(*this, that);
- });
-
-MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable,
- copy_constructor(const copy_constructor&) = delete;);
-
-#undef MPARK_VARIANT_COPY_CONSTRUCTOR
-
-template <typename Traits>
-class assignment : public copy_constructor<Traits>
-{
- using super = copy_constructor<Traits>;
-
-public:
- INHERITING_CTOR(assignment, super)
- using super::operator=;
-
- template <std::size_t I, typename... Args>
- inline /* auto & */ auto emplace(Args&&... args)
- -> decltype(this->construct_alt(access::base::get_alt<I>(*this), lib::forward<Args>(args)...))
- {
- this->destroy();
- auto& result =
- this->construct_alt(access::base::get_alt<I>(*this), lib::forward<Args>(args)...);
- this->index_ = I;
- return result;
- }
-
-protected:
-#ifndef MPARK_GENERIC_LAMBDAS
- template <typename That>
- struct assigner
- {
- template <typename ThisAlt, typename ThatAlt>
- inline void operator()(ThisAlt& this_alt, ThatAlt&& that_alt) const
- {
- self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);
- }
- assignment* self;
- };
-#endif
-
- template <std::size_t I, typename T, typename Arg>
- inline void assign_alt(alt<I, T>& a, Arg&& arg)
- {
- if (this->index() == I)
- {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
- a.value = lib::forward<Arg>(arg);
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- }
- else
- {
- struct
- {
- void operator()(std::true_type) const { this_->emplace<I>(lib::forward<Arg>(arg_)); }
- void operator()(std::false_type) const { this_->emplace<I>(T(lib::forward<Arg>(arg_))); }
- assignment* this_;
- Arg&& arg_;
- } impl{this, lib::forward<Arg>(arg)};
- impl(lib::bool_constant < std::is_nothrow_constructible<T, Arg>::value ||
- !std::is_nothrow_move_constructible<T>::value > {});
- }
- }
-
- template <typename That>
- inline void generic_assign(That&& that)
- {
- if (this->valueless_by_exception() && that.valueless_by_exception())
- {
- // do nothing.
- }
- else if (that.valueless_by_exception())
- {
- this->destroy();
- }
- else
- {
- visitation::alt::visit_alt_at(
- that.index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [this](auto& this_alt, auto&& that_alt) {
- this->assign_alt(this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
- }
-#else
- assigner<That> { this }
-#endif
- ,
- *this, lib::forward<That>(that));
- }
- }
-};
-
-template <typename Traits, Trait = Traits::move_assignable_trait>
-class move_assignment;
-
-#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
- template <typename... Ts> \
- class move_assignment<traits<Ts...>, move_assignable_trait> : public assignment<traits<Ts...>> \
- { \
- using super = assignment<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(move_assignment, super) \
- using super::operator=; \
- \
- move_assignment(const move_assignment&) = default; \
- move_assignment(move_assignment&&) = default; \
- ~move_assignment() = default; \
- move_assignment& operator=(const move_assignment&) = default; \
- definition \
- }
-
-MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable,
- move_assignment& operator=(move_assignment&& that) = default;);
-
-MPARK_VARIANT_MOVE_ASSIGNMENT(
- Trait::Available, move_assignment& operator=(move_assignment&& that) noexcept(
- lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
- std::is_nothrow_move_assignable<Ts>::value)...>::value) {
- this->generic_assign(lib::move(that));
- return *this;
- });
-
-MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable,
- move_assignment& operator=(move_assignment&&) = delete;);
-
-#undef MPARK_VARIANT_MOVE_ASSIGNMENT
-
-template <typename Traits, Trait = Traits::copy_assignable_trait>
-class copy_assignment;
-
-#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
- template <typename... Ts> \
- class copy_assignment<traits<Ts...>, copy_assignable_trait> \
- : public move_assignment<traits<Ts...>> \
- { \
- using super = move_assignment<traits<Ts...>>; \
- \
- public: \
- INHERITING_CTOR(copy_assignment, super) \
- using super::operator=; \
- \
- copy_assignment(const copy_assignment&) = default; \
- copy_assignment(copy_assignment&&) = default; \
- ~copy_assignment() = default; \
- definition copy_assignment& operator=(copy_assignment&&) = default; \
- }
-
-MPARK_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable,
- copy_assignment& operator=(const copy_assignment& that) = default;);
-
-MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Available,
- copy_assignment& operator=(const copy_assignment& that) {
- this->generic_assign(that);
- return *this;
- });
-
-MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable,
- copy_assignment& operator=(const copy_assignment&) = delete;);
-
-#undef MPARK_VARIANT_COPY_ASSIGNMENT
-
-template <typename... Ts>
-class impl : public copy_assignment<traits<Ts...>>
-{
- using super = copy_assignment<traits<Ts...>>;
-
-public:
- INHERITING_CTOR(impl, super)
- using super::operator=;
-
- template <std::size_t I, typename Arg>
- inline void assign(Arg&& arg)
- {
- this->assign_alt(access::base::get_alt<I>(*this), lib::forward<Arg>(arg));
- }
-
- inline void swap(impl& that)
- {
- if (this->valueless_by_exception() && that.valueless_by_exception())
- {
- // do nothing.
- }
- else if (this->index() == that.index())
- {
- visitation::alt::visit_alt_at(this->index(),
-#ifdef MPARK_GENERIC_LAMBDAS
- [](auto& this_alt, auto& that_alt) {
- using std::swap;
- swap(this_alt.value, that_alt.value);
- }
-#else
- swapper {}
-#endif
- ,
- *this, that);
- }
- else
- {
- impl* lhs = this;
- impl* rhs = lib::addressof(that);
- if (lhs->move_nothrow() && !rhs->move_nothrow())
- {
- std::swap(lhs, rhs);
- }
- impl tmp(lib::move(*rhs));
-#ifdef MPARK_EXCEPTIONS
- // EXTENSION: When the move construction of `lhs` into `rhs` throws
- // and `tmp` is nothrow move constructible then we move `tmp` back
- // into `rhs` and provide the strong exception safety guarantee.
- try
- {
- this->generic_construct(*rhs, lib::move(*lhs));
- }
- catch (...)
- {
- if (tmp.move_nothrow())
- {
- this->generic_construct(*rhs, lib::move(tmp));
- }
- throw;
- }
-#else
- this->generic_construct(*rhs, lib::move(*lhs));
-#endif
- this->generic_construct(*lhs, lib::move(tmp));
- }
- }
-
-private:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct swapper
- {
- template <typename ThisAlt, typename ThatAlt>
- inline void operator()(ThisAlt& this_alt, ThatAlt& that_alt) const
- {
- using std::swap;
- swap(this_alt.value, that_alt.value);
- }
- };
-#endif
-
- inline constexpr bool move_nothrow() const
- {
- return this->valueless_by_exception() ||
- lib::array<bool, sizeof...(Ts)>{
- {std::is_nothrow_move_constructible<Ts>::value...}}[this->index()];
- }
-};
-
-template <std::size_t I, typename T>
-struct overload_leaf
-{
- using F = lib::size_constant<I> (*)(T);
- operator F() const { return nullptr; }
-};
-
-template <typename... Ts>
-struct overload_impl
-{
-private:
- template <typename>
- struct impl;
-
- template <std::size_t... Is>
- struct impl<lib::index_sequence<Is...>> : overload_leaf<Is, Ts>...
- {
- };
-
-public:
- using type = impl<lib::index_sequence_for<Ts...>>;
-};
-
-template <typename... Ts>
-using overload = typename overload_impl<Ts...>::type;
-
-template <typename T, typename... Ts>
-using best_match = lib::invoke_result_t<overload<Ts...>, T&&>;
-
-template <typename T>
-struct is_in_place_index : std::false_type
-{
-};
-
-template <std::size_t I>
-struct is_in_place_index<in_place_index_t<I>> : std::true_type
-{
-};
-
-template <typename T>
-struct is_in_place_type : std::false_type
-{
-};
-
-template <typename T>
-struct is_in_place_type<in_place_type_t<T>> : std::true_type
-{
-};
-
-} // namespace detail
-
-template <typename... Ts>
-class variant
-{
- static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative.");
-
- static_assert(lib::all<!std::is_array<Ts>::value...>::value,
- "variant can not have an array type as an alternative.");
-
- static_assert(lib::all<!std::is_reference<Ts>::value...>::value,
- "variant can not have a reference type as an alternative.");
-
- static_assert(lib::all<!std::is_void<Ts>::value...>::value,
- "variant can not have a void type as an alternative.");
-
-public:
- template <typename Front = lib::type_pack_element_t<0, Ts...>,
- lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>
- inline constexpr variant() noexcept(std::is_nothrow_default_constructible<Front>::value)
- : impl_(in_place_index_t<0>{})
- {
- }
-
- variant(const variant&) = default;
- variant(variant&&) = default;
-
- template <typename Arg, typename Decayed = lib::decay_t<Arg>,
- lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,
- lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0,
- lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0,
- std::size_t I = detail::best_match<Arg, Ts...>::value,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>
- inline constexpr variant(Arg&& arg) noexcept(std::is_nothrow_constructible<T, Arg>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg))
- {
- }
-
- template <std::size_t I, typename... Args, typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline explicit constexpr variant(in_place_index_t<I>, Args&&... args) noexcept(
- std::is_nothrow_constructible<T, Args...>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...)
- {
- }
-
- template <
- std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, std::initializer_list<Up>&, Args...>::value, int> =
- 0>
- inline explicit constexpr variant(
- in_place_index_t<I>, std::initializer_list<Up> il,
- Args&&... args) noexcept(std::is_nothrow_constructible<T, std::initializer_list<Up>&,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...)
- {
- }
-
- template <typename T, typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline explicit constexpr variant(in_place_type_t<T>, Args&&... args) noexcept(
- std::is_nothrow_constructible<T, Args...>::value)
- : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...)
- {
- }
-
- template <typename T, typename Up, typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, std::initializer_list<Up>&, Args...>::value,
- int> = 0>
- inline explicit constexpr variant(
- in_place_type_t<T>, std::initializer_list<Up> il,
- Args&&... args) noexcept(std::is_nothrow_constructible<T, std::initializer_list<Up>&,
- Args...>::value)
- : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...)
- {
- }
-
- ~variant() = default;
-
- variant& operator=(const variant&) = default;
- variant& operator=(variant&&) = default;
-
- template <
- typename Arg, lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value, int> = 0,
- std::size_t I = detail::best_match<Arg, Ts...>::value,
- typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<(std::is_assignable<T&, Arg>::value && std::is_constructible<T, Arg>::value),
- int> = 0>
- inline variant& operator=(Arg&& arg) noexcept((std::is_nothrow_assignable<T&, Arg>::value &&
- std::is_nothrow_constructible<T, Arg>::value))
- {
- impl_.template assign<I>(lib::forward<Arg>(arg));
- return *this;
- }
-
- template <std::size_t I, typename... Args, typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline T& emplace(Args&&... args)
- {
- return impl_.template emplace<I>(lib::forward<Args>(args)...);
- }
-
- template <
- std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t<I, Ts...>,
- lib::enable_if_t<std::is_constructible<T, std::initializer_list<Up>&, Args...>::value, int> =
- 0>
- inline T& emplace(std::initializer_list<Up> il, Args&&... args)
- {
- return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
- }
-
- template <typename T, typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
- inline T& emplace(Args&&... args)
- {
- return impl_.template emplace<I>(lib::forward<Args>(args)...);
- }
-
- template <typename T, typename Up, typename... Args,
- std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
- lib::enable_if_t<std::is_constructible<T, std::initializer_list<Up>&, Args...>::value,
- int> = 0>
- inline T& emplace(std::initializer_list<Up> il, Args&&... args)
- {
- return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
- }
-
- inline constexpr bool valueless_by_exception() const noexcept
- {
- return impl_.valueless_by_exception();
- }
-
- inline constexpr std::size_t index() const noexcept { return impl_.index(); }
-
- template <
- bool Dummy = true,
- lib::enable_if_t<
- lib::all<Dummy, (lib::dependent_type<std::is_move_constructible<Ts>, Dummy>::value &&
- lib::dependent_type<lib::is_swappable<Ts>, Dummy>::value)...>::value,
- int> = 0>
- inline void
- swap(variant& that) noexcept(lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
- lib::is_nothrow_swappable<Ts>::value)...>::value)
- {
- impl_.swap(that.impl_);
- }
-
-private:
- detail::impl<Ts...> impl_;
-
- friend struct detail::access::variant;
- friend struct detail::visitation::variant;
-};
-
-template <std::size_t I, typename... Ts>
-inline constexpr bool holds_alternative(const variant<Ts...>& v) noexcept
-{
- return v.index() == I;
-}
-
-template <typename T, typename... Ts>
-inline constexpr bool holds_alternative(const variant<Ts...>& v) noexcept
-{
- return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);
-}
-
-namespace detail
-{
-template <std::size_t I, typename V>
-struct generic_get_impl
-{
- constexpr generic_get_impl(int) {}
-
- constexpr AUTO_REFREF operator()(V&& v) const
- AUTO_REFREF_RETURN(access::variant::get_alt<I>(lib::forward<V>(v)).value)
-};
-
-template <std::size_t I, typename V>
-inline constexpr AUTO_REFREF generic_get(V&& v) AUTO_REFREF_RETURN(generic_get_impl<I, V>(
- holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(lib::forward<V>(v)))
-} // namespace detail
-
-template <std::size_t I, typename... Ts>
-inline constexpr variant_alternative_t<I, variant<Ts...>>& get(variant<Ts...>& v)
-{
- return detail::generic_get<I>(v);
-}
-
-template <std::size_t I, typename... Ts>
-inline constexpr variant_alternative_t<I, variant<Ts...>>&& get(variant<Ts...>&& v)
-{
- return detail::generic_get<I>(lib::move(v));
-}
-
-template <std::size_t I, typename... Ts>
-inline constexpr const variant_alternative_t<I, variant<Ts...>>& get(const variant<Ts...>& v)
-{
- return detail::generic_get<I>(v);
-}
-
-template <std::size_t I, typename... Ts>
-inline constexpr const variant_alternative_t<I, variant<Ts...>>&& get(const variant<Ts...>&& v)
-{
- return detail::generic_get<I>(lib::move(v));
-}
-
-template <typename T, typename... Ts>
-inline constexpr T& get(variant<Ts...>& v)
-{
- return get<detail::find_index_checked<T, Ts...>::value>(v);
-}
-
-template <typename T, typename... Ts>
-inline constexpr T&& get(variant<Ts...>&& v)
-{
- return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
-}
-
-template <typename T, typename... Ts>
-inline constexpr const T& get(const variant<Ts...>& v)
-{
- return get<detail::find_index_checked<T, Ts...>::value>(v);
-}
-
-template <typename T, typename... Ts>
-inline constexpr const T&& get(const variant<Ts...>&& v)
-{
- return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
-}
-
-namespace detail
-{
-template <std::size_t I, typename V>
-inline constexpr /* auto * */ AUTO generic_get_if(V* v) noexcept AUTO_RETURN(
- v&& holds_alternative<I>(*v) ? lib::addressof(access::variant::get_alt<I>(*v).value) : nullptr)
-
-} // namespace detail
-
-template <std::size_t I, typename... Ts>
-inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
-get_if(variant<Ts...>* v) noexcept
-{
- return detail::generic_get_if<I>(v);
-}
-
-template <std::size_t I, typename... Ts>
-inline constexpr lib::add_pointer_t<const variant_alternative_t<I, variant<Ts...>>>
-get_if(const variant<Ts...>* v) noexcept
-{
- return detail::generic_get_if<I>(v);
-}
-
-template <typename T, typename... Ts>
-inline constexpr lib::add_pointer_t<T> get_if(variant<Ts...>* v) noexcept
-{
- return get_if<detail::find_index_checked<T, Ts...>::value>(v);
-}
-
-template <typename T, typename... Ts>
-inline constexpr lib::add_pointer_t<const T> get_if(const variant<Ts...>* v) noexcept
-{
- return get_if<detail::find_index_checked<T, Ts...>::value>(v);
-}
-
-template <typename... Ts>
-inline constexpr bool operator==(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::equal_to;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.index() != rhs.index())
- return false;
- if (lhs.valueless_by_exception())
- return true;
- return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
-#else
- return lhs.index() == rhs.index() && (lhs.valueless_by_exception() ||
- variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
-#endif
-}
-
-template <typename... Ts>
-inline constexpr bool operator!=(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::not_equal_to;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.index() != rhs.index())
- return true;
- if (lhs.valueless_by_exception())
- return false;
- return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
-#else
- return lhs.index() != rhs.index() ||
- (!lhs.valueless_by_exception() &&
- variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
-#endif
-}
-
-template <typename... Ts>
-inline constexpr bool operator<(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::less;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (rhs.valueless_by_exception())
- return false;
- if (lhs.valueless_by_exception())
- return true;
- if (lhs.index() < rhs.index())
- return true;
- if (lhs.index() > rhs.index())
- return false;
- return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
-#else
- return !rhs.valueless_by_exception() &&
- (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||
- (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));
-#endif
-}
-
-template <typename... Ts>
-inline constexpr bool operator>(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::greater;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.valueless_by_exception())
- return false;
- if (rhs.valueless_by_exception())
- return true;
- if (lhs.index() > rhs.index())
- return true;
- if (lhs.index() < rhs.index())
- return false;
- return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
-#else
- return !lhs.valueless_by_exception() &&
- (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));
-#endif
-}
-
-template <typename... Ts>
-inline constexpr bool operator<=(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::less_equal;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (lhs.valueless_by_exception())
- return true;
- if (rhs.valueless_by_exception())
- return false;
- if (lhs.index() < rhs.index())
- return true;
- if (lhs.index() > rhs.index())
- return false;
- return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
-#else
- return lhs.valueless_by_exception() ||
- (!rhs.valueless_by_exception() &&
- (lhs.index() < rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));
-#endif
-}
-
-template <typename... Ts>
-inline constexpr bool operator>=(const variant<Ts...>& lhs, const variant<Ts...>& rhs)
-{
- using detail::visitation::variant;
- using lib::greater_equal;
-#ifdef MPARK_CPP14_CONSTEXPR
- if (rhs.valueless_by_exception())
- return true;
- if (lhs.valueless_by_exception())
- return false;
- if (lhs.index() > rhs.index())
- return true;
- if (lhs.index() < rhs.index())
- return false;
- return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
-#else
- return rhs.valueless_by_exception() ||
- (!lhs.valueless_by_exception() &&
- (lhs.index() > rhs.index() ||
- (lhs.index() == rhs.index() &&
- variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs))));
-#endif
-}
-
-struct monostate
-{
-};
-
-inline constexpr bool operator<(monostate, monostate) noexcept
-{
- return false;
-}
-
-inline constexpr bool operator>(monostate, monostate) noexcept
-{
- return false;
-}
-
-inline constexpr bool operator<=(monostate, monostate) noexcept
-{
- return true;
-}
-
-inline constexpr bool operator>=(monostate, monostate) noexcept
-{
- return true;
-}
-
-inline constexpr bool operator==(monostate, monostate) noexcept
-{
- return true;
-}
-
-inline constexpr bool operator!=(monostate, monostate) noexcept
-{
- return false;
-}
-
-#ifdef MPARK_CPP14_CONSTEXPR
-namespace detail
-{
-inline constexpr bool all(std::initializer_list<bool> bs)
-{
- for (bool b : bs)
- {
- if (!b)
- {
- return false;
- }
- }
- return true;
-}
-
-} // namespace detail
-
-template <typename Visitor, typename... Vs>
-inline constexpr decltype(auto) visit(Visitor&& visitor, Vs&&... vs)
-{
- return (detail::all({!vs.valueless_by_exception()...}) ? (void)0 : throw_bad_variant_access()),
- detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs)...);
-}
-#else
-namespace detail
-{
-template <std::size_t N>
-inline constexpr bool all_impl(const lib::array<bool, N>& bs, std::size_t idx)
-{
- return idx >= N || (bs[idx] && all_impl(bs, idx + 1));
-}
-
-template <std::size_t N>
-inline constexpr bool all(const lib::array<bool, N>& bs)
-{
- return all_impl(bs, 0);
-}
-
-} // namespace detail
-
-template <typename Visitor, typename... Vs>
-inline constexpr DECLTYPE_AUTO visit(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN(
- (detail::all(lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}}) ?
- (void)0 :
- throw_bad_variant_access()),
- detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
- lib::forward<Vs>(vs)...))
-#endif
-
-template <typename... Ts>
-inline auto swap(variant<Ts...>& lhs, variant<Ts...>& rhs) noexcept(noexcept(lhs.swap(rhs)))
- -> decltype(lhs.swap(rhs))
-{
- lhs.swap(rhs);
-}
-
-namespace detail
-{
-template <typename T, typename...>
-using enabled_type = T;
-
-namespace hash
-{
-template <typename H, typename K>
-constexpr bool meets_requirements()
-{
- return std::is_copy_constructible<H>::value && std::is_move_constructible<H>::value &&
- lib::is_invocable_r<std::size_t, H, const K&>::value;
-}
-
-template <typename K>
-constexpr bool is_enabled()
-{
- using H = std::hash<K>;
- return meets_requirements<H, K>() && std::is_default_constructible<H>::value &&
- std::is_copy_assignable<H>::value && std::is_move_assignable<H>::value;
-}
-
-} // namespace hash
-
-} // namespace detail
-
-#undef AUTO
-#undef AUTO_RETURN
-
-#undef AUTO_REFREF
-#undef AUTO_REFREF_RETURN
-
-#undef DECLTYPE_AUTO
-#undef DECLTYPE_AUTO_RETURN
-
-} // namespace mpark
-
-namespace std
-{
-template <typename... Ts>
-struct hash<mpark::detail::enabled_type<
- mpark::variant<Ts...>, mpark::lib::enable_if_t<mpark::lib::all<mpark::detail::hash::is_enabled<
- mpark::lib::remove_const_t<Ts>>()...>::value>>>
-{
- using argument_type = mpark::variant<Ts...>;
- using result_type = std::size_t;
-
- inline result_type operator()(const argument_type& v) const
- {
- using mpark::detail::visitation::variant;
- std::size_t result = v.valueless_by_exception() ?
- 299792458 // Random value chosen by the universe upon creation
- :
- variant::visit_alt(
-#ifdef MPARK_GENERIC_LAMBDAS
- [](const auto& alt) {
- using alt_type = mpark::lib::decay_t<decltype(alt)>;
- using value_type =
- mpark::lib::remove_const_t<typename alt_type::value_type>;
- return hash<value_type>{}(alt.value);
- }
-#else
- hasher {}
-#endif
- ,
- v);
- return hash_combine(result, hash<std::size_t>{}(v.index()));
- }
-
-private:
-#ifndef MPARK_GENERIC_LAMBDAS
- struct hasher
- {
- template <typename Alt>
- inline std::size_t operator()(const Alt& alt) const
- {
- using alt_type = mpark::lib::decay_t<Alt>;
- using value_type = mpark::lib::remove_const_t<typename alt_type::value_type>;
- return hash<value_type>{}(alt.value);
- }
- };
-#endif
-
- static std::size_t hash_combine(std::size_t lhs, std::size_t rhs)
- {
- return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
- }
-};
-
-template <>
-struct hash<mpark::monostate>
-{
- using argument_type = mpark::monostate;
- using result_type = std::size_t;
-
- inline result_type operator()(const argument_type&) const noexcept
- {
- return 66740831; // return a fundamentally attractive random value.
- }
-};
-
-} // namespace std
-
-namespace std
-{
-using mpark::bad_variant_access;
-using mpark::get;
-using mpark::get_if;
-using mpark::holds_alternative;
-using mpark::monostate;
-using mpark::variant;
-using mpark::variant_alternative;
-using mpark::variant_alternative_t;
-using mpark::variant_size;
-using mpark::visit;
-} // namespace std
-#endif