diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 69a8cd9eab..2899476e34 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -16,18 +16,13 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC") check_and_add_flag(CPPLATEST /std:c++latest) check_and_add_flag(STANDARD_COMPLIANCE /permissive-) else() - # Enable C++17, but fall back to C++14 if it isn't available. - # CMAKE_CXX_STANDARD cannot be used here because we require C++14 or newer, not any standard. + # Enable C++17 + # CMAKE_CXX_STANDARD cannot be used because it requires cmake 3.8+. check_and_add_flag(CXX17 -std=c++17) if(NOT FLAG_CXX_CXX17) - set(CMAKE_CXX_STANDARD 14) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) + # Fall back to -std=c++1z + check_and_add_flag(CXX1Z -std=c++1z) endif() - - # These compat headers must not be in the include path when building with MSVC, - # because it currently does not support __has_include_next / #include_next. - include_directories(SYSTEM Core/Common/Compat) endif() # These aren't actually needed for C11/C++11 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 - -namespace mpark -{ -struct in_place_t -{ - explicit in_place_t() = default; -}; - -template -struct in_place_index_t -{ - explicit in_place_index_t() = default; -}; - -template -struct in_place_type_t -{ - explicit in_place_type_t() = default; -}; - -#ifdef MPARK_VARIABLE_TEMPLATES -constexpr in_place_t in_place{}; - -template -constexpr in_place_index_t in_place_index{}; - -template -constexpr in_place_type_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() -#include_next -#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 -#include -#include -#include -#include - -#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 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) is approximately sizeof(T)+1. The interface -// is based on the upcoming std::optional, and gtl::optional is -// designed to be cheaply drop-in replaceable by std::optional, 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 and std::optional 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 f() { -// string result; -// if (...) { -// ... -// result = ...; -// return result; -// } else { -// ... -// return tensorflow::gtl::nullopt; -// } -// } -// -// int main() { -// tensorflow::gtl::optional optstr = f(); -// if (optstr) { -// // non-empty -// print(optstr.value()); -// } else { -// // empty -// error(); -// } -// } -template -class optional; - -// The tag constant `in_place` is used as the first parameter of an optional -// 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 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 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 -constexpr T&& forward(typename std::remove_reference::type& - t) noexcept { // NOLINT(runtime/references) - return static_cast(t); -} - -struct empty_struct {}; -// This class stores the data in optional. -// It is specialized based on whether T is trivially destructible. -// This is the specialization for non trivially destructible type. -template ::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 - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(internal_optional::forward(args)...) {} - - ~optional_data_dtor_base() { destruct(); } -}; - -// Specialization for trivially destructible type. -template -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 { engaged_ = false; } - - // dummy_ must be initialized for constexpr constructor - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {} - - template - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(internal_optional::forward(args)...) {} - - ~optional_data_dtor_base() = default; -}; - -template -class optional_data : public optional_data_dtor_base { - protected: - using base = optional_data_dtor_base; - using base::base; - - T* pointer() { return &this->data_; } - - constexpr const T* pointer() const { return &this->data_; } - - template - void construct(Args&&... args) { - new (pointer()) T(std::forward(args)...); - this->engaged_ = true; - } - - template - void assign(U&& u) { - if (this->engaged_) { - this->data_ = std::forward(u); - } else { - construct(std::forward(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::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::value&& - std::is_nothrow_move_constructible::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 -class optional_ctor_base; - -template <> -class optional_ctor_base { - 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 { - 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 { - 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 -class optional_assign_base; - -template <> -class optional_assign_base { - 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 { - 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 { - 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 -constexpr copy_traits get_ctor_copy_traits() { - return std::is_copy_constructible::value - ? copy_traits::copyable - : std::is_move_constructible::value ? copy_traits::movable - : copy_traits::non_movable; -} - -template -constexpr copy_traits get_assign_copy_traits() { - return std::is_copy_assignable::value && - std::is_copy_constructible::value - ? copy_traits::copyable - : std::is_move_assignable::value && - std::is_move_constructible::value - ? copy_traits::movable - : copy_traits::non_movable; -} - -// Whether T is constructible or convertible from optional. -template -struct is_constructible_convertible_from_optional - : std::integral_constant< - bool, std::is_constructible&>::value || - std::is_constructible&&>::value || - std::is_constructible&>::value || - std::is_constructible&&>::value || - std::is_convertible&, T>::value || - std::is_convertible&&, T>::value || - std::is_convertible&, T>::value || - std::is_convertible&&, T>::value> {}; - -// Whether T is constructible or convertible or assignable from optional. -template -struct is_constructible_convertible_assignable_from_optional - : std::integral_constant< - bool, is_constructible_convertible_from_optional::value || - std::is_assignable&>::value || - std::is_assignable&&>::value || - std::is_assignable&>::value || - std::is_assignable&&>::value> {}; - -} // namespace internal_optional - -template -class optional : private internal_optional::optional_data, - private internal_optional::optional_ctor_base< - internal_optional::get_ctor_copy_traits()>, - private internal_optional::optional_assign_base< - internal_optional::get_assign_copy_traits()> { - using data_base = internal_optional::optional_data; - - 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(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 SFINAE. - template - constexpr explicit optional(in_place_t, Args&&... args) - : data_base(in_place_t(), internal_optional::forward(args)...) {} - - // optional(in_place, {arg1, arg2, arg3}) constructs a non-empty optional - // with an in-place list-initialized value of T({arg1, arg2, arg3}). - template &, Args&&...>::value>::type> - constexpr explicit optional(in_place_t, std::initializer_list il, - Args&&... args) - : data_base(in_place_t(), il, internal_optional::forward(args)...) { - } - - template < - typename U = T, - typename std::enable_if< - std::is_constructible::value && - !std::is_same::type>::value && - !std::is_same, typename std::decay::type>::value && - std::is_convertible::value, - bool>::type = false> - constexpr optional(U&& v) // NOLINT - : data_base(in_place_t(), internal_optional::forward(v)) {} - - template < - typename U = T, - typename std::enable_if< - std::is_constructible::value && - !std::is_same::type>::value && - !std::is_same, typename std::decay::type>::value && - !std::is_convertible::value, - bool>::type = false> - explicit constexpr optional(U&& v) - : data_base(in_place_t(), internal_optional::forward(v)) {} - - // Converting copy constructor (implicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - std::is_convertible::value, - bool>::type = false> - optional(const optional& rhs) { // NOLINT - if (rhs) { - this->construct(*rhs); - } - } - - // Converting copy constructor (explicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - !std::is_convertible::value, - bool>::type = false> - explicit optional(const optional& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting move constructor (implicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - std::is_convertible::value, - bool>::type = false> - optional(optional&& rhs) { // NOLINT - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Converting move constructor (explicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - !std::is_convertible::value, - bool>::type = false> - explicit optional(optional&& 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, typename std::decay::type>::value && - (!std::is_scalar::value || - !std::is_same::type>::value) && - std::is_constructible::value && - std::is_assignable::value>::type> - optional& operator=(U&& v) { - this->assign(std::forward(v)); - return *this; - } - - template ::value && - std::is_assignable::value && - !internal_optional:: - is_constructible_convertible_assignable_from_optional< - T, U>::value>::type> - optional& operator=(const optional& rhs) { - if (rhs) { - this->assign(*rhs); - } else { - this->destruct(); - } - return *this; - } - - template ::value && - std::is_assignable::value && - !internal_optional:: - is_constructible_convertible_assignable_from_optional< - T, U>::value>::type> - optional& operator=(optional&& 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 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 ::value>::type> - void emplace(Args&&... args) { - this->destruct(); - this->construct(std::forward(args)...); - } - - // Emplace reconstruction with initializer-list. See immediately above. - template &, Args&&...>::value>::type> - void emplace(std::initializer_list il, Args&&... args) { - this->destruct(); - this->construct(il, std::forward(args)...); - } - - // [optional.swap], swap - // Swap, standard semantics. - void swap(optional& rhs) noexcept( - std::is_nothrow_move_constructible::value&& - std::is_trivial::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 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 - constexpr T value_or(U&& v) const & { - return static_cast(*this) ? **this - : static_cast(std::forward(v)); - } - template - T value_or(U&& v) && { // NOLINT(build/c++11) - return static_cast(*this) ? std::move(**this) - : static_cast(std::forward(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::type>::value, - "optional is not allowed."); - static_assert( - !std::is_same::type>::value, - "optional is not allowed."); - static_assert(!std::is_reference::value, - "optional is not allowed."); -}; - -// [optional.specalg] -// Swap, standard semantics. -// This function shall not participate in overload resolution unless -// is_move_constructible_v is true and is_swappable_v is true. -// NOTE: we assume is_swappable is always true. There will be a compiling error -// if T is actually not Swappable. -template ::value, - bool>::type = false> -void swap(optional& a, optional& 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 where the type T is deduced -// from v. Can also be explicitly instantiated as make_optional(v). -template -constexpr optional::type> make_optional(T&& v) { - return optional::type>(std::forward(v)); -} - -template -constexpr optional make_optional(Args&&... args) { - return optional(in_place_t(), internal_optional::forward(args)...); -} - -template -constexpr optional make_optional(std::initializer_list il, - Args&&... args) { - return optional(in_place_t(), il, - internal_optional::forward(args)...); -} - -// Relational operators. Empty optionals are considered equal to each -// other and less than non-empty optionals. Supports relations between -// optional and optional, between optional and T, and between -// optional 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 -constexpr bool operator==(const optional& x, const optional& y) { - return static_cast(x) != static_cast(y) - ? false - : static_cast(x) == false ? true : *x == *y; -} -// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; -// otherwise *x != *y. -template -constexpr bool operator!=(const optional& x, const optional& y) { - return static_cast(x) != static_cast(y) - ? true - : static_cast(x) == false ? false : *x != *y; -} -// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y. -template -constexpr bool operator<(const optional& x, const optional& y) { - return !y ? false : !x ? true : *x < *y; -} -// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y. -template -constexpr bool operator>(const optional& x, const optional& y) { - return !x ? false : !y ? true : *x > *y; -} -// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y. -template -constexpr bool operator<=(const optional& x, const optional& y) { - return !x ? true : !y ? false : *x <= *y; -} -// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y. -template -constexpr bool operator>=(const optional& x, const optional& y) { - return !y ? true : !x ? false : *x >= *y; -} - -// Comparison with nullopt [optional.nullops] -// The C++17 (N4606) "Returns:" statements are used directly here. -template -constexpr bool operator==(const optional& x, nullopt_t) noexcept { - return !x; -} -template -constexpr bool operator==(nullopt_t, const optional& x) noexcept { - return !x; -} -template -constexpr bool operator!=(const optional& x, nullopt_t) noexcept { - return static_cast(x); -} -template -constexpr bool operator!=(nullopt_t, const optional& x) noexcept { - return static_cast(x); -} -template -constexpr bool operator<(const optional& x, nullopt_t) noexcept { - return false; -} -template -constexpr bool operator<(nullopt_t, const optional& x) noexcept { - return static_cast(x); -} -template -constexpr bool operator<=(const optional& x, nullopt_t) noexcept { - return !x; -} -template -constexpr bool operator<=(nullopt_t, const optional& x) noexcept { - return true; -} -template -constexpr bool operator>(const optional& x, nullopt_t) noexcept { - return static_cast(x); -} -template -constexpr bool operator>(nullopt_t, const optional& x) noexcept { - return false; -} -template -constexpr bool operator>=(const optional& x, nullopt_t) noexcept { - return true; -} -template -constexpr bool operator>=(nullopt_t, const optional& x) noexcept { - return !x; -} - -// Comparison with T [optional.comp_with_t] -// The C++17 (N4606) "Equivalent to:" statements are used directly here. -template -constexpr bool operator==(const optional& x, const T& v) { - return static_cast(x) ? *x == v : false; -} -template -constexpr bool operator==(const T& v, const optional& x) { - return static_cast(x) ? v == *x : false; -} -template -constexpr bool operator!=(const optional& x, const T& v) { - return static_cast(x) ? *x != v : true; -} -template -constexpr bool operator!=(const T& v, const optional& x) { - return static_cast(x) ? v != *x : true; -} -template -constexpr bool operator<(const optional& x, const T& v) { - return static_cast(x) ? *x < v : true; -} -template -constexpr bool operator<(const T& v, const optional& x) { - return static_cast(x) ? v < *x : false; -} -template -constexpr bool operator<=(const optional& x, const T& v) { - return static_cast(x) ? *x <= v : true; -} -template -constexpr bool operator<=(const T& v, const optional& x) { - return static_cast(x) ? v <= *x : false; -} -template -constexpr bool operator>(const optional& x, const T& v) { - return static_cast(x) ? *x > v : false; -} -template -constexpr bool operator>(const T& v, const optional& x) { - return static_cast(x) ? v > *x : true; -} -template -constexpr bool operator>=(const optional& x, const T& v) { - return static_cast(x) ? *x >= v : false; -} -template -constexpr bool operator>=(const T& v, const optional& x) { - return static_cast(x) ? v >= *x : true; -} - -} // namespace gtl - -namespace std { - -template -struct hash<::gtl::optional> { - size_t operator()(const ::gtl::optional& opt) const { - if (opt) { - return hash()(*opt); - } else { - return static_cast(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() -#include_next -#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 variant { - public: - - // 20.7.2.1, constructors - constexpr variant() noexcept(see below); - variant(const variant&); - variant(variant&&) noexcept(see below); - - template constexpr variant(T&&) noexcept(see below); - - template - constexpr explicit variant(in_place_type_t, Args&&...); - - template - constexpr explicit variant( - in_place_type_t, initializer_list, Args&&...); - - template - constexpr explicit variant(in_place_index_t, Args&&...); - - template - constexpr explicit variant( - in_place_index_t, initializer_list, Args&&...); - - // 20.7.2.2, destructor - ~variant(); - - // 20.7.2.3, assignment - variant& operator=(const variant&); - variant& operator=(variant&&) noexcept(see below); - - template variant& operator=(T&&) noexcept(see below); - - // 20.7.2.4, modifiers - template - T& emplace(Args&&...); - - template - T& emplace(initializer_list, Args&&...); - - template - variant_alternative& emplace(Args&&...); - - template - variant_alternative& emplace(initializer_list, 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 struct variant_size; // undefined - - template - constexpr size_t variant_size_v = variant_size::value; - - template struct variant_size; - template struct variant_size; - template struct variant_size; - - template - struct variant_size>; - - template struct variant_alternative; // undefined - - template - using variant_alternative_t = typename variant_alternative::type; - - template struct variant_alternative; - template struct variant_alternative; - template struct variant_alternative; - - template - struct variant_alternative>; - - constexpr size_t variant_npos = -1; - - // 20.7.4, value access - template - constexpr bool holds_alternative(const variant&) noexcept; - - template - constexpr variant_alternative_t>& - get(variant&); - - template - constexpr variant_alternative_t>&& - get(variant&&); - - template - constexpr variant_alternative_t> const& - get(const variant&); - - template - constexpr variant_alternative_t> const&& - get(const variant&&); - - template - constexpr T& get(variant&); - - template - constexpr T&& get(variant&&); - - template - constexpr const T& get(const variant&); - - template - constexpr const T&& get(const variant&&); - - template - constexpr add_pointer_t>> - get_if(variant*) noexcept; - - template - constexpr add_pointer_t>> - get_if(const variant*) noexcept; - - template - constexpr add_pointer_t - get_if(variant*) noexcept; - - template - constexpr add_pointer_t - get_if(const variant*) noexcept; - - // 20.7.5, relational operators - template - constexpr bool operator==(const variant&, const variant&); - - template - constexpr bool operator!=(const variant&, const variant&); - - template - constexpr bool operator<(const variant&, const variant&); - - template - constexpr bool operator>(const variant&, const variant&); - - template - constexpr bool operator<=(const variant&, const variant&); - - template - constexpr bool operator>=(const variant&, const variant&); - - // 20.7.6, visitation - template - 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 - void swap(variant&, variant&) noexcept(see below); - - // 20.7.10, class bad_variant_access - class bad_variant_access; - - // 20.7.11, hash support - template struct hash; - template struct hash>; - template <> struct hash; - -} // namespace std - -*/ - -#include -#include -#include -#include -#include -#include -#include - -// 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() // >= 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 -#include -#include -#include - -#define RETURN(...) \ - noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } - -namespace mpark -{ -namespace lib -{ -template -struct identity -{ - using type = T; -}; - -inline namespace cpp14 -{ -template -struct array -{ - constexpr const T& operator[](std::size_t index) const { return data[index]; } - - T data[N == 0 ? 1 : N]; -}; - -template -using add_pointer_t = typename std::add_pointer::type; - -template -using common_type_t = typename std::common_type::type; - -template -using decay_t = typename std::decay::type; - -template -using enable_if_t = typename std::enable_if::type; - -template -using remove_const_t = typename std::remove_const::type; - -template -using remove_reference_t = typename std::remove_reference::type; - -template -inline constexpr T&& forward(remove_reference_t& t) noexcept -{ - return static_cast(t); -} - -template -inline constexpr T&& forward(remove_reference_t&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "can not forward an rvalue as an lvalue"); - return static_cast(t); -} - -template -inline constexpr remove_reference_t&& move(T&& t) noexcept -{ - return static_cast&&>(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 -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept { return sizeof...(Is); } -}; - -template -using index_sequence = integer_sequence; - -template -struct make_index_sequence_concat; - -template -struct make_index_sequence_concat, index_sequence> - : identity> -{ -}; - -template -struct make_index_sequence_impl; - -template -using make_index_sequence = typename make_index_sequence_impl::type; - -template -struct make_index_sequence_impl - : make_index_sequence_concat, make_index_sequence> -{ -}; - -template <> -struct make_index_sequence_impl<0> : identity> -{ -}; - -template <> -struct make_index_sequence_impl<1> : identity> -{ -}; - -template -using index_sequence_for = make_index_sequence; -#endif - -// -#ifdef MPARK_TRANSPARENT_OPERATORS -using equal_to = std::equal_to<>; -#else -struct equal_to -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) == lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using not_equal_to = std::not_equal_to<>; -#else -struct not_equal_to -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) != lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using less = std::less<>; -#else -struct less -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) < lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using greater = std::greater<>; -#else -struct greater -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) > lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using less_equal = std::less_equal<>; -#else -struct less_equal -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) <= lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using greater_equal = std::greater_equal<>; -#else -struct greater_equal -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) >= lib::forward(rhs)) -}; -#endif -} // namespace cpp14 - -inline namespace cpp17 -{ -// -template -using bool_constant = std::integral_constant; - -template -struct voider : identity -{ -}; - -template -using void_t = typename voider::type; - -namespace detail -{ -namespace swappable -{ -using std::swap; - -template -struct is_swappable -{ -private: - template (), std::declval()))> - inline static std::true_type test(int); - - template - inline static std::false_type test(...); - -public: - static constexpr bool value = decltype(test(0))::value; -}; - -template ::value> -struct is_nothrow_swappable -{ - static constexpr bool value = noexcept(swap(std::declval(), std::declval())); -}; - -template -struct is_nothrow_swappable : std::false_type -{ -}; - -} // namespace swappable -} // namespace detail - -using detail::swappable::is_nothrow_swappable; -using detail::swappable::is_swappable; - -// -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif -template -inline constexpr auto invoke(F&& f, As&&... as) RETURN(lib::forward(f)(lib::forward(as)...)) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - template - inline constexpr auto invoke(T B::*pmv, D&& d) RETURN(lib::forward(d).*pmv) - - template - inline constexpr auto invoke(Pmv pmv, Ptr&& ptr) RETURN((*lib::forward(ptr)).*pmv) - - template - inline constexpr auto invoke(T B::*pmf, D&& d, As&&... as) - RETURN((lib::forward(d).*pmf)(lib::forward(as)...)) - - template - inline constexpr auto invoke(Pmf pmf, Ptr&& ptr, As&&... as) - RETURN(((*lib::forward(ptr)).*pmf)(lib::forward(as)...)) - - namespace detail -{ - template - struct invoke_result - { - }; - - template - struct invoke_result(), std::declval()...))>, F, - Args...> - : identity(), std::declval()...))> - { - }; - -} // namespace detail - -template -using invoke_result = detail::invoke_result; - -template -using invoke_result_t = typename invoke_result::type; - -namespace detail -{ -template -struct is_invocable : std::false_type -{ -}; - -template -struct is_invocable>, F, Args...> : std::true_type -{ -}; - -template -struct is_invocable_r : std::false_type -{ -}; - -template -struct is_invocable_r>, R, F, Args...> - : std::is_convertible, R> -{ -}; - -} // namespace detail - -template -using is_invocable = detail::is_invocable; - -template -using is_invocable_r = detail::is_invocable_r; - -// -#ifdef MPARK_BUILTIN_ADDRESSOF -template -inline constexpr T* addressof(T& arg) -{ - return __builtin_addressof(arg); -} -#else -namespace detail -{ -namespace has_addressof_impl -{ -struct fail; - -template -inline fail operator&(T&&); - -template -inline static constexpr bool impl() -{ - return (std::is_class::value || std::is_union::value) && - !std::is_same()), fail>::value; -} - -} // namespace has_addressof_impl - -template -using has_addressof = bool_constant()>; - -template -inline constexpr T* addressof(T& arg, std::true_type) -{ - return std::addressof(arg); -} - -template -inline constexpr T* addressof(T& arg, std::false_type) -{ - return &arg; -} - -} // namespace detail - -template -inline constexpr T* addressof(T& arg) -{ - return detail::addressof(arg, detail::has_addressof{}); -} -#endif - -template -inline constexpr T* addressof(const T&&) = delete; - -} // namespace cpp17 - -template -struct remove_all_extents : identity -{ -}; - -template -struct remove_all_extents> : remove_all_extents -{ -}; - -template -using remove_all_extents_t = typename remove_all_extents::type; - -template -using size_constant = std::integral_constant; - -template -struct indexed_type : size_constant, identity -{ -}; - -template -using all = std::is_same, integer_sequence>; - -#ifdef MPARK_TYPE_PACK_ELEMENT -template -using type_pack_element_t = __type_pack_element; -#else -template -struct type_pack_element_impl -{ -private: - template - struct set; - - template - struct set> : indexed_type... - { - }; - - template - inline static std::enable_if impl(indexed_type); - - inline static std::enable_if impl(...); - -public: - using type = decltype(impl(set>{})); -}; - -template -using type_pack_element = typename type_pack_element_impl::type; - -template -using type_pack_element_t = typename type_pack_element::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 -struct is_trivially_copy_constructible - : bool_constant::value&& __has_trivial_copy(T)> -{ -}; - -template -struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> -{ -}; - -template -struct is_trivially_copy_assignable - : bool_constant::value&& __has_trivial_assign(T)> -{ -}; - -template -struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> -{ -}; -#endif - -template -struct dependent_type : T -{ -}; - -template -struct push_back; - -template -using push_back_t = typename push_back::type; - -template -struct push_back, J> -{ - using type = index_sequence; -}; - -} // 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 { return __VA_ARGS__; } - -#define AUTO_REFREF auto -#define AUTO_REFREF_RETURN(...) \ - ->decltype((__VA_ARGS__)) \ - { \ - static_assert(std::is_reference::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 -class variant; - -template -struct variant_size; - -#ifdef MPARK_VARIABLE_TEMPLATES -template -constexpr std::size_t variant_size_v = variant_size::value; -#endif - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size> : lib::size_constant -{ -}; - -template -struct variant_alternative; - -template -using variant_alternative_t = typename variant_alternative::type; - -template -struct variant_alternative : std::add_const> -{ -}; - -template -struct variant_alternative : std::add_volatile> -{ -}; - -template -struct variant_alternative : std::add_cv> -{ -}; - -template -struct variant_alternative> -{ - static_assert(I < sizeof...(Ts), "Index out of bounds in std::variant_alternative<>"); - using type = lib::type_pack_element_t; -}; - -constexpr std::size_t variant_npos = static_cast(-1); - -namespace detail -{ -constexpr std::size_t not_found = static_cast(-1); -constexpr std::size_t ambiguous = static_cast(-2); - -#ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr std::size_t find_index() -{ - constexpr lib::array matches = {{std::is_same::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 -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 -inline constexpr std::size_t find_index() -{ - return find_index_impl(not_found, 0, std::is_same::value...); -} -#endif - -template -using find_index_sfinae_impl = - lib::enable_if_t>; - -template -using find_index_sfinae = find_index_sfinae_impl()>; - -template -struct find_index_checked_impl : lib::size_constant -{ - static_assert(I != not_found, "the specified type is not found."); - static_assert(I != ambiguous, "the specified type is ambiguous."); -}; - -template -using find_index_checked = find_index_checked_impl()>; - -struct valueless_t -{ -}; - -enum class Trait -{ - TriviallyAvailable, - Available, - Unavailable -}; - -template class IsTriviallyAvailable, - template class IsAvailable> -inline constexpr Trait trait() -{ - return IsTriviallyAvailable::value ? - Trait::TriviallyAvailable : - IsAvailable::value ? Trait::Available : Trait::Unavailable; -} - -#ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr Trait common_trait(Traits... traits) -{ - Trait result = Trait::TriviallyAvailable; - for (Trait t : {traits...}) - { - if (static_cast(t) > static_cast(result)) - { - result = t; - } - } - return result; -} -#else -inline constexpr Trait common_trait_impl(Trait result) -{ - return result; -} - -template -inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts) -{ - return static_cast(t) > static_cast(result) ? common_trait_impl(t, ts...) : - common_trait_impl(result, ts...); -} - -template -inline constexpr Trait common_trait(Traits... ts) -{ - return common_trait_impl(Trait::TriviallyAvailable, ts...); -} -#endif - -template -struct traits -{ - static constexpr Trait copy_constructible_trait = common_trait( - trait()...); - - static constexpr Trait move_constructible_trait = common_trait( - trait()...); - - static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, - trait()...); - - static constexpr Trait move_assignable_trait = - common_trait(move_constructible_trait, - trait()...); - - static constexpr Trait destructible_trait = - common_trait(trait()...); -}; - -namespace access -{ -struct recursive_union -{ -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto&& get_alt(V&& v, in_place_index_t<0>) - { - return lib::forward(v).head_; - } - - template - inline static constexpr auto&& get_alt(V&& v, in_place_index_t) - { - return get_alt(lib::forward(v).tail_, in_place_index_t{}); - } -#else - template - struct get_alt_impl - { - template - inline constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) - }; - - template - struct get_alt_impl<0, Dummy> - { - template - inline constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(lib::forward(v).head_) - }; - - template - inline static constexpr AUTO_REFREF get_alt(V&& v, in_place_index_t) - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) -#endif -}; - -struct base -{ - template - inline static constexpr AUTO_REFREF get_alt(V&& v) - AUTO_REFREF_RETURN(recursive_union::get_alt(data(lib::forward(v)), in_place_index_t{})) -}; - -struct variant -{ - template - inline static constexpr AUTO_REFREF get_alt(V&& v) - AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) -}; - -} // namespace access - -namespace visitation -{ -struct base -{ - template - inline static constexpr const T& at(const T& elem) - { - return elem; - } - - template - inline static constexpr const lib::remove_all_extents_t& at(const lib::array& elems, - std::size_t i, Is... is) - { - return at(elems[i], is...); - } - - template - inline static constexpr int visit_visitor_return_type_check() - { - static_assert(lib::all::value...>::value, - "`mpark::visit` requires the visitor to have a single " - "return type."); - return 0; - } - - template - inline static constexpr lib::array...>, sizeof...(Fs)> - make_farray(Fs&&... fs) - { - using result = lib::array...>, sizeof...(Fs)>; - return visit_visitor_return_type_check...>(), - result{{lib::forward(fs)...}}; - } - - template - struct dispatcher - { - template - struct impl - { - inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs) - DECLTYPE_AUTO_RETURN(lib::invoke(static_cast(f), - access::base::get_alt(static_cast(vs))...)) - }; - }; - - template - inline static constexpr AUTO make_dispatch(lib::index_sequence) - AUTO_RETURN(&dispatcher::template impl::dispatch) - - template - inline static constexpr AUTO make_fdiagonal_impl() AUTO_RETURN( - make_dispatch(lib::index_sequence::value...>{})) - - template - inline static constexpr AUTO make_fdiagonal_impl(lib::index_sequence) - AUTO_RETURN(make_farray(make_fdiagonal_impl()...)) - - template - inline static constexpr /* auto * */ auto make_fdiagonal() - -> decltype(make_fdiagonal_impl( - lib::make_index_sequence::size()>{})) - { - static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, - "all of the variants must be the same size."); - return make_fdiagonal_impl(lib::make_index_sequence::size()>{}); - } - -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto make_fmatrix_impl(Is is) - { - return make_dispatch(is); - } - - template - inline static constexpr auto make_fmatrix_impl(Is, lib::index_sequence, Ls... ls) - { - return make_farray(make_fmatrix_impl(lib::push_back_t{}, ls...)...); - } - - template - inline static constexpr auto make_fmatrix() - { - return make_fmatrix_impl(lib::index_sequence<>{}, - lib::make_index_sequence::size()>{}...); - } -#else - template - struct make_fmatrix_impl - { - template - struct impl; - - template - struct impl - { - inline constexpr AUTO operator()() const AUTO_RETURN(make_dispatch(Is{})) - }; - - template - struct impl, Ls...> - { - inline constexpr AUTO operator()() const - AUTO_RETURN(make_farray(impl, Ls...>{}()...)) - }; - }; - - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN(typename make_fmatrix_impl::template impl< - lib::index_sequence<>, lib::make_index_sequence::size()>...>{}()) -#endif -}; // namespace base - -template -using FDiagonal = decltype(base::make_fdiagonal()); - -template -struct fdiagonal -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4268) -#endif - static constexpr FDiagonal value = base::make_fdiagonal(); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -}; - -template -constexpr FDiagonal fdiagonal::value; - -template -using FMatrix = decltype(base::make_fmatrix()); - -template -struct fmatrix -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4268) -#endif - static constexpr FMatrix value = base::make_fmatrix(); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -}; - -template -constexpr FMatrix fmatrix::value; - -struct alt -{ - template - inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor&& visitor, - Vs&&... vs) - DECLTYPE_AUTO_RETURN( - base::at(fdiagonal(vs)))...>::value, - index)(lib::forward(visitor), as_base(lib::forward(vs))...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_alt(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - base::at(fmatrix(vs)))...>::value, - vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) -}; - -struct variant -{ -private: - template - struct visit_exhaustive_visitor_check - { - static_assert(lib::is_invocable::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), - lib::forward(values)...)) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - }; - - template - struct value_visitor - { - Visitor&& visitor_; - - template - inline constexpr DECLTYPE_AUTO operator()(Alts&&... alts) const DECLTYPE_AUTO_RETURN( - visit_exhaustive_visitor_check(alts).value))...>{}( - lib::forward(visitor_), lib::forward(alts).value...)) - }; - - template - inline static constexpr AUTO make_value_visitor(Visitor&& visitor) - AUTO_RETURN(value_visitor{lib::forward(visitor)}) - - public - : template - 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), - lib::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), - lib::forward(vs).impl_...)) - - template - 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)), - lib::forward(vs)...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_value(Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(visit_alt(make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) -}; - -} // namespace visitation - -template -struct alt -{ - using value_type = T; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - template - inline explicit constexpr alt(in_place_t, Args&&... args) : value(lib::forward(args)...) - { - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - T value; -}; - -template -union recursive_union; - -template -union recursive_union -{ -}; - -#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ - template \ - union recursive_union \ - { \ - public: \ - inline explicit constexpr recursive_union(valueless_t) noexcept : dummy_{} {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t<0>, Args&&... args) \ - : head_(in_place_t{}, lib::forward(args)...) \ - { \ - } \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t, Args&&... args) \ - : tail_(in_place_index_t{}, lib::forward(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 head_; \ - recursive_union 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 -class base -{ -public: - inline explicit constexpr base(valueless_t tag) noexcept - : data_(tag), index_(static_cast(-1)) - { - } - - template - inline explicit constexpr base(in_place_index_t, Args&&... args) - : data_(in_place_index_t{}, lib::forward(args)...), index_(I) - { - } - - inline constexpr bool valueless_by_exception() const noexcept - { - return index_ == static_cast(-1); - } - - inline constexpr std::size_t index() const noexcept - { - return valueless_by_exception() ? variant_npos : index_; - } - -protected: - using data_t = recursive_union; - - 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 - 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 \ - inline explicit constexpr type(Args&&... args) : base(lib::forward(args)...) \ - { \ - } -#else -#define INHERITING_CTOR(type, base) using base::base; -#endif - -template -class destructor; - -#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ - template \ - class destructor, destructible_trait> : public base \ - { \ - using super = base; \ - \ - 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(-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(-1); - }); - -MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; - , inline void destroy() noexcept = delete;); - -#undef MPARK_VARIANT_DESTRUCTOR - -template -class constructor : public destructor -{ - using super = destructor; - -public: - INHERITING_CTOR(constructor, super) - using super::operator=; - -protected: -#ifndef MPARK_GENERIC_LAMBDAS - struct ctor - { - template - inline void operator()(LhsAlt& lhs_alt, RhsAlt&& rhs_alt) const - { - constructor::construct_alt(lhs_alt, lib::forward(rhs_alt).value); - } - }; -#endif - - template - inline static T& construct_alt(alt& a, Args&&... args) - { - ::new (static_cast(lib::addressof(a))) - alt(in_place_t{}, lib::forward(args)...); - return a.value; - } - - template - 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(rhs_alt).value); - } -#else - ctor {} -#endif - , - lhs, lib::forward(rhs)); - lhs.index_ = rhs.index_; - } - } -}; - -template -class move_constructor; - -#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ - template \ - class move_constructor, move_constructible_trait> \ - : public constructor> \ - { \ - using super = constructor>; \ - \ - 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::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 -class copy_constructor; - -#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ - template \ - class copy_constructor, copy_constructible_trait> \ - : public move_constructor> \ - { \ - using super = move_constructor>; \ - \ - 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 -class assignment : public copy_constructor -{ - using super = copy_constructor; - -public: - INHERITING_CTOR(assignment, super) - using super::operator=; - - template - inline /* auto & */ auto emplace(Args&&... args) - -> decltype(this->construct_alt(access::base::get_alt(*this), lib::forward(args)...)) - { - this->destroy(); - auto& result = - this->construct_alt(access::base::get_alt(*this), lib::forward(args)...); - this->index_ = I; - return result; - } - -protected: -#ifndef MPARK_GENERIC_LAMBDAS - template - struct assigner - { - template - inline void operator()(ThisAlt& this_alt, ThatAlt&& that_alt) const - { - self->assign_alt(this_alt, lib::forward(that_alt).value); - } - assignment* self; - }; -#endif - - template - inline void assign_alt(alt& a, Arg&& arg) - { - if (this->index() == I) - { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - a.value = lib::forward(arg); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - } - else - { - struct - { - void operator()(std::true_type) const { this_->emplace(lib::forward(arg_)); } - void operator()(std::false_type) const { this_->emplace(T(lib::forward(arg_))); } - assignment* this_; - Arg&& arg_; - } impl{this, lib::forward(arg)}; - impl(lib::bool_constant < std::is_nothrow_constructible::value || - !std::is_nothrow_move_constructible::value > {}); - } - } - - template - 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(that_alt).value); - } -#else - assigner { this } -#endif - , - *this, lib::forward(that)); - } - } -}; - -template -class move_assignment; - -#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ - template \ - class move_assignment, move_assignable_trait> : public assignment> \ - { \ - using super = assignment>; \ - \ - 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::value && - std::is_nothrow_move_assignable::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 -class copy_assignment; - -#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ - template \ - class copy_assignment, copy_assignable_trait> \ - : public move_assignment> \ - { \ - using super = move_assignment>; \ - \ - 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 -class impl : public copy_assignment> -{ - using super = copy_assignment>; - -public: - INHERITING_CTOR(impl, super) - using super::operator=; - - template - inline void assign(Arg&& arg) - { - this->assign_alt(access::base::get_alt(*this), lib::forward(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 - 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{ - {std::is_nothrow_move_constructible::value...}}[this->index()]; - } -}; - -template -struct overload_leaf -{ - using F = lib::size_constant (*)(T); - operator F() const { return nullptr; } -}; - -template -struct overload_impl -{ -private: - template - struct impl; - - template - struct impl> : overload_leaf... - { - }; - -public: - using type = impl>; -}; - -template -using overload = typename overload_impl::type; - -template -using best_match = lib::invoke_result_t, T&&>; - -template -struct is_in_place_index : std::false_type -{ -}; - -template -struct is_in_place_index> : std::true_type -{ -}; - -template -struct is_in_place_type : std::false_type -{ -}; - -template -struct is_in_place_type> : std::true_type -{ -}; - -} // namespace detail - -template -class variant -{ - static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have an array type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a reference type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a void type as an alternative."); - -public: - template , - lib::enable_if_t::value, int> = 0> - inline constexpr variant() noexcept(std::is_nothrow_default_constructible::value) - : impl_(in_place_index_t<0>{}) - { - } - - variant(const variant&) = default; - variant(variant&&) = default; - - template , - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t::value, int> = 0> - inline constexpr variant(Arg&& arg) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(arg)) - { - } - - template , - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(in_place_index_t, Args&&... args) noexcept( - std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - { - } - - template < - std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, - lib::enable_if_t&, Args...>::value, int> = - 0> - inline explicit constexpr variant( - in_place_index_t, std::initializer_list il, - Args&&... args) noexcept(std::is_nothrow_constructible&, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - { - } - - template ::value, - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(in_place_type_t, Args&&... args) noexcept( - std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - { - } - - template ::value, - lib::enable_if_t&, Args...>::value, - int> = 0> - inline explicit constexpr variant( - in_place_type_t, std::initializer_list il, - Args&&... args) noexcept(std::is_nothrow_constructible&, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - { - } - - ~variant() = default; - - variant& operator=(const variant&) = default; - variant& operator=(variant&&) = default; - - template < - typename Arg, lib::enable_if_t, variant>::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t<(std::is_assignable::value && std::is_constructible::value), - int> = 0> - inline variant& operator=(Arg&& arg) noexcept((std::is_nothrow_assignable::value && - std::is_nothrow_constructible::value)) - { - impl_.template assign(lib::forward(arg)); - return *this; - } - - template , - lib::enable_if_t::value, int> = 0> - inline T& emplace(Args&&... args) - { - return impl_.template emplace(lib::forward(args)...); - } - - template < - std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, - lib::enable_if_t&, Args...>::value, int> = - 0> - inline T& emplace(std::initializer_list il, Args&&... args) - { - return impl_.template emplace(il, lib::forward(args)...); - } - - template ::value, - lib::enable_if_t::value, int> = 0> - inline T& emplace(Args&&... args) - { - return impl_.template emplace(lib::forward(args)...); - } - - template ::value, - lib::enable_if_t&, Args...>::value, - int> = 0> - inline T& emplace(std::initializer_list il, Args&&... args) - { - return impl_.template emplace(il, lib::forward(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>::value && - lib::dependent_type, Dummy>::value)...>::value, - int> = 0> - inline void - swap(variant& that) noexcept(lib::all<(std::is_nothrow_move_constructible::value && - lib::is_nothrow_swappable::value)...>::value) - { - impl_.swap(that.impl_); - } - -private: - detail::impl impl_; - - friend struct detail::access::variant; - friend struct detail::visitation::variant; -}; - -template -inline constexpr bool holds_alternative(const variant& v) noexcept -{ - return v.index() == I; -} - -template -inline constexpr bool holds_alternative(const variant& v) noexcept -{ - return holds_alternative::value>(v); -} - -namespace detail -{ -template -struct generic_get_impl -{ - constexpr generic_get_impl(int) {} - - constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(access::variant::get_alt(lib::forward(v)).value) -}; - -template -inline constexpr AUTO_REFREF generic_get(V&& v) AUTO_REFREF_RETURN(generic_get_impl( - holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))(lib::forward(v))) -} // namespace detail - -template -inline constexpr variant_alternative_t>& get(variant& v) -{ - return detail::generic_get(v); -} - -template -inline constexpr variant_alternative_t>&& get(variant&& v) -{ - return detail::generic_get(lib::move(v)); -} - -template -inline constexpr const variant_alternative_t>& get(const variant& v) -{ - return detail::generic_get(v); -} - -template -inline constexpr const variant_alternative_t>&& get(const variant&& v) -{ - return detail::generic_get(lib::move(v)); -} - -template -inline constexpr T& get(variant& v) -{ - return get::value>(v); -} - -template -inline constexpr T&& get(variant&& v) -{ - return get::value>(lib::move(v)); -} - -template -inline constexpr const T& get(const variant& v) -{ - return get::value>(v); -} - -template -inline constexpr const T&& get(const variant&& v) -{ - return get::value>(lib::move(v)); -} - -namespace detail -{ -template -inline constexpr /* auto * */ AUTO generic_get_if(V* v) noexcept AUTO_RETURN( - v&& holds_alternative(*v) ? lib::addressof(access::variant::get_alt(*v).value) : nullptr) - -} // namespace detail - -template -inline constexpr lib::add_pointer_t>> -get_if(variant* v) noexcept -{ - return detail::generic_get_if(v); -} - -template -inline constexpr lib::add_pointer_t>> -get_if(const variant* v) noexcept -{ - return detail::generic_get_if(v); -} - -template -inline constexpr lib::add_pointer_t get_if(variant* v) noexcept -{ - return get_if::value>(v); -} - -template -inline constexpr lib::add_pointer_t get_if(const variant* v) noexcept -{ - return get_if::value>(v); -} - -template -inline constexpr bool operator==(const variant& lhs, const variant& 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 -inline constexpr bool operator!=(const variant& lhs, const variant& 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 -inline constexpr bool operator<(const variant& lhs, const variant& 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 -inline constexpr bool operator>(const variant& lhs, const variant& 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 -inline constexpr bool operator<=(const variant& lhs, const variant& 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 -inline constexpr bool operator>=(const variant& lhs, const variant& 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 bs) -{ - for (bool b : bs) - { - if (!b) - { - return false; - } - } - return true; -} - -} // namespace detail - -template -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), - lib::forward(vs)...); -} -#else -namespace detail -{ -template -inline constexpr bool all_impl(const lib::array& bs, std::size_t idx) -{ - return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); -} - -template -inline constexpr bool all(const lib::array& bs) -{ - return all_impl(bs, 0); -} - -} // namespace detail - -template -inline constexpr DECLTYPE_AUTO visit(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - (detail::all(lib::array{{!vs.valueless_by_exception()...}}) ? - (void)0 : - throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...)) -#endif - -template -inline auto swap(variant& lhs, variant& rhs) noexcept(noexcept(lhs.swap(rhs))) - -> decltype(lhs.swap(rhs)) -{ - lhs.swap(rhs); -} - -namespace detail -{ -template -using enabled_type = T; - -namespace hash -{ -template -constexpr bool meets_requirements() -{ - return std::is_copy_constructible::value && std::is_move_constructible::value && - lib::is_invocable_r::value; -} - -template -constexpr bool is_enabled() -{ - using H = std::hash; - return meets_requirements() && std::is_default_constructible::value && - std::is_copy_assignable::value && std::is_move_assignable::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 -struct hash, mpark::lib::enable_if_t>()...>::value>>> -{ - using argument_type = mpark::variant; - 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; - using value_type = - mpark::lib::remove_const_t; - return hash{}(alt.value); - } -#else - hasher {} -#endif - , - v); - return hash_combine(result, hash{}(v.index())); - } - -private: -#ifndef MPARK_GENERIC_LAMBDAS - struct hasher - { - template - inline std::size_t operator()(const Alt& alt) const - { - using alt_type = mpark::lib::decay_t; - using value_type = mpark::lib::remove_const_t; - return hash{}(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 -{ - 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