diff options
| author | Léo Lam <leo@innovatetechnologi.es> | 2017-12-25 22:35:08 +0100 |
|---|---|---|
| committer | Léo Lam <leo@innovatetechnologi.es> | 2019-05-04 23:04:18 +0200 |
| commit | 04c8201c323bd5cb7fd09beb456e4e77608270f7 (patch) | |
| tree | f5089bf107a783068cbb54fc03a3fcdfc5a6d372 /Source/Core | |
| parent | 99a4ca8de7111c8554b50217744e24bc71912cfe (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.h | 45 | ||||
| -rw-r--r-- | Source/Core/Common/Compat/optional | 907 | ||||
| -rw-r--r-- | Source/Core/Common/Compat/variant | 2523 |
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 |
