From 04c8201c323bd5cb7fd09beb456e4e77608270f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 25 Dec 2017 22:35:08 +0100 Subject: [PATCH 1/6] 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 --- Source/CMakeLists.txt | 13 +- Source/Core/Common/Compat/in_place.h | 45 - Source/Core/Common/Compat/optional | 907 --------- Source/Core/Common/Compat/variant | 2523 -------------------------- 4 files changed, 4 insertions(+), 3484 deletions(-) delete mode 100644 Source/Core/Common/Compat/in_place.h delete mode 100644 Source/Core/Common/Compat/optional delete mode 100644 Source/Core/Common/Compat/variant diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 69a8cd9eab..2899476e34 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -16,18 +16,13 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC") check_and_add_flag(CPPLATEST /std:c++latest) check_and_add_flag(STANDARD_COMPLIANCE /permissive-) else() - # Enable C++17, but fall back to C++14 if it isn't available. - # CMAKE_CXX_STANDARD cannot be used here because we require C++14 or newer, not any standard. + # Enable C++17 + # CMAKE_CXX_STANDARD cannot be used because it requires cmake 3.8+. check_and_add_flag(CXX17 -std=c++17) if(NOT FLAG_CXX_CXX17) - set(CMAKE_CXX_STANDARD 14) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) + # Fall back to -std=c++1z + check_and_add_flag(CXX1Z -std=c++1z) endif() - - # These compat headers must not be in the include path when building with MSVC, - # because it currently does not support __has_include_next / #include_next. - include_directories(SYSTEM Core/Common/Compat) endif() # These aren't actually needed for C11/C++11 diff --git a/Source/Core/Common/Compat/in_place.h b/Source/Core/Common/Compat/in_place.h deleted file mode 100644 index bded66c019..0000000000 --- a/Source/Core/Common/Compat/in_place.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#include - -namespace mpark -{ -struct in_place_t -{ - explicit in_place_t() = default; -}; - -template -struct in_place_index_t -{ - explicit in_place_index_t() = default; -}; - -template -struct in_place_type_t -{ - explicit in_place_type_t() = default; -}; - -#ifdef MPARK_VARIABLE_TEMPLATES -constexpr in_place_t in_place{}; - -template -constexpr in_place_index_t in_place_index{}; - -template -constexpr in_place_type_t in_place_type{}; -#endif - -} // namespace mpark diff --git a/Source/Core/Common/Compat/optional b/Source/Core/Common/Compat/optional deleted file mode 100644 index 1da42ff4d2..0000000000 --- a/Source/Core/Common/Compat/optional +++ /dev/null @@ -1,907 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#if __cplusplus >= 201703L && __has_include_next() -#include_next -#else -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include -#include -#include -#include - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) -#define GTL_HAS_EXCEPTIONS -#endif - -namespace gtl { - -// A value of type gtl::optional holds either a value of T or an -// "empty" value. When it holds a value of T, it stores it as a direct -// subobject, so sizeof(optional) is approximately sizeof(T)+1. The interface -// is based on the upcoming std::optional, and gtl::optional is -// designed to be cheaply drop-in replaceable by std::optional, once it is -// rolled out. -// -// This implementation is based on the specification in the latest draft as of -// 2017-01-05, section 20.6. -// -// Differences between gtl::optional and std::optional include: -// - constexpr not used for nonconst member functions. -// (dependency on some differences between C++11 and C++14.) -// - nullopt and in_place are not constexpr. We need the inline variable -// support in C++17 for external linkage. -// - optional::swap() and swap() relies on std::is_(nothrow_)swappable -// which is introduced in C++17. So we assume is_swappable is always true -// and is_nothrow_swappable is same as std::is_trivial. -// - make_optional cannot be constexpr due to absence of guaranteed copy -// elision. -// -// Synopsis: -// -// #include "tensorflow/core/lib/gtl/optional.h" -// -// tensorflow::gtl::optional f() { -// string result; -// if (...) { -// ... -// result = ...; -// return result; -// } else { -// ... -// return tensorflow::gtl::nullopt; -// } -// } -// -// int main() { -// tensorflow::gtl::optional optstr = f(); -// if (optstr) { -// // non-empty -// print(optstr.value()); -// } else { -// // empty -// error(); -// } -// } -template -class optional; - -// The tag constant `in_place` is used as the first parameter of an optional -// constructor to indicate that the remaining arguments should be forwarded -// to the underlying T constructor. -struct in_place_t {}; -extern const in_place_t in_place; - -// The tag constant `nullopt` is used to indicate an empty optional in -// certain functions, such as construction or assignment. -struct nullopt_t { - struct init_t {}; - static init_t init; - // It must not be default-constructible to avoid ambiguity for opt = {}. - // Note the non-const reference, it is to eliminate ambiguity for code like: - // struct S { int value; }; - // - // void Test() { - // optional opt; - // opt = {{}}; - // } - explicit constexpr nullopt_t(init_t& /*unused*/) {} // NOLINT -}; -extern const nullopt_t nullopt; - -class bad_optional_access : public std::exception -{ -public: - virtual const char* what() const noexcept { return "bad_optional_access"; } -}; - -[[noreturn]] inline void throw_bad_optional_access() -{ -#ifdef GTL_HAS_EXCEPTIONS - throw bad_optional_access{}; -#else - std::terminate(); -#endif -} - -namespace internal_optional { - -// define forward locally because std::forward is not constexpr until C++14 -template -constexpr T&& forward(typename std::remove_reference::type& - t) noexcept { // NOLINT(runtime/references) - return static_cast(t); -} - -struct empty_struct {}; -// This class stores the data in optional. -// It is specialized based on whether T is trivially destructible. -// This is the specialization for non trivially destructible type. -template ::value> -class optional_data_dtor_base { - protected: - // Whether there is data or not. - bool engaged_; - // data storage - union { - empty_struct dummy_; - T data_; - }; - - void destruct() noexcept { - if (engaged_) { - data_.~T(); - engaged_ = false; - } - } - - // dummy_ must be initialized for constexpr constructor - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {} - - template - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(internal_optional::forward(args)...) {} - - ~optional_data_dtor_base() { destruct(); } -}; - -// Specialization for trivially destructible type. -template -class optional_data_dtor_base { - protected: - // Whether there is data or not. - bool engaged_; - // data storage - union { - empty_struct dummy_; - T data_; - }; - void destruct() noexcept { engaged_ = false; } - - // dummy_ must be initialized for constexpr constructor - constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{} {} - - template - constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args) - : engaged_(true), data_(internal_optional::forward(args)...) {} - - ~optional_data_dtor_base() = default; -}; - -template -class optional_data : public optional_data_dtor_base { - protected: - using base = optional_data_dtor_base; - using base::base; - - T* pointer() { return &this->data_; } - - constexpr const T* pointer() const { return &this->data_; } - - template - void construct(Args&&... args) { - new (pointer()) T(std::forward(args)...); - this->engaged_ = true; - } - - template - void assign(U&& u) { - if (this->engaged_) { - this->data_ = std::forward(u); - } else { - construct(std::forward(u)); - } - } - - optional_data() = default; - - optional_data(const optional_data& rhs) { - if (rhs.engaged_) { - construct(rhs.data_); - } - } - - optional_data(optional_data&& rhs) noexcept( - std::is_nothrow_move_constructible::value) { - if (rhs.engaged_) { - construct(std::move(rhs.data_)); - } - } - - optional_data& operator=(const optional_data& rhs) { - if (rhs.engaged_) { - assign(rhs.data_); - } else { - this->destruct(); - } - return *this; - } - - optional_data& operator=(optional_data&& rhs) noexcept( - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value) { - if (rhs.engaged_) { - assign(std::move(rhs.data_)); - } else { - this->destruct(); - } - return *this; - } -}; - -// ordered by level of restriction, from low to high. -// copyable implies movable. -enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 }; - -// base class for enabling/disabling copy/move constructor. -template -class optional_ctor_base; - -template <> -class optional_ctor_base { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = default; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = default; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -template <> -class optional_ctor_base { - public: - constexpr optional_ctor_base() = default; - optional_ctor_base(const optional_ctor_base&) = delete; - optional_ctor_base(optional_ctor_base&&) = delete; - optional_ctor_base& operator=(const optional_ctor_base&) = default; - optional_ctor_base& operator=(optional_ctor_base&&) = default; -}; - -// base class for enabling/disabling copy/move assignment. -template -class optional_assign_base; - -template <> -class optional_assign_base { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = default; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = default; -}; - -template <> -class optional_assign_base { - public: - constexpr optional_assign_base() = default; - optional_assign_base(const optional_assign_base&) = default; - optional_assign_base(optional_assign_base&&) = default; - optional_assign_base& operator=(const optional_assign_base&) = delete; - optional_assign_base& operator=(optional_assign_base&&) = delete; -}; - -template -constexpr copy_traits get_ctor_copy_traits() { - return std::is_copy_constructible::value - ? copy_traits::copyable - : std::is_move_constructible::value ? copy_traits::movable - : copy_traits::non_movable; -} - -template -constexpr copy_traits get_assign_copy_traits() { - return std::is_copy_assignable::value && - std::is_copy_constructible::value - ? copy_traits::copyable - : std::is_move_assignable::value && - std::is_move_constructible::value - ? copy_traits::movable - : copy_traits::non_movable; -} - -// Whether T is constructible or convertible from optional. -template -struct is_constructible_convertible_from_optional - : std::integral_constant< - bool, std::is_constructible&>::value || - std::is_constructible&&>::value || - std::is_constructible&>::value || - std::is_constructible&&>::value || - std::is_convertible&, T>::value || - std::is_convertible&&, T>::value || - std::is_convertible&, T>::value || - std::is_convertible&&, T>::value> {}; - -// Whether T is constructible or convertible or assignable from optional. -template -struct is_constructible_convertible_assignable_from_optional - : std::integral_constant< - bool, is_constructible_convertible_from_optional::value || - std::is_assignable&>::value || - std::is_assignable&&>::value || - std::is_assignable&>::value || - std::is_assignable&&>::value> {}; - -} // namespace internal_optional - -template -class optional : private internal_optional::optional_data, - private internal_optional::optional_ctor_base< - internal_optional::get_ctor_copy_traits()>, - private internal_optional::optional_assign_base< - internal_optional::get_assign_copy_traits()> { - using data_base = internal_optional::optional_data; - - public: - typedef T value_type; - - // [optional.ctor], constructors - - // A default constructed optional holds the empty value, NOT a default - // constructed T. - constexpr optional() noexcept {} - - // An optional initialized with `nullopt` holds the empty value. - constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit) - - // Copy constructor, standard semantics. - optional(const optional& src) = default; - - // Move constructor, standard semantics. - optional(optional&& src) = default; - - // optional(in_place, arg1, arg2, arg3) constructs a non-empty optional - // with an in-place constructed value of T(arg1,arg2,arg3). - // TODO(b/34201852): Add std::is_constructible SFINAE. - template - constexpr explicit optional(in_place_t, Args&&... args) - : data_base(in_place_t(), internal_optional::forward(args)...) {} - - // optional(in_place, {arg1, arg2, arg3}) constructs a non-empty optional - // with an in-place list-initialized value of T({arg1, arg2, arg3}). - template &, Args&&...>::value>::type> - constexpr explicit optional(in_place_t, std::initializer_list il, - Args&&... args) - : data_base(in_place_t(), il, internal_optional::forward(args)...) { - } - - template < - typename U = T, - typename std::enable_if< - std::is_constructible::value && - !std::is_same::type>::value && - !std::is_same, typename std::decay::type>::value && - std::is_convertible::value, - bool>::type = false> - constexpr optional(U&& v) // NOLINT - : data_base(in_place_t(), internal_optional::forward(v)) {} - - template < - typename U = T, - typename std::enable_if< - std::is_constructible::value && - !std::is_same::type>::value && - !std::is_same, typename std::decay::type>::value && - !std::is_convertible::value, - bool>::type = false> - explicit constexpr optional(U&& v) - : data_base(in_place_t(), internal_optional::forward(v)) {} - - // Converting copy constructor (implicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - std::is_convertible::value, - bool>::type = false> - optional(const optional& rhs) { // NOLINT - if (rhs) { - this->construct(*rhs); - } - } - - // Converting copy constructor (explicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - !std::is_convertible::value, - bool>::type = false> - explicit optional(const optional& rhs) { - if (rhs) { - this->construct(*rhs); - } - } - - // Converting move constructor (implicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - std::is_convertible::value, - bool>::type = false> - optional(optional&& rhs) { // NOLINT - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // Converting move constructor (explicit) - template < - typename U, - typename std::enable_if< - std::is_constructible::value && - !internal_optional::is_constructible_convertible_from_optional< - T, U>::value && - !std::is_convertible::value, - bool>::type = false> - explicit optional(optional&& rhs) { - if (rhs) { - this->construct(std::move(*rhs)); - } - } - - // [optional.dtor], destructor, trivial if T is trivially destructible. - ~optional() = default; - - // [optional.assign], assignment - - // Assignment from nullopt: opt = nullopt - optional& operator=(nullopt_t) noexcept { - this->destruct(); - return *this; - } - - // Copy assigment, standard semantics. - optional& operator=(const optional& src) = default; - - // Move assignment, standard semantics. - optional& operator=(optional&& src) = default; - - // Value assignment - template < - typename U = T, - typename = typename std::enable_if< - !std::is_same, typename std::decay::type>::value && - (!std::is_scalar::value || - !std::is_same::type>::value) && - std::is_constructible::value && - std::is_assignable::value>::type> - optional& operator=(U&& v) { - this->assign(std::forward(v)); - return *this; - } - - template ::value && - std::is_assignable::value && - !internal_optional:: - is_constructible_convertible_assignable_from_optional< - T, U>::value>::type> - optional& operator=(const optional& rhs) { - if (rhs) { - this->assign(*rhs); - } else { - this->destruct(); - } - return *this; - } - - template ::value && - std::is_assignable::value && - !internal_optional:: - is_constructible_convertible_assignable_from_optional< - T, U>::value>::type> - optional& operator=(optional&& rhs) { - if (rhs) { - this->assign(std::move(*rhs)); - } else { - this->destruct(); - } - return *this; - } - - // [optional.mod], modifiers - // Destroys the inner T value if one is present. - void reset() noexcept { this->destruct(); } - - // Emplace reconstruction. (Re)constructs the underlying T in-place with the - // given arguments forwarded: - // - // optional opt; - // opt.emplace(arg1,arg2,arg3); (Constructs Foo(arg1,arg2,arg3)) - // - // If the optional is non-empty, and the `args` refer to subobjects of the - // current object, then behavior is undefined. This is because the current - // object will be destructed before the new object is constructed with `args`. - // - template ::value>::type> - void emplace(Args&&... args) { - this->destruct(); - this->construct(std::forward(args)...); - } - - // Emplace reconstruction with initializer-list. See immediately above. - template &, Args&&...>::value>::type> - void emplace(std::initializer_list il, Args&&... args) { - this->destruct(); - this->construct(il, std::forward(args)...); - } - - // [optional.swap], swap - // Swap, standard semantics. - void swap(optional& rhs) noexcept( - std::is_nothrow_move_constructible::value&& - std::is_trivial::value) { - if (*this) { - if (rhs) { - using std::swap; - swap(**this, *rhs); - } else { - rhs.construct(std::move(**this)); - this->destruct(); - } - } else { - if (rhs) { - this->construct(std::move(*rhs)); - rhs.destruct(); - } else { - // no effect (swap(disengaged, disengaged)) - } - } - } - - // [optional.observe], observers - // You may use `*opt`, and `opt->m`, to access the underlying T value and T's - // member `m`, respectively. If the optional is empty, behavior is - // undefined. - constexpr const T* operator->() const { return this->pointer(); } - T* operator->() { - assert(this->engaged_); - return this->pointer(); - } - constexpr const T& operator*() const & { return reference(); } - T& operator*() & { - assert(this->engaged_); - return reference(); - } - constexpr const T&& operator*() const && { return std::move(reference()); } - T&& operator*() && { - assert(this->engaged_); - return std::move(reference()); - } - - // In a bool context an optional will return false if and only if it is - // empty. - // - // if (opt) { - // // do something with opt.value(); - // } else { - // // opt is empty - // } - // - constexpr explicit operator bool() const noexcept { return this->engaged_; } - - // Returns false if and only if *this is empty. - constexpr bool has_value() const noexcept { return this->engaged_; } - - // Use `opt.value()` to get a reference to underlying value. The constness - // and lvalue/rvalue-ness of `opt` is preserved to the view of the T - // subobject. - const T& value() const & { - if (!*this) - throw_bad_optional_access(); - return reference(); - } - T& value() & { - if (!*this) - throw_bad_optional_access(); - return reference(); - } - T&& value() && { // NOLINT(build/c++11) - if (!*this) - throw_bad_optional_access(); - return std::move(reference()); - } - const T&& value() const && { // NOLINT(build/c++11) - if (!*this) - throw_bad_optional_access(); - return std::move(reference()); - } - - // Use `opt.value_or(val)` to get either the value of T or the given default - // `val` in the empty case. - template - constexpr T value_or(U&& v) const & { - return static_cast(*this) ? **this - : static_cast(std::forward(v)); - } - template - T value_or(U&& v) && { // NOLINT(build/c++11) - return static_cast(*this) ? std::move(**this) - : static_cast(std::forward(v)); - } - - private: - // Private accessors for internal storage viewed as reference to T. - constexpr const T& reference() const { return *this->pointer(); } - T& reference() { return *(this->pointer()); } - - // T constaint checks. You can't have an optional of nullopt_t, in_place_t or - // a reference. - static_assert( - !std::is_same::type>::value, - "optional is not allowed."); - static_assert( - !std::is_same::type>::value, - "optional is not allowed."); - static_assert(!std::is_reference::value, - "optional is not allowed."); -}; - -// [optional.specalg] -// Swap, standard semantics. -// This function shall not participate in overload resolution unless -// is_move_constructible_v is true and is_swappable_v is true. -// NOTE: we assume is_swappable is always true. There will be a compiling error -// if T is actually not Swappable. -template ::value, - bool>::type = false> -void swap(optional& a, optional& b) noexcept(noexcept(a.swap(b))) { - a.swap(b); -} - -// NOTE: make_optional cannot be constexpr in C++11 because the copy/move -// constructor is not constexpr and we don't have guaranteed copy elision -// util C++17. But they are still declared constexpr for consistency with -// the standard. - -// make_optional(v) creates a non-empty optional where the type T is deduced -// from v. Can also be explicitly instantiated as make_optional(v). -template -constexpr optional::type> make_optional(T&& v) { - return optional::type>(std::forward(v)); -} - -template -constexpr optional make_optional(Args&&... args) { - return optional(in_place_t(), internal_optional::forward(args)...); -} - -template -constexpr optional make_optional(std::initializer_list il, - Args&&... args) { - return optional(in_place_t(), il, - internal_optional::forward(args)...); -} - -// Relational operators. Empty optionals are considered equal to each -// other and less than non-empty optionals. Supports relations between -// optional and optional, between optional and T, and between -// optional and nullopt. -// Note: We're careful to support T having non-bool relationals. - -// Relational operators [optional.relops] -// The C++17 (N4606) "Returns:" statements are translated into code -// in an obvious way here, and the original text retained as function docs. -// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; -// otherwise *x == *y. -template -constexpr bool operator==(const optional& x, const optional& y) { - return static_cast(x) != static_cast(y) - ? false - : static_cast(x) == false ? true : *x == *y; -} -// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; -// otherwise *x != *y. -template -constexpr bool operator!=(const optional& x, const optional& y) { - return static_cast(x) != static_cast(y) - ? true - : static_cast(x) == false ? false : *x != *y; -} -// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y. -template -constexpr bool operator<(const optional& x, const optional& y) { - return !y ? false : !x ? true : *x < *y; -} -// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y. -template -constexpr bool operator>(const optional& x, const optional& y) { - return !x ? false : !y ? true : *x > *y; -} -// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y. -template -constexpr bool operator<=(const optional& x, const optional& y) { - return !x ? true : !y ? false : *x <= *y; -} -// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y. -template -constexpr bool operator>=(const optional& x, const optional& y) { - return !y ? true : !x ? false : *x >= *y; -} - -// Comparison with nullopt [optional.nullops] -// The C++17 (N4606) "Returns:" statements are used directly here. -template -constexpr bool operator==(const optional& x, nullopt_t) noexcept { - return !x; -} -template -constexpr bool operator==(nullopt_t, const optional& x) noexcept { - return !x; -} -template -constexpr bool operator!=(const optional& x, nullopt_t) noexcept { - return static_cast(x); -} -template -constexpr bool operator!=(nullopt_t, const optional& x) noexcept { - return static_cast(x); -} -template -constexpr bool operator<(const optional& x, nullopt_t) noexcept { - return false; -} -template -constexpr bool operator<(nullopt_t, const optional& x) noexcept { - return static_cast(x); -} -template -constexpr bool operator<=(const optional& x, nullopt_t) noexcept { - return !x; -} -template -constexpr bool operator<=(nullopt_t, const optional& x) noexcept { - return true; -} -template -constexpr bool operator>(const optional& x, nullopt_t) noexcept { - return static_cast(x); -} -template -constexpr bool operator>(nullopt_t, const optional& x) noexcept { - return false; -} -template -constexpr bool operator>=(const optional& x, nullopt_t) noexcept { - return true; -} -template -constexpr bool operator>=(nullopt_t, const optional& x) noexcept { - return !x; -} - -// Comparison with T [optional.comp_with_t] -// The C++17 (N4606) "Equivalent to:" statements are used directly here. -template -constexpr bool operator==(const optional& x, const T& v) { - return static_cast(x) ? *x == v : false; -} -template -constexpr bool operator==(const T& v, const optional& x) { - return static_cast(x) ? v == *x : false; -} -template -constexpr bool operator!=(const optional& x, const T& v) { - return static_cast(x) ? *x != v : true; -} -template -constexpr bool operator!=(const T& v, const optional& x) { - return static_cast(x) ? v != *x : true; -} -template -constexpr bool operator<(const optional& x, const T& v) { - return static_cast(x) ? *x < v : true; -} -template -constexpr bool operator<(const T& v, const optional& x) { - return static_cast(x) ? v < *x : false; -} -template -constexpr bool operator<=(const optional& x, const T& v) { - return static_cast(x) ? *x <= v : true; -} -template -constexpr bool operator<=(const T& v, const optional& x) { - return static_cast(x) ? v <= *x : false; -} -template -constexpr bool operator>(const optional& x, const T& v) { - return static_cast(x) ? *x > v : false; -} -template -constexpr bool operator>(const T& v, const optional& x) { - return static_cast(x) ? v > *x : true; -} -template -constexpr bool operator>=(const optional& x, const T& v) { - return static_cast(x) ? *x >= v : false; -} -template -constexpr bool operator>=(const T& v, const optional& x) { - return static_cast(x) ? v >= *x : true; -} - -} // namespace gtl - -namespace std { - -template -struct hash<::gtl::optional> { - size_t operator()(const ::gtl::optional& opt) const { - if (opt) { - return hash()(*opt); - } else { - return static_cast(0x297814aaad196e6dULL); - } - } -}; - -using ::gtl::optional; -using ::gtl::bad_optional_access; -using ::gtl::nullopt_t; -using ::gtl::nullopt; -using ::gtl::make_optional; -} // namespace std - -#endif diff --git a/Source/Core/Common/Compat/variant b/Source/Core/Common/Compat/variant deleted file mode 100644 index 45d8b81d15..0000000000 --- a/Source/Core/Common/Compat/variant +++ /dev/null @@ -1,2523 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#if __cplusplus >= 201703L && __has_include_next() -#include_next -#else -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -/* - variant synopsis - -namespace std { - - // 20.7.2, class template variant - template - class variant { - public: - - // 20.7.2.1, constructors - constexpr variant() noexcept(see below); - variant(const variant&); - variant(variant&&) noexcept(see below); - - template constexpr variant(T&&) noexcept(see below); - - template - constexpr explicit variant(in_place_type_t, Args&&...); - - template - constexpr explicit variant( - in_place_type_t, initializer_list, Args&&...); - - template - constexpr explicit variant(in_place_index_t, Args&&...); - - template - constexpr explicit variant( - in_place_index_t, initializer_list, Args&&...); - - // 20.7.2.2, destructor - ~variant(); - - // 20.7.2.3, assignment - variant& operator=(const variant&); - variant& operator=(variant&&) noexcept(see below); - - template variant& operator=(T&&) noexcept(see below); - - // 20.7.2.4, modifiers - template - T& emplace(Args&&...); - - template - T& emplace(initializer_list, Args&&...); - - template - variant_alternative& emplace(Args&&...); - - template - variant_alternative& emplace(initializer_list, Args&&...); - - // 20.7.2.5, value status - constexpr bool valueless_by_exception() const noexcept; - constexpr size_t index() const noexcept; - - // 20.7.2.6, swap - void swap(variant&) noexcept(see below); - }; - - // 20.7.3, variant helper classes - template struct variant_size; // undefined - - template - constexpr size_t variant_size_v = variant_size::value; - - template struct variant_size; - template struct variant_size; - template struct variant_size; - - template - struct variant_size>; - - template struct variant_alternative; // undefined - - template - using variant_alternative_t = typename variant_alternative::type; - - template struct variant_alternative; - template struct variant_alternative; - template struct variant_alternative; - - template - struct variant_alternative>; - - constexpr size_t variant_npos = -1; - - // 20.7.4, value access - template - constexpr bool holds_alternative(const variant&) noexcept; - - template - constexpr variant_alternative_t>& - get(variant&); - - template - constexpr variant_alternative_t>&& - get(variant&&); - - template - constexpr variant_alternative_t> const& - get(const variant&); - - template - constexpr variant_alternative_t> const&& - get(const variant&&); - - template - constexpr T& get(variant&); - - template - constexpr T&& get(variant&&); - - template - constexpr const T& get(const variant&); - - template - constexpr const T&& get(const variant&&); - - template - constexpr add_pointer_t>> - get_if(variant*) noexcept; - - template - constexpr add_pointer_t>> - get_if(const variant*) noexcept; - - template - constexpr add_pointer_t - get_if(variant*) noexcept; - - template - constexpr add_pointer_t - get_if(const variant*) noexcept; - - // 20.7.5, relational operators - template - constexpr bool operator==(const variant&, const variant&); - - template - constexpr bool operator!=(const variant&, const variant&); - - template - constexpr bool operator<(const variant&, const variant&); - - template - constexpr bool operator>(const variant&, const variant&); - - template - constexpr bool operator<=(const variant&, const variant&); - - template - constexpr bool operator>=(const variant&, const variant&); - - // 20.7.6, visitation - template - constexpr see below visit(Visitor&&, Variants&&...); - - // 20.7.7, class monostate - struct monostate; - - // 20.7.8, monostate relational operators - constexpr bool operator<(monostate, monostate) noexcept; - constexpr bool operator>(monostate, monostate) noexcept; - constexpr bool operator<=(monostate, monostate) noexcept; - constexpr bool operator>=(monostate, monostate) noexcept; - constexpr bool operator==(monostate, monostate) noexcept; - constexpr bool operator!=(monostate, monostate) noexcept; - - // 20.7.9, specialized algorithms - template - void swap(variant&, variant&) noexcept(see below); - - // 20.7.10, class bad_variant_access - class bad_variant_access; - - // 20.7.11, hash support - template struct hash; - template struct hash>; - template <> struct hash; - -} // namespace std - -*/ - -#include -#include -#include -#include -#include -#include -#include - -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#ifndef MPARK_CONFIG_HPP -#define MPARK_CONFIG_HPP - -// MSVC 2015 Update 3. -#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) -#error "MPark.Variant requires C++11 support." -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#ifndef __has_include -#define __has_include(x) 0 -#endif - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#if __has_builtin(__builtin_addressof) || (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) -#define MPARK_BUILTIN_ADDRESSOF -#endif - -#if __has_builtin(__builtin_unreachable) -#define MPARK_BUILTIN_UNREACHABLE -#endif - -#if __has_builtin(__type_pack_element) -#define MPARK_TYPE_PACK_ELEMENT -#endif - -#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 -#define MPARK_CPP14_CONSTEXPR -#endif - -#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ - (defined(_MSC_VER) && defined(_CPPUNWIND)) -#define MPARK_EXCEPTIONS -#endif - -#if defined(__cpp_generic_lambdas) || defined(_MSC_VER) -#define MPARK_GENERIC_LAMBDAS -#endif - -#if defined(__cpp_lib_integer_sequence) -#define MPARK_INTEGER_SEQUENCE -#endif - -#if defined(__cpp_return_type_deduction) || defined(_MSC_VER) -#define MPARK_RETURN_TYPE_DEDUCTION -#endif - -#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) -#define MPARK_TRANSPARENT_OPERATORS -#endif - -#if defined(__cpp_variable_templates) || defined(_MSC_VER) -#define MPARK_VARIABLE_TEMPLATES -#endif - -#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 -#define MPARK_TRIVIALITY_TYPE_TRAITS -#endif - -#endif // MPARK_CONFIG_HPP - -#include "in_place.h" - -// MPark.Variant -// -// Copyright Michael Park, 2015-2017 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -#ifndef MPARK_LIB_HPP -#define MPARK_LIB_HPP - -#include -#include -#include -#include - -#define RETURN(...) \ - noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; } - -namespace mpark -{ -namespace lib -{ -template -struct identity -{ - using type = T; -}; - -inline namespace cpp14 -{ -template -struct array -{ - constexpr const T& operator[](std::size_t index) const { return data[index]; } - - T data[N == 0 ? 1 : N]; -}; - -template -using add_pointer_t = typename std::add_pointer::type; - -template -using common_type_t = typename std::common_type::type; - -template -using decay_t = typename std::decay::type; - -template -using enable_if_t = typename std::enable_if::type; - -template -using remove_const_t = typename std::remove_const::type; - -template -using remove_reference_t = typename std::remove_reference::type; - -template -inline constexpr T&& forward(remove_reference_t& t) noexcept -{ - return static_cast(t); -} - -template -inline constexpr T&& forward(remove_reference_t&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "can not forward an rvalue as an lvalue"); - return static_cast(t); -} - -template -inline constexpr remove_reference_t&& move(T&& t) noexcept -{ - return static_cast&&>(t); -} - -#ifdef MPARK_INTEGER_SEQUENCE -using std::index_sequence; -using std::index_sequence_for; -using std::integer_sequence; -using std::make_index_sequence; -#else -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept { return sizeof...(Is); } -}; - -template -using index_sequence = integer_sequence; - -template -struct make_index_sequence_concat; - -template -struct make_index_sequence_concat, index_sequence> - : identity> -{ -}; - -template -struct make_index_sequence_impl; - -template -using make_index_sequence = typename make_index_sequence_impl::type; - -template -struct make_index_sequence_impl - : make_index_sequence_concat, make_index_sequence> -{ -}; - -template <> -struct make_index_sequence_impl<0> : identity> -{ -}; - -template <> -struct make_index_sequence_impl<1> : identity> -{ -}; - -template -using index_sequence_for = make_index_sequence; -#endif - -// -#ifdef MPARK_TRANSPARENT_OPERATORS -using equal_to = std::equal_to<>; -#else -struct equal_to -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) == lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using not_equal_to = std::not_equal_to<>; -#else -struct not_equal_to -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) != lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using less = std::less<>; -#else -struct less -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) < lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using greater = std::greater<>; -#else -struct greater -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) > lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using less_equal = std::less_equal<>; -#else -struct less_equal -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) <= lib::forward(rhs)) -}; -#endif - -#ifdef MPARK_TRANSPARENT_OPERATORS -using greater_equal = std::greater_equal<>; -#else -struct greater_equal -{ - template - inline constexpr auto operator()(Lhs&& lhs, Rhs&& rhs) const - RETURN(lib::forward(lhs) >= lib::forward(rhs)) -}; -#endif -} // namespace cpp14 - -inline namespace cpp17 -{ -// -template -using bool_constant = std::integral_constant; - -template -struct voider : identity -{ -}; - -template -using void_t = typename voider::type; - -namespace detail -{ -namespace swappable -{ -using std::swap; - -template -struct is_swappable -{ -private: - template (), std::declval()))> - inline static std::true_type test(int); - - template - inline static std::false_type test(...); - -public: - static constexpr bool value = decltype(test(0))::value; -}; - -template ::value> -struct is_nothrow_swappable -{ - static constexpr bool value = noexcept(swap(std::declval(), std::declval())); -}; - -template -struct is_nothrow_swappable : std::false_type -{ -}; - -} // namespace swappable -} // namespace detail - -using detail::swappable::is_nothrow_swappable; -using detail::swappable::is_swappable; - -// -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif -template -inline constexpr auto invoke(F&& f, As&&... as) RETURN(lib::forward(f)(lib::forward(as)...)) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - template - inline constexpr auto invoke(T B::*pmv, D&& d) RETURN(lib::forward(d).*pmv) - - template - inline constexpr auto invoke(Pmv pmv, Ptr&& ptr) RETURN((*lib::forward(ptr)).*pmv) - - template - inline constexpr auto invoke(T B::*pmf, D&& d, As&&... as) - RETURN((lib::forward(d).*pmf)(lib::forward(as)...)) - - template - inline constexpr auto invoke(Pmf pmf, Ptr&& ptr, As&&... as) - RETURN(((*lib::forward(ptr)).*pmf)(lib::forward(as)...)) - - namespace detail -{ - template - struct invoke_result - { - }; - - template - struct invoke_result(), std::declval()...))>, F, - Args...> - : identity(), std::declval()...))> - { - }; - -} // namespace detail - -template -using invoke_result = detail::invoke_result; - -template -using invoke_result_t = typename invoke_result::type; - -namespace detail -{ -template -struct is_invocable : std::false_type -{ -}; - -template -struct is_invocable>, F, Args...> : std::true_type -{ -}; - -template -struct is_invocable_r : std::false_type -{ -}; - -template -struct is_invocable_r>, R, F, Args...> - : std::is_convertible, R> -{ -}; - -} // namespace detail - -template -using is_invocable = detail::is_invocable; - -template -using is_invocable_r = detail::is_invocable_r; - -// -#ifdef MPARK_BUILTIN_ADDRESSOF -template -inline constexpr T* addressof(T& arg) -{ - return __builtin_addressof(arg); -} -#else -namespace detail -{ -namespace has_addressof_impl -{ -struct fail; - -template -inline fail operator&(T&&); - -template -inline static constexpr bool impl() -{ - return (std::is_class::value || std::is_union::value) && - !std::is_same()), fail>::value; -} - -} // namespace has_addressof_impl - -template -using has_addressof = bool_constant()>; - -template -inline constexpr T* addressof(T& arg, std::true_type) -{ - return std::addressof(arg); -} - -template -inline constexpr T* addressof(T& arg, std::false_type) -{ - return &arg; -} - -} // namespace detail - -template -inline constexpr T* addressof(T& arg) -{ - return detail::addressof(arg, detail::has_addressof{}); -} -#endif - -template -inline constexpr T* addressof(const T&&) = delete; - -} // namespace cpp17 - -template -struct remove_all_extents : identity -{ -}; - -template -struct remove_all_extents> : remove_all_extents -{ -}; - -template -using remove_all_extents_t = typename remove_all_extents::type; - -template -using size_constant = std::integral_constant; - -template -struct indexed_type : size_constant, identity -{ -}; - -template -using all = std::is_same, integer_sequence>; - -#ifdef MPARK_TYPE_PACK_ELEMENT -template -using type_pack_element_t = __type_pack_element; -#else -template -struct type_pack_element_impl -{ -private: - template - struct set; - - template - struct set> : indexed_type... - { - }; - - template - inline static std::enable_if impl(indexed_type); - - inline static std::enable_if impl(...); - -public: - using type = decltype(impl(set>{})); -}; - -template -using type_pack_element = typename type_pack_element_impl::type; - -template -using type_pack_element_t = typename type_pack_element::type; -#endif - -#ifdef MPARK_TRIVIALITY_TYPE_TRAITS -using std::is_trivially_copy_assignable; -using std::is_trivially_copy_constructible; -using std::is_trivially_move_assignable; -using std::is_trivially_move_constructible; -#else -template -struct is_trivially_copy_constructible - : bool_constant::value&& __has_trivial_copy(T)> -{ -}; - -template -struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> -{ -}; - -template -struct is_trivially_copy_assignable - : bool_constant::value&& __has_trivial_assign(T)> -{ -}; - -template -struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> -{ -}; -#endif - -template -struct dependent_type : T -{ -}; - -template -struct push_back; - -template -using push_back_t = typename push_back::type; - -template -struct push_back, J> -{ - using type = index_sequence; -}; - -} // namespace lib -} // namespace mpark - -#undef RETURN - -#endif // MPARK_LIB_HPP - -namespace mpark -{ - -#ifdef MPARK_RETURN_TYPE_DEDUCTION - -#define AUTO auto -#define AUTO_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } - -#define AUTO_REFREF auto&& -#define AUTO_REFREF_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } - -#define DECLTYPE_AUTO decltype(auto) -#define DECLTYPE_AUTO_RETURN(...) \ - { \ - return __VA_ARGS__; \ - } - -#else - -#define AUTO auto -#define AUTO_RETURN(...) \ - ->lib::decay_t { return __VA_ARGS__; } - -#define AUTO_REFREF auto -#define AUTO_REFREF_RETURN(...) \ - ->decltype((__VA_ARGS__)) \ - { \ - static_assert(std::is_reference::value, ""); \ - return __VA_ARGS__; \ - } - -#define DECLTYPE_AUTO auto -#define DECLTYPE_AUTO_RETURN(...) \ - ->decltype(__VA_ARGS__) { return __VA_ARGS__; } - -#endif - -class bad_variant_access : public std::exception -{ -public: - virtual const char* what() const noexcept { return "bad_variant_access"; } -}; - -[[noreturn]] inline void throw_bad_variant_access() -{ -#ifdef MPARK_EXCEPTIONS - throw bad_variant_access{}; -#else - std::terminate(); -#ifdef MPARK_BUILTIN_UNREACHABLE - __builtin_unreachable(); -#endif -#endif -} - -template -class variant; - -template -struct variant_size; - -#ifdef MPARK_VARIABLE_TEMPLATES -template -constexpr std::size_t variant_size_v = variant_size::value; -#endif - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size : variant_size -{ -}; - -template -struct variant_size> : lib::size_constant -{ -}; - -template -struct variant_alternative; - -template -using variant_alternative_t = typename variant_alternative::type; - -template -struct variant_alternative : std::add_const> -{ -}; - -template -struct variant_alternative : std::add_volatile> -{ -}; - -template -struct variant_alternative : std::add_cv> -{ -}; - -template -struct variant_alternative> -{ - static_assert(I < sizeof...(Ts), "Index out of bounds in std::variant_alternative<>"); - using type = lib::type_pack_element_t; -}; - -constexpr std::size_t variant_npos = static_cast(-1); - -namespace detail -{ -constexpr std::size_t not_found = static_cast(-1); -constexpr std::size_t ambiguous = static_cast(-2); - -#ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr std::size_t find_index() -{ - constexpr lib::array matches = {{std::is_same::value...}}; - std::size_t result = not_found; - for (std::size_t i = 0; i < sizeof...(Ts); ++i) - { - if (matches[i]) - { - if (result != not_found) - { - return ambiguous; - } - result = i; - } - } - return result; -} -#else -inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t) -{ - return result; -} - -template -inline constexpr std::size_t find_index_impl(std::size_t result, std::size_t idx, bool b, Bs... bs) -{ - return b ? (result != not_found ? ambiguous : find_index_impl(idx, idx + 1, bs...)) : - find_index_impl(result, idx + 1, bs...); -} - -template -inline constexpr std::size_t find_index() -{ - return find_index_impl(not_found, 0, std::is_same::value...); -} -#endif - -template -using find_index_sfinae_impl = - lib::enable_if_t>; - -template -using find_index_sfinae = find_index_sfinae_impl()>; - -template -struct find_index_checked_impl : lib::size_constant -{ - static_assert(I != not_found, "the specified type is not found."); - static_assert(I != ambiguous, "the specified type is ambiguous."); -}; - -template -using find_index_checked = find_index_checked_impl()>; - -struct valueless_t -{ -}; - -enum class Trait -{ - TriviallyAvailable, - Available, - Unavailable -}; - -template class IsTriviallyAvailable, - template class IsAvailable> -inline constexpr Trait trait() -{ - return IsTriviallyAvailable::value ? - Trait::TriviallyAvailable : - IsAvailable::value ? Trait::Available : Trait::Unavailable; -} - -#ifdef MPARK_CPP14_CONSTEXPR -template -inline constexpr Trait common_trait(Traits... traits) -{ - Trait result = Trait::TriviallyAvailable; - for (Trait t : {traits...}) - { - if (static_cast(t) > static_cast(result)) - { - result = t; - } - } - return result; -} -#else -inline constexpr Trait common_trait_impl(Trait result) -{ - return result; -} - -template -inline constexpr Trait common_trait_impl(Trait result, Trait t, Traits... ts) -{ - return static_cast(t) > static_cast(result) ? common_trait_impl(t, ts...) : - common_trait_impl(result, ts...); -} - -template -inline constexpr Trait common_trait(Traits... ts) -{ - return common_trait_impl(Trait::TriviallyAvailable, ts...); -} -#endif - -template -struct traits -{ - static constexpr Trait copy_constructible_trait = common_trait( - trait()...); - - static constexpr Trait move_constructible_trait = common_trait( - trait()...); - - static constexpr Trait copy_assignable_trait = - common_trait(copy_constructible_trait, - trait()...); - - static constexpr Trait move_assignable_trait = - common_trait(move_constructible_trait, - trait()...); - - static constexpr Trait destructible_trait = - common_trait(trait()...); -}; - -namespace access -{ -struct recursive_union -{ -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto&& get_alt(V&& v, in_place_index_t<0>) - { - return lib::forward(v).head_; - } - - template - inline static constexpr auto&& get_alt(V&& v, in_place_index_t) - { - return get_alt(lib::forward(v).tail_, in_place_index_t{}); - } -#else - template - struct get_alt_impl - { - template - inline constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) - }; - - template - struct get_alt_impl<0, Dummy> - { - template - inline constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(lib::forward(v).head_) - }; - - template - inline static constexpr AUTO_REFREF get_alt(V&& v, in_place_index_t) - AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) -#endif -}; - -struct base -{ - template - inline static constexpr AUTO_REFREF get_alt(V&& v) - AUTO_REFREF_RETURN(recursive_union::get_alt(data(lib::forward(v)), in_place_index_t{})) -}; - -struct variant -{ - template - inline static constexpr AUTO_REFREF get_alt(V&& v) - AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) -}; - -} // namespace access - -namespace visitation -{ -struct base -{ - template - inline static constexpr const T& at(const T& elem) - { - return elem; - } - - template - inline static constexpr const lib::remove_all_extents_t& at(const lib::array& elems, - std::size_t i, Is... is) - { - return at(elems[i], is...); - } - - template - inline static constexpr int visit_visitor_return_type_check() - { - static_assert(lib::all::value...>::value, - "`mpark::visit` requires the visitor to have a single " - "return type."); - return 0; - } - - template - inline static constexpr lib::array...>, sizeof...(Fs)> - make_farray(Fs&&... fs) - { - using result = lib::array...>, sizeof...(Fs)>; - return visit_visitor_return_type_check...>(), - result{{lib::forward(fs)...}}; - } - - template - struct dispatcher - { - template - struct impl - { - inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs) - DECLTYPE_AUTO_RETURN(lib::invoke(static_cast(f), - access::base::get_alt(static_cast(vs))...)) - }; - }; - - template - inline static constexpr AUTO make_dispatch(lib::index_sequence) - AUTO_RETURN(&dispatcher::template impl::dispatch) - - template - inline static constexpr AUTO make_fdiagonal_impl() AUTO_RETURN( - make_dispatch(lib::index_sequence::value...>{})) - - template - inline static constexpr AUTO make_fdiagonal_impl(lib::index_sequence) - AUTO_RETURN(make_farray(make_fdiagonal_impl()...)) - - template - inline static constexpr /* auto * */ auto make_fdiagonal() - -> decltype(make_fdiagonal_impl( - lib::make_index_sequence::size()>{})) - { - static_assert(lib::all<(lib::decay_t::size() == lib::decay_t::size())...>::value, - "all of the variants must be the same size."); - return make_fdiagonal_impl(lib::make_index_sequence::size()>{}); - } - -#ifdef MPARK_RETURN_TYPE_DEDUCTION - template - inline static constexpr auto make_fmatrix_impl(Is is) - { - return make_dispatch(is); - } - - template - inline static constexpr auto make_fmatrix_impl(Is, lib::index_sequence, Ls... ls) - { - return make_farray(make_fmatrix_impl(lib::push_back_t{}, ls...)...); - } - - template - inline static constexpr auto make_fmatrix() - { - return make_fmatrix_impl(lib::index_sequence<>{}, - lib::make_index_sequence::size()>{}...); - } -#else - template - struct make_fmatrix_impl - { - template - struct impl; - - template - struct impl - { - inline constexpr AUTO operator()() const AUTO_RETURN(make_dispatch(Is{})) - }; - - template - struct impl, Ls...> - { - inline constexpr AUTO operator()() const - AUTO_RETURN(make_farray(impl, Ls...>{}()...)) - }; - }; - - template - inline static constexpr AUTO make_fmatrix() - AUTO_RETURN(typename make_fmatrix_impl::template impl< - lib::index_sequence<>, lib::make_index_sequence::size()>...>{}()) -#endif -}; // namespace base - -template -using FDiagonal = decltype(base::make_fdiagonal()); - -template -struct fdiagonal -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4268) -#endif - static constexpr FDiagonal value = base::make_fdiagonal(); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -}; - -template -constexpr FDiagonal fdiagonal::value; - -template -using FMatrix = decltype(base::make_fmatrix()); - -template -struct fmatrix -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4268) -#endif - static constexpr FMatrix value = base::make_fmatrix(); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -}; - -template -constexpr FMatrix fmatrix::value; - -struct alt -{ - template - inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, Visitor&& visitor, - Vs&&... vs) - DECLTYPE_AUTO_RETURN( - base::at(fdiagonal(vs)))...>::value, - index)(lib::forward(visitor), as_base(lib::forward(vs))...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_alt(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - base::at(fmatrix(vs)))...>::value, - vs.index()...)(lib::forward(visitor), as_base(lib::forward(vs))...)) -}; - -struct variant -{ -private: - template - struct visit_exhaustive_visitor_check - { - static_assert(lib::is_invocable::value, - "`mpark::visit` requires the visitor to be exhaustive."); - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif - inline constexpr DECLTYPE_AUTO operator()(Visitor&& visitor, Values&&... values) const - DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), - lib::forward(values)...)) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - }; - - template - struct value_visitor - { - Visitor&& visitor_; - - template - inline constexpr DECLTYPE_AUTO operator()(Alts&&... alts) const DECLTYPE_AUTO_RETURN( - visit_exhaustive_visitor_check(alts).value))...>{}( - lib::forward(visitor_), lib::forward(alts).value...)) - }; - - template - inline static constexpr AUTO make_value_visitor(Visitor&& visitor) - AUTO_RETURN(value_visitor{lib::forward(visitor)}) - - public - : template - inline static constexpr DECLTYPE_AUTO - visit_alt_at(std::size_t index, Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(alt::visit_alt_at(index, lib::forward(visitor), - lib::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO visit_alt(Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), - lib::forward(vs).impl_...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_value_at(std::size_t index, Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(visit_alt_at(index, - make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) - - template - inline static constexpr DECLTYPE_AUTO - visit_value(Visitor&& visitor, Vs&&... vs) - DECLTYPE_AUTO_RETURN(visit_alt(make_value_visitor(lib::forward(visitor)), - lib::forward(vs)...)) -}; - -} // namespace visitation - -template -struct alt -{ - using value_type = T; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - template - inline explicit constexpr alt(in_place_t, Args&&... args) : value(lib::forward(args)...) - { - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - T value; -}; - -template -union recursive_union; - -template -union recursive_union -{ -}; - -#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ - template \ - union recursive_union \ - { \ - public: \ - inline explicit constexpr recursive_union(valueless_t) noexcept : dummy_{} {} \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t<0>, Args&&... args) \ - : head_(in_place_t{}, lib::forward(args)...) \ - { \ - } \ - \ - template \ - inline explicit constexpr recursive_union(in_place_index_t, Args&&... args) \ - : tail_(in_place_index_t{}, lib::forward(args)...) \ - { \ - } \ - \ - recursive_union(const recursive_union&) = default; \ - recursive_union(recursive_union&&) = default; \ - \ - destructor \ - \ - recursive_union& \ - operator=(const recursive_union&) = default; \ - recursive_union& operator=(recursive_union&&) = default; \ - \ - private: \ - char dummy_; \ - alt head_; \ - recursive_union tail_; \ - \ - friend struct access::recursive_union; \ - } - -MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, ~recursive_union() = default;); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, ~recursive_union(){}); -MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, ~recursive_union() = delete;); - -#undef MPARK_VARIANT_RECURSIVE_UNION - -using index_t = unsigned int; - -template -class base -{ -public: - inline explicit constexpr base(valueless_t tag) noexcept - : data_(tag), index_(static_cast(-1)) - { - } - - template - inline explicit constexpr base(in_place_index_t, Args&&... args) - : data_(in_place_index_t{}, lib::forward(args)...), index_(I) - { - } - - inline constexpr bool valueless_by_exception() const noexcept - { - return index_ == static_cast(-1); - } - - inline constexpr std::size_t index() const noexcept - { - return valueless_by_exception() ? variant_npos : index_; - } - -protected: - using data_t = recursive_union; - - friend inline constexpr base& as_base(base& b) { return b; } - friend inline constexpr const base& as_base(const base& b) { return b; } - friend inline constexpr base&& as_base(base&& b) { return lib::move(b); } - friend inline constexpr const base&& as_base(const base&& b) { return lib::move(b); } - - friend inline constexpr data_t& data(base& b) { return b.data_; } - friend inline constexpr const data_t& data(const base& b) { return b.data_; } - friend inline constexpr data_t&& data(base&& b) { return lib::move(b).data_; } - friend inline constexpr const data_t&& data(const base&& b) { return lib::move(b).data_; } - - inline static constexpr std::size_t size() { return sizeof...(Ts); } - - data_t data_; - index_t index_; - - friend struct access::base; - friend struct visitation::base; -}; - -struct dtor -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4100) -#endif - template - inline void operator()(Alt& alt) const noexcept - { - alt.~Alt(); - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif -}; - -#if defined(_MSC_VER) && _MSC_VER < 1910 -#define INHERITING_CTOR(type, base) \ - template \ - inline explicit constexpr type(Args&&... args) : base(lib::forward(args)...) \ - { \ - } -#else -#define INHERITING_CTOR(type, base) using base::base; -#endif - -template -class destructor; - -#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ - template \ - class destructor, destructible_trait> : public base \ - { \ - using super = base; \ - \ - public: \ - INHERITING_CTOR(destructor, super) \ - using super::operator=; \ - \ - destructor(const destructor&) = default; \ - destructor(destructor&&) = default; \ - definition destructor& operator=(const destructor&) = default; \ - destructor& operator=(destructor&&) = default; \ - \ - protected: \ - destroy \ - } - -MPARK_VARIANT_DESTRUCTOR(Trait::TriviallyAvailable, ~destructor() = default; - , inline void destroy() noexcept { - this->index_ = static_cast(-1); - }); - -MPARK_VARIANT_DESTRUCTOR(Trait::Available, ~destructor() { destroy(); }, - inline void destroy() noexcept { - if (!this->valueless_by_exception()) - { - visitation::alt::visit_alt(dtor{}, *this); - } - this->index_ = static_cast(-1); - }); - -MPARK_VARIANT_DESTRUCTOR(Trait::Unavailable, ~destructor() = delete; - , inline void destroy() noexcept = delete;); - -#undef MPARK_VARIANT_DESTRUCTOR - -template -class constructor : public destructor -{ - using super = destructor; - -public: - INHERITING_CTOR(constructor, super) - using super::operator=; - -protected: -#ifndef MPARK_GENERIC_LAMBDAS - struct ctor - { - template - inline void operator()(LhsAlt& lhs_alt, RhsAlt&& rhs_alt) const - { - constructor::construct_alt(lhs_alt, lib::forward(rhs_alt).value); - } - }; -#endif - - template - inline static T& construct_alt(alt& a, Args&&... args) - { - ::new (static_cast(lib::addressof(a))) - alt(in_place_t{}, lib::forward(args)...); - return a.value; - } - - template - inline static void generic_construct(constructor& lhs, Rhs&& rhs) - { - lhs.destroy(); - if (!rhs.valueless_by_exception()) - { - visitation::alt::visit_alt_at(rhs.index(), -#ifdef MPARK_GENERIC_LAMBDAS - [](auto& lhs_alt, auto&& rhs_alt) { - constructor::construct_alt( - lhs_alt, lib::forward(rhs_alt).value); - } -#else - ctor {} -#endif - , - lhs, lib::forward(rhs)); - lhs.index_ = rhs.index_; - } - } -}; - -template -class move_constructor; - -#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ - template \ - class move_constructor, move_constructible_trait> \ - : public constructor> \ - { \ - using super = constructor>; \ - \ - public: \ - INHERITING_CTOR(move_constructor, super) \ - using super::operator=; \ - \ - move_constructor(const move_constructor&) = default; \ - definition ~move_constructor() = default; \ - move_constructor& operator=(const move_constructor&) = default; \ - move_constructor& operator=(move_constructor&&) = default; \ - } - -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::TriviallyAvailable, - move_constructor(move_constructor&& that) = default;); - -MPARK_VARIANT_MOVE_CONSTRUCTOR( - Trait::Available, move_constructor(move_constructor&& that) noexcept( - lib::all::value...>::value) - : move_constructor(valueless_t{}) { this->generic_construct(*this, lib::move(that)); }); - -MPARK_VARIANT_MOVE_CONSTRUCTOR(Trait::Unavailable, move_constructor(move_constructor&&) = delete;); - -#undef MPARK_VARIANT_MOVE_CONSTRUCTOR - -template -class copy_constructor; - -#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ - template \ - class copy_constructor, copy_constructible_trait> \ - : public move_constructor> \ - { \ - using super = move_constructor>; \ - \ - public: \ - INHERITING_CTOR(copy_constructor, super) \ - using super::operator=; \ - \ - definition copy_constructor(copy_constructor&&) = default; \ - ~copy_constructor() = default; \ - copy_constructor& operator=(const copy_constructor&) = default; \ - copy_constructor& operator=(copy_constructor&&) = default; \ - } - -MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::TriviallyAvailable, - copy_constructor(const copy_constructor& that) = default;); - -MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Available, copy_constructor(const copy_constructor& that) - : copy_constructor(valueless_t{}) { - this->generic_construct(*this, that); - }); - -MPARK_VARIANT_COPY_CONSTRUCTOR(Trait::Unavailable, - copy_constructor(const copy_constructor&) = delete;); - -#undef MPARK_VARIANT_COPY_CONSTRUCTOR - -template -class assignment : public copy_constructor -{ - using super = copy_constructor; - -public: - INHERITING_CTOR(assignment, super) - using super::operator=; - - template - inline /* auto & */ auto emplace(Args&&... args) - -> decltype(this->construct_alt(access::base::get_alt(*this), lib::forward(args)...)) - { - this->destroy(); - auto& result = - this->construct_alt(access::base::get_alt(*this), lib::forward(args)...); - this->index_ = I; - return result; - } - -protected: -#ifndef MPARK_GENERIC_LAMBDAS - template - struct assigner - { - template - inline void operator()(ThisAlt& this_alt, ThatAlt&& that_alt) const - { - self->assign_alt(this_alt, lib::forward(that_alt).value); - } - assignment* self; - }; -#endif - - template - inline void assign_alt(alt& a, Arg&& arg) - { - if (this->index() == I) - { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) -#endif - a.value = lib::forward(arg); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - } - else - { - struct - { - void operator()(std::true_type) const { this_->emplace(lib::forward(arg_)); } - void operator()(std::false_type) const { this_->emplace(T(lib::forward(arg_))); } - assignment* this_; - Arg&& arg_; - } impl{this, lib::forward(arg)}; - impl(lib::bool_constant < std::is_nothrow_constructible::value || - !std::is_nothrow_move_constructible::value > {}); - } - } - - template - inline void generic_assign(That&& that) - { - if (this->valueless_by_exception() && that.valueless_by_exception()) - { - // do nothing. - } - else if (that.valueless_by_exception()) - { - this->destroy(); - } - else - { - visitation::alt::visit_alt_at( - that.index(), -#ifdef MPARK_GENERIC_LAMBDAS - [this](auto& this_alt, auto&& that_alt) { - this->assign_alt(this_alt, lib::forward(that_alt).value); - } -#else - assigner { this } -#endif - , - *this, lib::forward(that)); - } - } -}; - -template -class move_assignment; - -#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ - template \ - class move_assignment, move_assignable_trait> : public assignment> \ - { \ - using super = assignment>; \ - \ - public: \ - INHERITING_CTOR(move_assignment, super) \ - using super::operator=; \ - \ - move_assignment(const move_assignment&) = default; \ - move_assignment(move_assignment&&) = default; \ - ~move_assignment() = default; \ - move_assignment& operator=(const move_assignment&) = default; \ - definition \ - } - -MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::TriviallyAvailable, - move_assignment& operator=(move_assignment&& that) = default;); - -MPARK_VARIANT_MOVE_ASSIGNMENT( - Trait::Available, move_assignment& operator=(move_assignment&& that) noexcept( - lib::all<(std::is_nothrow_move_constructible::value && - std::is_nothrow_move_assignable::value)...>::value) { - this->generic_assign(lib::move(that)); - return *this; - }); - -MPARK_VARIANT_MOVE_ASSIGNMENT(Trait::Unavailable, - move_assignment& operator=(move_assignment&&) = delete;); - -#undef MPARK_VARIANT_MOVE_ASSIGNMENT - -template -class copy_assignment; - -#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ - template \ - class copy_assignment, copy_assignable_trait> \ - : public move_assignment> \ - { \ - using super = move_assignment>; \ - \ - public: \ - INHERITING_CTOR(copy_assignment, super) \ - using super::operator=; \ - \ - copy_assignment(const copy_assignment&) = default; \ - copy_assignment(copy_assignment&&) = default; \ - ~copy_assignment() = default; \ - definition copy_assignment& operator=(copy_assignment&&) = default; \ - } - -MPARK_VARIANT_COPY_ASSIGNMENT(Trait::TriviallyAvailable, - copy_assignment& operator=(const copy_assignment& that) = default;); - -MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Available, - copy_assignment& operator=(const copy_assignment& that) { - this->generic_assign(that); - return *this; - }); - -MPARK_VARIANT_COPY_ASSIGNMENT(Trait::Unavailable, - copy_assignment& operator=(const copy_assignment&) = delete;); - -#undef MPARK_VARIANT_COPY_ASSIGNMENT - -template -class impl : public copy_assignment> -{ - using super = copy_assignment>; - -public: - INHERITING_CTOR(impl, super) - using super::operator=; - - template - inline void assign(Arg&& arg) - { - this->assign_alt(access::base::get_alt(*this), lib::forward(arg)); - } - - inline void swap(impl& that) - { - if (this->valueless_by_exception() && that.valueless_by_exception()) - { - // do nothing. - } - else if (this->index() == that.index()) - { - visitation::alt::visit_alt_at(this->index(), -#ifdef MPARK_GENERIC_LAMBDAS - [](auto& this_alt, auto& that_alt) { - using std::swap; - swap(this_alt.value, that_alt.value); - } -#else - swapper {} -#endif - , - *this, that); - } - else - { - impl* lhs = this; - impl* rhs = lib::addressof(that); - if (lhs->move_nothrow() && !rhs->move_nothrow()) - { - std::swap(lhs, rhs); - } - impl tmp(lib::move(*rhs)); -#ifdef MPARK_EXCEPTIONS - // EXTENSION: When the move construction of `lhs` into `rhs` throws - // and `tmp` is nothrow move constructible then we move `tmp` back - // into `rhs` and provide the strong exception safety guarantee. - try - { - this->generic_construct(*rhs, lib::move(*lhs)); - } - catch (...) - { - if (tmp.move_nothrow()) - { - this->generic_construct(*rhs, lib::move(tmp)); - } - throw; - } -#else - this->generic_construct(*rhs, lib::move(*lhs)); -#endif - this->generic_construct(*lhs, lib::move(tmp)); - } - } - -private: -#ifndef MPARK_GENERIC_LAMBDAS - struct swapper - { - template - inline void operator()(ThisAlt& this_alt, ThatAlt& that_alt) const - { - using std::swap; - swap(this_alt.value, that_alt.value); - } - }; -#endif - - inline constexpr bool move_nothrow() const - { - return this->valueless_by_exception() || - lib::array{ - {std::is_nothrow_move_constructible::value...}}[this->index()]; - } -}; - -template -struct overload_leaf -{ - using F = lib::size_constant (*)(T); - operator F() const { return nullptr; } -}; - -template -struct overload_impl -{ -private: - template - struct impl; - - template - struct impl> : overload_leaf... - { - }; - -public: - using type = impl>; -}; - -template -using overload = typename overload_impl::type; - -template -using best_match = lib::invoke_result_t, T&&>; - -template -struct is_in_place_index : std::false_type -{ -}; - -template -struct is_in_place_index> : std::true_type -{ -}; - -template -struct is_in_place_type : std::false_type -{ -}; - -template -struct is_in_place_type> : std::true_type -{ -}; - -} // namespace detail - -template -class variant -{ - static_assert(0 < sizeof...(Ts), "variant must consist of at least one alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have an array type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a reference type as an alternative."); - - static_assert(lib::all::value...>::value, - "variant can not have a void type as an alternative."); - -public: - template , - lib::enable_if_t::value, int> = 0> - inline constexpr variant() noexcept(std::is_nothrow_default_constructible::value) - : impl_(in_place_index_t<0>{}) - { - } - - variant(const variant&) = default; - variant(variant&&) = default; - - template , - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - lib::enable_if_t::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t::value, int> = 0> - inline constexpr variant(Arg&& arg) noexcept(std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(arg)) - { - } - - template , - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(in_place_index_t, Args&&... args) noexcept( - std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - { - } - - template < - std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, - lib::enable_if_t&, Args...>::value, int> = - 0> - inline explicit constexpr variant( - in_place_index_t, std::initializer_list il, - Args&&... args) noexcept(std::is_nothrow_constructible&, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - { - } - - template ::value, - lib::enable_if_t::value, int> = 0> - inline explicit constexpr variant(in_place_type_t, Args&&... args) noexcept( - std::is_nothrow_constructible::value) - : impl_(in_place_index_t{}, lib::forward(args)...) - { - } - - template ::value, - lib::enable_if_t&, Args...>::value, - int> = 0> - inline explicit constexpr variant( - in_place_type_t, std::initializer_list il, - Args&&... args) noexcept(std::is_nothrow_constructible&, - Args...>::value) - : impl_(in_place_index_t{}, il, lib::forward(args)...) - { - } - - ~variant() = default; - - variant& operator=(const variant&) = default; - variant& operator=(variant&&) = default; - - template < - typename Arg, lib::enable_if_t, variant>::value, int> = 0, - std::size_t I = detail::best_match::value, - typename T = lib::type_pack_element_t, - lib::enable_if_t<(std::is_assignable::value && std::is_constructible::value), - int> = 0> - inline variant& operator=(Arg&& arg) noexcept((std::is_nothrow_assignable::value && - std::is_nothrow_constructible::value)) - { - impl_.template assign(lib::forward(arg)); - return *this; - } - - template , - lib::enable_if_t::value, int> = 0> - inline T& emplace(Args&&... args) - { - return impl_.template emplace(lib::forward(args)...); - } - - template < - std::size_t I, typename Up, typename... Args, typename T = lib::type_pack_element_t, - lib::enable_if_t&, Args...>::value, int> = - 0> - inline T& emplace(std::initializer_list il, Args&&... args) - { - return impl_.template emplace(il, lib::forward(args)...); - } - - template ::value, - lib::enable_if_t::value, int> = 0> - inline T& emplace(Args&&... args) - { - return impl_.template emplace(lib::forward(args)...); - } - - template ::value, - lib::enable_if_t&, Args...>::value, - int> = 0> - inline T& emplace(std::initializer_list il, Args&&... args) - { - return impl_.template emplace(il, lib::forward(args)...); - } - - inline constexpr bool valueless_by_exception() const noexcept - { - return impl_.valueless_by_exception(); - } - - inline constexpr std::size_t index() const noexcept { return impl_.index(); } - - template < - bool Dummy = true, - lib::enable_if_t< - lib::all, Dummy>::value && - lib::dependent_type, Dummy>::value)...>::value, - int> = 0> - inline void - swap(variant& that) noexcept(lib::all<(std::is_nothrow_move_constructible::value && - lib::is_nothrow_swappable::value)...>::value) - { - impl_.swap(that.impl_); - } - -private: - detail::impl impl_; - - friend struct detail::access::variant; - friend struct detail::visitation::variant; -}; - -template -inline constexpr bool holds_alternative(const variant& v) noexcept -{ - return v.index() == I; -} - -template -inline constexpr bool holds_alternative(const variant& v) noexcept -{ - return holds_alternative::value>(v); -} - -namespace detail -{ -template -struct generic_get_impl -{ - constexpr generic_get_impl(int) {} - - constexpr AUTO_REFREF operator()(V&& v) const - AUTO_REFREF_RETURN(access::variant::get_alt(lib::forward(v)).value) -}; - -template -inline constexpr AUTO_REFREF generic_get(V&& v) AUTO_REFREF_RETURN(generic_get_impl( - holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))(lib::forward(v))) -} // namespace detail - -template -inline constexpr variant_alternative_t>& get(variant& v) -{ - return detail::generic_get(v); -} - -template -inline constexpr variant_alternative_t>&& get(variant&& v) -{ - return detail::generic_get(lib::move(v)); -} - -template -inline constexpr const variant_alternative_t>& get(const variant& v) -{ - return detail::generic_get(v); -} - -template -inline constexpr const variant_alternative_t>&& get(const variant&& v) -{ - return detail::generic_get(lib::move(v)); -} - -template -inline constexpr T& get(variant& v) -{ - return get::value>(v); -} - -template -inline constexpr T&& get(variant&& v) -{ - return get::value>(lib::move(v)); -} - -template -inline constexpr const T& get(const variant& v) -{ - return get::value>(v); -} - -template -inline constexpr const T&& get(const variant&& v) -{ - return get::value>(lib::move(v)); -} - -namespace detail -{ -template -inline constexpr /* auto * */ AUTO generic_get_if(V* v) noexcept AUTO_RETURN( - v&& holds_alternative(*v) ? lib::addressof(access::variant::get_alt(*v).value) : nullptr) - -} // namespace detail - -template -inline constexpr lib::add_pointer_t>> -get_if(variant* v) noexcept -{ - return detail::generic_get_if(v); -} - -template -inline constexpr lib::add_pointer_t>> -get_if(const variant* v) noexcept -{ - return detail::generic_get_if(v); -} - -template -inline constexpr lib::add_pointer_t get_if(variant* v) noexcept -{ - return get_if::value>(v); -} - -template -inline constexpr lib::add_pointer_t get_if(const variant* v) noexcept -{ - return get_if::value>(v); -} - -template -inline constexpr bool operator==(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::equal_to; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.index() != rhs.index()) - return false; - if (lhs.valueless_by_exception()) - return true; - return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); -#else - return lhs.index() == rhs.index() && (lhs.valueless_by_exception() || - variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); -#endif -} - -template -inline constexpr bool operator!=(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::not_equal_to; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.index() != rhs.index()) - return true; - if (lhs.valueless_by_exception()) - return false; - return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); -#else - return lhs.index() != rhs.index() || - (!lhs.valueless_by_exception() && - variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); -#endif -} - -template -inline constexpr bool operator<(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::less; -#ifdef MPARK_CPP14_CONSTEXPR - if (rhs.valueless_by_exception()) - return false; - if (lhs.valueless_by_exception()) - return true; - if (lhs.index() < rhs.index()) - return true; - if (lhs.index() > rhs.index()) - return false; - return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); -#else - return !rhs.valueless_by_exception() && - (lhs.valueless_by_exception() || lhs.index() < rhs.index() || - (lhs.index() == rhs.index() && variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); -#endif -} - -template -inline constexpr bool operator>(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::greater; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.valueless_by_exception()) - return false; - if (rhs.valueless_by_exception()) - return true; - if (lhs.index() > rhs.index()) - return true; - if (lhs.index() < rhs.index()) - return false; - return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); -#else - return !lhs.valueless_by_exception() && - (rhs.valueless_by_exception() || lhs.index() > rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); -#endif -} - -template -inline constexpr bool operator<=(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::less_equal; -#ifdef MPARK_CPP14_CONSTEXPR - if (lhs.valueless_by_exception()) - return true; - if (rhs.valueless_by_exception()) - return false; - if (lhs.index() < rhs.index()) - return true; - if (lhs.index() > rhs.index()) - return false; - return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); -#else - return lhs.valueless_by_exception() || - (!rhs.valueless_by_exception() && - (lhs.index() < rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); -#endif -} - -template -inline constexpr bool operator>=(const variant& lhs, const variant& rhs) -{ - using detail::visitation::variant; - using lib::greater_equal; -#ifdef MPARK_CPP14_CONSTEXPR - if (rhs.valueless_by_exception()) - return true; - if (lhs.valueless_by_exception()) - return false; - if (lhs.index() > rhs.index()) - return true; - if (lhs.index() < rhs.index()) - return false; - return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); -#else - return rhs.valueless_by_exception() || - (!lhs.valueless_by_exception() && - (lhs.index() > rhs.index() || - (lhs.index() == rhs.index() && - variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs)))); -#endif -} - -struct monostate -{ -}; - -inline constexpr bool operator<(monostate, monostate) noexcept -{ - return false; -} - -inline constexpr bool operator>(monostate, monostate) noexcept -{ - return false; -} - -inline constexpr bool operator<=(monostate, monostate) noexcept -{ - return true; -} - -inline constexpr bool operator>=(monostate, monostate) noexcept -{ - return true; -} - -inline constexpr bool operator==(monostate, monostate) noexcept -{ - return true; -} - -inline constexpr bool operator!=(monostate, monostate) noexcept -{ - return false; -} - -#ifdef MPARK_CPP14_CONSTEXPR -namespace detail -{ -inline constexpr bool all(std::initializer_list bs) -{ - for (bool b : bs) - { - if (!b) - { - return false; - } - } - return true; -} - -} // namespace detail - -template -inline constexpr decltype(auto) visit(Visitor&& visitor, Vs&&... vs) -{ - return (detail::all({!vs.valueless_by_exception()...}) ? (void)0 : throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...); -} -#else -namespace detail -{ -template -inline constexpr bool all_impl(const lib::array& bs, std::size_t idx) -{ - return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); -} - -template -inline constexpr bool all(const lib::array& bs) -{ - return all_impl(bs, 0); -} - -} // namespace detail - -template -inline constexpr DECLTYPE_AUTO visit(Visitor&& visitor, Vs&&... vs) DECLTYPE_AUTO_RETURN( - (detail::all(lib::array{{!vs.valueless_by_exception()...}}) ? - (void)0 : - throw_bad_variant_access()), - detail::visitation::variant::visit_value(lib::forward(visitor), - lib::forward(vs)...)) -#endif - -template -inline auto swap(variant& lhs, variant& rhs) noexcept(noexcept(lhs.swap(rhs))) - -> decltype(lhs.swap(rhs)) -{ - lhs.swap(rhs); -} - -namespace detail -{ -template -using enabled_type = T; - -namespace hash -{ -template -constexpr bool meets_requirements() -{ - return std::is_copy_constructible::value && std::is_move_constructible::value && - lib::is_invocable_r::value; -} - -template -constexpr bool is_enabled() -{ - using H = std::hash; - return meets_requirements() && std::is_default_constructible::value && - std::is_copy_assignable::value && std::is_move_assignable::value; -} - -} // namespace hash - -} // namespace detail - -#undef AUTO -#undef AUTO_RETURN - -#undef AUTO_REFREF -#undef AUTO_REFREF_RETURN - -#undef DECLTYPE_AUTO -#undef DECLTYPE_AUTO_RETURN - -} // namespace mpark - -namespace std -{ -template -struct hash, mpark::lib::enable_if_t>()...>::value>>> -{ - using argument_type = mpark::variant; - using result_type = std::size_t; - - inline result_type operator()(const argument_type& v) const - { - using mpark::detail::visitation::variant; - std::size_t result = v.valueless_by_exception() ? - 299792458 // Random value chosen by the universe upon creation - : - variant::visit_alt( -#ifdef MPARK_GENERIC_LAMBDAS - [](const auto& alt) { - using alt_type = mpark::lib::decay_t; - using value_type = - mpark::lib::remove_const_t; - return hash{}(alt.value); - } -#else - hasher {} -#endif - , - v); - return hash_combine(result, hash{}(v.index())); - } - -private: -#ifndef MPARK_GENERIC_LAMBDAS - struct hasher - { - template - inline std::size_t operator()(const Alt& alt) const - { - using alt_type = mpark::lib::decay_t; - using value_type = mpark::lib::remove_const_t; - return hash{}(alt.value); - } - }; -#endif - - static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) - { - return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); - } -}; - -template <> -struct hash -{ - using argument_type = mpark::monostate; - using result_type = std::size_t; - - inline result_type operator()(const argument_type&) const noexcept - { - return 66740831; // return a fundamentally attractive random value. - } -}; - -} // namespace std - -namespace std -{ -using mpark::bad_variant_access; -using mpark::get; -using mpark::get_if; -using mpark::holds_alternative; -using mpark::monostate; -using mpark::variant; -using mpark::variant_alternative; -using mpark::variant_alternative_t; -using mpark::variant_size; -using mpark::visit; -} // namespace std -#endif From c40ae4508dcf6a14ad7a810fe8cd83488aa59103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 25 Dec 2017 22:41:09 +0100 Subject: [PATCH 2/6] Bump minimum GCC version to 7.0 GCC 7.0 is the first version with full support for C++17. Also fixes some bugs like https://stackoverflow.com/questions/32097759 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3577234bb5..f51b8af77c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,8 +203,8 @@ endif() # Enforce minimum GCC version -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) - message(FATAL_ERROR "Dolphin requires at least GCC 6.0 (found ${CMAKE_CXX_COMPILER_VERSION})") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) + message(FATAL_ERROR "Dolphin requires at least GCC 7.0 (found ${CMAKE_CXX_COMPILER_VERSION})") endif() if(CMAKE_GENERATOR MATCHES "Ninja") From cb168f22d66edf0216fadc5bdc602394d5e9b9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 25 Dec 2017 22:56:36 +0100 Subject: [PATCH 3/6] Replace custom UNUSED macro with [[maybe_unused]] --- Source/Core/Common/Compiler.h | 9 --------- Source/Core/Common/Crypto/ec.cpp | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/Source/Core/Common/Compiler.h b/Source/Core/Common/Compiler.h index 0cd3836330..2b709cfe6f 100644 --- a/Source/Core/Common/Compiler.h +++ b/Source/Core/Common/Compiler.h @@ -4,15 +4,6 @@ #pragma once -// TODO: Replace this with [[maybe_unused]] directly when GCC 7 and clang 3.9 -// are hard requirements. -#if defined(__GNUC__) || __clang__ -// Disable "unused function" warnings for the ones manually marked as such. -#define DOLPHIN_UNUSED __attribute__((unused)) -#else -#define DOLPHIN_UNUSED [[maybe_unused]] -#endif - #ifdef _WIN32 #define DOLPHIN_FORCE_INLINE __forceinline #else diff --git a/Source/Core/Common/Crypto/ec.cpp b/Source/Core/Common/Crypto/ec.cpp index 098d3e30c6..86ad2cccca 100644 --- a/Source/Core/Common/Crypto/ec.cpp +++ b/Source/Core/Common/Crypto/ec.cpp @@ -173,7 +173,7 @@ private: }; // y**2 + x*y = x**3 + x + b -DOLPHIN_UNUSED static const u8 ec_b[30] = { +[[maybe_unused]] static const u8 ec_b[30] = { 0x00, 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c, 0x09, 0x23, 0xbb, 0x58, 0x21, 0x3b, 0x33, 0x3b, 0x20, 0xe9, 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad}; From 6f84984b7b0514227327b2e2c5ef10907d150b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 25 Dec 2017 23:01:00 +0100 Subject: [PATCH 4/6] Use attribute [[fallthrough]] --- Source/Core/Core/HW/SI/SI_DeviceGBA.cpp | 4 ++-- Source/Core/Core/IOS/WFS/WFSI.cpp | 2 +- .../Core/PowerPC/JitArm64/JitArm64_RegCache.cpp | 13 +++++-------- Source/Core/DolphinQt/RenderWidget.cpp | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp b/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp index 37a1b0f7e9..8d28ed322f 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGBA.cpp @@ -314,9 +314,9 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int length) m_last_cmd = buffer[0]; m_timestamp_sent = CoreTiming::GetTicks(); m_next_action = NextAction::WaitTransferTime; + [[fallthrough]]; } - // [[fallthrough]]b case NextAction::WaitTransferTime: { int elapsed_time = static_cast(CoreTiming::GetTicks() - m_timestamp_sent); @@ -324,9 +324,9 @@ int CSIDevice_GBA::RunBuffer(u8* buffer, int length) if (GetTransferTime(m_last_cmd) > elapsed_time) return 0; m_next_action = NextAction::ReceiveResponse; + [[fallthrough]]; } - // [[fallthrough]] case NextAction::ReceiveResponse: { int num_data_received = m_sock_server.Receive(buffer); diff --git a/Source/Core/Core/IOS/WFS/WFSI.cpp b/Source/Core/Core/IOS/WFS/WFSI.cpp index ac18c400c1..0f98bf357f 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.cpp +++ b/Source/Core/Core/IOS/WFS/WFSI.cpp @@ -186,7 +186,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) case IOCTL_WFSI_PREPARE_PROFILE: m_base_extract_path = StringFromFormat("/vol/%s/tmp/", m_device_name.c_str()); - // Fall through intended. + [[fallthrough]]; case IOCTL_WFSI_PREPARE_CONTENT: { diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp index b97ac69180..02f557b9b7 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp @@ -426,8 +426,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type) // Else convert this register back to doubles. m_float_emit->FCVTL(64, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg)); reg.Load(host_reg, REG_REG); - - // fall through + [[fallthrough]]; } case REG_REG: // already in a reg { @@ -442,8 +441,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type) // Else convert this register back to a double. m_float_emit->FCVT(64, 32, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg)); reg.Load(host_reg, REG_LOWER_PAIR); - - // fall through + [[fallthrough]]; } case REG_LOWER_PAIR: { @@ -476,8 +474,7 @@ ARM64Reg Arm64FPRCache::R(size_t preg, RegType type) m_float_emit->FCVT(64, 32, EncodeRegToDouble(host_reg), EncodeRegToDouble(host_reg)); reg.Load(host_reg, REG_DUP); - - // fall through + [[fallthrough]]; } case REG_DUP: { @@ -549,7 +546,7 @@ ARM64Reg Arm64FPRCache::RW(size_t preg, RegType type) case REG_REG_SINGLE: flush_reg = GetReg(); m_float_emit->FCVTL(64, EncodeRegToDouble(flush_reg), EncodeRegToDouble(host_reg)); - // fall through + [[fallthrough]]; case REG_REG: // We are doing a full 128bit store because it takes 2 cycles on a Cortex-A57 to do a 128bit // store. @@ -559,7 +556,7 @@ ARM64Reg Arm64FPRCache::RW(size_t preg, RegType type) case REG_DUP_SINGLE: flush_reg = GetReg(); m_float_emit->FCVT(64, 32, EncodeRegToDouble(flush_reg), EncodeRegToDouble(host_reg)); - // fall through + [[fallthrough]]; case REG_DUP: // Store PSR1 (which is equal to PSR0) in memory. m_float_emit->STR(64, INDEX_UNSIGNED, flush_reg, PPC_REG, PPCSTATE_OFF(ps[preg].ps1)); diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index 1d2ffddc0f..668d7fced3 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -189,8 +189,8 @@ bool RenderWidget::event(QEvent* event) case QEvent::MouseMove: if (g_Config.bFreeLook) OnFreeLookMouseMove(static_cast(event)); + [[fallthrough]]; - // [[fallthrough]] case QEvent::MouseButtonPress: if (!Settings::Instance().GetHideCursor() && isActiveWindow()) { From ab9ece9bcab8a6d55dbe6f3a904d49231e5f73e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 26 Dec 2017 00:38:44 +0100 Subject: [PATCH 5/6] Replace MathUtil::Clamp with std::clamp --- Source/Core/AudioCommon/Mixer.cpp | 10 ++++----- Source/Core/Common/MathUtil.h | 22 +++++++------------ Source/Core/Core/DSP/DSPAccelerator.cpp | 5 +++-- Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp | 7 +++--- Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h | 8 +++---- Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp | 9 ++++---- Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp | 7 +++--- Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h | 6 ++--- Source/Core/Core/HW/GCMemcard/GCMemcard.cpp | 5 ++--- Source/Core/Core/HW/StreamADPCM.cpp | 7 +++--- Source/Core/Core/HW/VideoInterface.cpp | 4 ++-- Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp | 9 ++++---- .../Core/HW/WiimoteEmu/Extension/Nunchuk.cpp | 1 + Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp | 6 ++--- .../Interpreter_LoadStorePaired.cpp | 3 ++- .../ControllerEmu/ControlGroup/Cursor.cpp | 6 ++--- .../InputCommon/ControllerEmu/StickGate.cpp | 5 +++-- .../ControllerInterface/Pipes/Pipes.cpp | 4 ++-- .../ControllerInterface/evdev/evdev.cpp | 1 + Source/Core/VideoBackends/D3D/Render.cpp | 1 + .../VideoBackends/Software/EfbInterface.cpp | 2 +- .../VideoBackends/Software/Rasterizer.cpp | 2 +- Source/Core/VideoBackends/Software/Tev.cpp | 6 ++--- .../VideoBackends/Software/TransformUnit.cpp | 13 +++++------ .../Core/VideoBackends/Vulkan/SwapChain.cpp | 8 +++---- Source/Core/VideoCommon/BPFunctions.cpp | 14 +++++++----- Source/Core/VideoCommon/RenderBase.cpp | 5 +++-- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- .../VideoCommon/TextureDecoder_Common.cpp | 19 ++++++++-------- .../Core/VideoCommon/TextureDecoder_x64.cpp | 1 - Source/UnitTests/Common/MathUtilTest.cpp | 12 ---------- 31 files changed, 101 insertions(+), 109 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index 7620ba5cec..5c1cb3a33f 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -4,13 +4,13 @@ #include "AudioCommon/Mixer.h" +#include #include #include #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" #include "Common/Swap.h" #include "Core/ConfigManager.h" @@ -86,14 +86,14 @@ unsigned int Mixer::MixerFifo::Mix(short* samples, unsigned int numSamples, int sampleL = ((l1 << 16) + (l2 - l1) * (u16)m_frac) >> 16; sampleL = (sampleL * lvolume) >> 8; sampleL += samples[currentSample + 1]; - samples[currentSample + 1] = MathUtil::Clamp(sampleL, -32767, 32767); + samples[currentSample + 1] = std::clamp(sampleL, -32767, 32767); s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); // current s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); // next int sampleR = ((r1 << 16) + (r2 - r1) * (u16)m_frac) >> 16; sampleR = (sampleR * rvolume) >> 8; sampleR += samples[currentSample]; - samples[currentSample] = MathUtil::Clamp(sampleR, -32767, 32767); + samples[currentSample] = std::clamp(sampleR, -32767, 32767); m_frac += ratio; indexR += 2 * (u16)(m_frac >> 16); @@ -111,8 +111,8 @@ unsigned int Mixer::MixerFifo::Mix(short* samples, unsigned int numSamples, s[1] = (s[1] * lvolume) >> 8; for (; currentSample < numSamples * 2; currentSample += 2) { - int sampleR = MathUtil::Clamp(s[0] + samples[currentSample + 0], -32767, 32767); - int sampleL = MathUtil::Clamp(s[1] + samples[currentSample + 1], -32767, 32767); + int sampleR = std::clamp(s[0] + samples[currentSample + 0], -32767, 32767); + int sampleL = std::clamp(s[1] + samples[currentSample + 1], -32767, 32767); samples[currentSample + 0] = sampleR; samples[currentSample + 1] = sampleL; diff --git a/Source/Core/Common/MathUtil.h b/Source/Core/Common/MathUtil.h index 990a5dd145..1556f8e39f 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -18,12 +18,6 @@ namespace MathUtil constexpr double TAU = 6.2831853071795865; constexpr double PI = TAU / 2; -template -constexpr T Clamp(const T val, const T& min, const T& max) -{ - return std::max(min, std::min(max, val)); -} - template constexpr auto Sign(const T& val) -> decltype((T{} < val) - (val < T{})) { @@ -81,20 +75,20 @@ struct Rectangle // this Clamp. void ClampLL(T x1, T y1, T x2, T y2) { - left = Clamp(left, x1, x2); - right = Clamp(right, x1, x2); - top = Clamp(top, y2, y1); - bottom = Clamp(bottom, y2, y1); + left = std::clamp(left, x1, x2); + right = std::clamp(right, x1, x2); + top = std::clamp(top, y2, y1); + bottom = std::clamp(bottom, y2, y1); } // If the rectangle is in a coordinate system with an upper-left origin, // use this Clamp. void ClampUL(T x1, T y1, T x2, T y2) { - left = Clamp(left, x1, x2); - right = Clamp(right, x1, x2); - top = Clamp(top, y1, y2); - bottom = Clamp(bottom, y1, y2); + left = std::clamp(left, x1, x2); + right = std::clamp(right, x1, x2); + top = std::clamp(top, y1, y2); + bottom = std::clamp(bottom, y1, y2); } }; diff --git a/Source/Core/Core/DSP/DSPAccelerator.cpp b/Source/Core/Core/DSP/DSPAccelerator.cpp index 581fed296f..d7841680f6 100644 --- a/Source/Core/Core/DSP/DSPAccelerator.cpp +++ b/Source/Core/Core/DSP/DSPAccelerator.cpp @@ -2,12 +2,13 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Core/DSP/DSPAccelerator.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" namespace DSP { @@ -89,7 +90,7 @@ u16 Accelerator::Read(const s16* coefs) temp -= 16; s32 val32 = (scale * temp) + ((0x400 + coef1 * m_yn1 + coef2 * m_yn2) >> 11); - val = static_cast(MathUtil::Clamp(val32, -0x7FFF, 0x7FFF)); + val = static_cast(std::clamp(val32, -0x7FFF, 0x7FFF)); step_size_bytes = 2; m_yn2 = m_yn1; diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp index 5abca20d98..85c3e0ba68 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Core/HW/DSPHLE/UCodes/AX.h" #include "Common/ChunkFile.h" @@ -9,7 +11,6 @@ #include "Common/File.h" #include "Common/FileUtil.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" #include "Common/Swap.h" #include "Core/HW/DSP.h" #include "Core/HW/DSPHLE/DSPHLE.h" @@ -535,8 +536,8 @@ void AXUCode::OutputSamples(u32 lr_addr, u32 surround_addr) // Output samples clamped to 16 bits and interlaced RLRLRLRLRL... for (u32 i = 0; i < 5 * 32; ++i) { - int left = MathUtil::Clamp(m_samples_left[i], -32767, 32767); - int right = MathUtil::Clamp(m_samples_right[i], -32767, 32767); + int left = std::clamp(m_samples_left[i], -32767, 32767); + int right = std::clamp(m_samples_right[i], -32767, 32767); buffer[2 * i + 0] = Common::swap16(right); buffer[2 * i + 1] = Common::swap16(left); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h index e56f001c68..490a000b85 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h @@ -12,11 +12,11 @@ #error AXVoice.h included without specifying version #endif +#include #include #include #include "Common/CommonTypes.h" -#include "Common/MathUtil.h" #include "Core/DSP/DSPAccelerator.h" #include "Core/HW/DSP.h" #include "Core/HW/DSPHLE/UCodes/AX.h" @@ -413,7 +413,7 @@ void MixAdd(int* out, const s16* input, u32 count, u16* pvol, s16* dpop, bool ra s64 sample = input[i]; sample *= volume; sample >>= 15; - sample = MathUtil::Clamp((s32)sample, -32767, 32767); // -32768 ? + sample = std::clamp((s32)sample, -32767, 32767); // -32768 ? out[i] += (s16)sample; volume += volume_delta; @@ -447,8 +447,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl // Apply a global volume ramp using the volume envelope parameters. for (u32 i = 0; i < count; ++i) { - samples[i] = MathUtil::Clamp(((s32)samples[i] * pb.vol_env.cur_volume) >> 15, -32767, - 32767); // -32768 ? + samples[i] = std::clamp(((s32)samples[i] * pb.vol_env.cur_volume) >> 15, -32767, + 32767); // -32768 ? pb.vol_env.cur_volume += pb.vol_env.cur_volume_delta; } diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp index 2429b648d1..6619bc909b 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp @@ -4,12 +4,13 @@ // #define AX_WII // Used in AXVoice. +#include + #include "Core/HW/DSPHLE/UCodes/AXWii.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" #include "Common/Swap.h" #include "Core/HW/DSPHLE/DSPHLE.h" #include "Core/HW/DSPHLE/MailHandler.h" @@ -602,8 +603,8 @@ void AXWiiUCode::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool left = ((s64)left * volume_ramp[i]) >> 15; right = ((s64)right * volume_ramp[i]) >> 15; - m_samples_left[i] = MathUtil::Clamp(left, -32767, 32767); - m_samples_right[i] = MathUtil::Clamp(right, -32767, 32767); + m_samples_left[i] = std::clamp(left, -32767, 32767); + m_samples_right[i] = std::clamp(right, -32767, 32767); } for (u32 i = 0; i < 3 * 32; ++i) @@ -626,7 +627,7 @@ void AXWiiUCode::OutputWMSamples(u32* addresses) u16* out = (u16*)HLEMemory_Get_Pointer(addresses[i]); for (u32 j = 0; j < 3 * 6; ++j) { - int sample = MathUtil::Clamp(in[j], -32767, 32767); + int sample = std::clamp(in[j], -32767, 32767); out[j] = Common::swap16((u16)sample); } } diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp index 4dc60770a5..329b270ad9 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.cpp @@ -4,6 +4,7 @@ #include "Core/HW/DSPHLE/UCodes/Zelda.h" +#include #include #include @@ -1086,7 +1087,7 @@ void ZeldaAudioRenderer::ApplyReverb(bool post_rendering) for (u16 j = 0; j < 8; ++j) sample += (s32)buffer[i + j] * rpb.filter_coeffs[j]; sample >>= 15; - buffer[i] = MathUtil::Clamp(sample, -0x8000, 0x7FFF); + buffer[i] = std::clamp(sample, -0x8000, 0x7FFF); } }; @@ -1526,7 +1527,7 @@ void ZeldaAudioRenderer::Resample(VPB* vpb, const s16* src, MixingBuffer* dst) dst_sample_unclamped += (s64)2 * coeffs[i] * input[i]; dst_sample_unclamped >>= 16; - dst_sample = (s16)MathUtil::Clamp(dst_sample_unclamped, -0x8000, 0x7FFF); + dst_sample = (s16)std::clamp(dst_sample_unclamped, -0x8000, 0x7FFF); pos += ratio; } @@ -1764,7 +1765,7 @@ void ZeldaAudioRenderer::DecodeAFC(VPB* vpb, s16* dst, size_t block_count) s32 sample = delta * nibbles[i] + yn1 * m_afc_coeffs[idx * 2] + yn2 * m_afc_coeffs[idx * 2 + 1]; sample >>= 11; - sample = MathUtil::Clamp(sample, -0x8000, 0x7fff); + sample = std::clamp(sample, -0x8000, 0x7fff); *dst++ = (s16)sample; yn2 = yn1; yn1 = sample; diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h index 2eed60aa50..32ab7f804d 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/Zelda.h @@ -4,10 +4,10 @@ #pragma once +#include #include #include "Common/CommonTypes.h" -#include "Common/MathUtil.h" #include "Core/HW/DSPHLE/UCodes/UCodes.h" namespace DSP @@ -54,7 +54,7 @@ private: s32 tmp = (u32)(*buf)[i] * (u32)vol; tmp >>= 16 - B; - (*buf)[i] = (s16)MathUtil::Clamp(tmp, -0x8000, 0x7FFF); + (*buf)[i] = (s16)std::clamp(tmp, -0x8000, 0x7FFF); } } template @@ -96,7 +96,7 @@ private: while (count--) { s32 vol_src = ((s32)*src++ * (s32)vol) >> 15; - *dst++ += MathUtil::Clamp(vol_src, -0x8000, 0x7FFF); + *dst++ += std::clamp(vol_src, -0x8000, 0x7FFF); } } diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp index d1beccb1e8..9eec76d717 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcard.cpp @@ -15,7 +15,6 @@ #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" #include "Common/File.h" -#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" #include "Common/Swap.h" @@ -609,8 +608,8 @@ u16 BlockAlloc::NextFreeBlock(u16 MaxBlock, u16 StartingBlock) const { if (m_free_blocks > 0) { - StartingBlock = MathUtil::Clamp(StartingBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); - MaxBlock = MathUtil::Clamp(MaxBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); + StartingBlock = std::clamp(StartingBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); + MaxBlock = std::clamp(MaxBlock, MC_FST_BLOCKS, BAT_SIZE + MC_FST_BLOCKS); for (u16 i = StartingBlock; i < MaxBlock; ++i) if (m_map[i - MC_FST_BLOCKS] == 0) return i; diff --git a/Source/Core/Core/HW/StreamADPCM.cpp b/Source/Core/Core/HW/StreamADPCM.cpp index fe309b63a5..e112023a32 100644 --- a/Source/Core/Core/HW/StreamADPCM.cpp +++ b/Source/Core/Core/HW/StreamADPCM.cpp @@ -4,11 +4,12 @@ // Adapted from in_cube by hcs & destop +#include + #include "Core/HW/StreamADPCM.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" -#include "Common/MathUtil.h" namespace StreamADPCM { @@ -30,7 +31,7 @@ static s16 ADPDecodeSample(s32 bits, s32 q, s32& hist1, s32& hist2) hist = (hist1 * 0x62) - (hist2 * 0x37); break; } - hist = MathUtil::Clamp((hist + 0x20) >> 6, -0x200000, 0x1fffff); + hist = std::clamp((hist + 0x20) >> 6, -0x200000, 0x1fffff); s32 cur = (((s16)(bits << 12) >> (q & 0xf)) << 6) + hist; @@ -38,7 +39,7 @@ static s16 ADPDecodeSample(s32 bits, s32 q, s32& hist1, s32& hist2) hist1 = cur; cur >>= 6; - cur = MathUtil::Clamp(cur, -0x8000, 0x7fff); + cur = std::clamp(cur, -0x8000, 0x7fff); return (s16)cur; } diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index a2750a5840..8dc871d88b 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -4,6 +4,7 @@ #include "Core/HW/VideoInterface.h" +#include #include #include #include @@ -12,7 +13,6 @@ #include "Common/CommonTypes.h" #include "Common/Config/Config.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" #include "Core/Config/MainSettings.h" #include "Core/Config/SYSCONFSettings.h" @@ -328,7 +328,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) u16 value = static_cast(1 + m_HTiming0.HLW * (CoreTiming::GetTicks() - s_ticks_last_line_start) / (GetTicksPerHalfLine())); - return MathUtil::Clamp(value, static_cast(1), static_cast(m_HTiming0.HLW * 2)); + return std::clamp(value, 1, m_HTiming0.HLW * 2); }), MMIO::ComplexWrite([](u32, u16 val) { WARN_LOG(VIDEOINTERFACE, diff --git a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp index e4c74668fa..cef7528c65 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp @@ -4,6 +4,7 @@ #include "Core/HW/WiimoteEmu/Dynamics.h" +#include #include #include "Common/MathUtil.h" @@ -170,7 +171,7 @@ void EmulateSwing(MotionState* state, ControllerEmu::Force* swing_group, float t if (y_progress > max_y_progress || y_progress < -1) { state->position.y = - MathUtil::Clamp(state->position.y, -1.f * max_distance, max_y_progress * max_distance); + std::clamp(state->position.y, -1.f * max_distance, max_y_progress * max_distance); state->velocity.y = 0; state->acceleration.y = 0; } @@ -184,9 +185,9 @@ WiimoteCommon::DataReportBuilder::AccelData ConvertAccelData(const Common::Vec3& // 10-bit integers. constexpr long MAX_VALUE = (1 << 10) - 1; - return {u16(MathUtil::Clamp(std::lround(scaled_accel.x + zero_g), 0l, MAX_VALUE)), - u16(MathUtil::Clamp(std::lround(scaled_accel.y + zero_g), 0l, MAX_VALUE)), - u16(MathUtil::Clamp(std::lround(scaled_accel.z + zero_g), 0l, MAX_VALUE))}; + return {u16(std::clamp(std::lround(scaled_accel.x + zero_g), 0l, MAX_VALUE)), + u16(std::clamp(std::lround(scaled_accel.y + zero_g), 0l, MAX_VALUE)), + u16(std::clamp(std::lround(scaled_accel.z + zero_g), 0l, MAX_VALUE))}; } void EmulateCursor(MotionState* state, ControllerEmu::Cursor* ir_group, float time_elapsed) diff --git a/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp b/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp index 8fbf005c93..971a038d89 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp @@ -4,6 +4,7 @@ #include "Core/HW/WiimoteEmu/Extension/Nunchuk.h" +#include #include #include #include diff --git a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp index de5e55f69e..f60507204a 100644 --- a/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/MotionPlus.cpp @@ -642,9 +642,9 @@ void MotionPlus::PrepareInput(const Common::Vec3& angular_velocity) mplus_data.pitch_slow = (std::abs(pitch) < SLOW_MAX_RAD_PER_SEC); s32 pitch_value = pitch * (mplus_data.pitch_slow ? SLOW_SCALE : FAST_SCALE); - yaw_value = MathUtil::Clamp(yaw_value + ZERO_VALUE, 0, MAX_VALUE); - roll_value = MathUtil::Clamp(roll_value + ZERO_VALUE, 0, MAX_VALUE); - pitch_value = MathUtil::Clamp(pitch_value + ZERO_VALUE, 0, MAX_VALUE); + yaw_value = std::clamp(yaw_value + ZERO_VALUE, 0, MAX_VALUE); + roll_value = std::clamp(roll_value + ZERO_VALUE, 0, MAX_VALUE); + pitch_value = std::clamp(pitch_value + ZERO_VALUE, 0, MAX_VALUE); // Bits 0-7 mplus_data.yaw1 = u8(yaw_value); diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp index 1d78e5e6d8..a81fae3dc1 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include @@ -63,7 +64,7 @@ SType ScaleAndClamp(double ps, u32 stScale) float min = (float)std::numeric_limits::min(); float max = (float)std::numeric_limits::max(); - return (SType)MathUtil::Clamp(convPS, min, max); + return (SType)std::clamp(convPS, min, max); } template diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp index dd5bc87887..410cf87b33 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp @@ -109,7 +109,7 @@ Cursor::StateData Cursor::GetState(const bool adjusted) // Smooth out z movement: // FYI: Not using relative input for Z. - m_state.z += MathUtil::Clamp(z - m_state.z, -max_z_step, max_z_step); + m_state.z += std::clamp(z - m_state.z, -max_z_step, max_z_step); // Relative input: if (m_relative_setting.GetValue()) @@ -122,8 +122,8 @@ Cursor::StateData Cursor::GetState(const bool adjusted) } else { - m_state.x = MathUtil::Clamp(m_state.x + input.x * max_step, -1.0, 1.0); - m_state.y = MathUtil::Clamp(m_state.y + input.y * max_step, -1.0, 1.0); + m_state.x = std::clamp(m_state.x + input.x * max_step, -1.0, 1.0); + m_state.y = std::clamp(m_state.y + input.y * max_step, -1.0, 1.0); } } // Absolute input: diff --git a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp index 48c21ae5be..70ed383398 100644 --- a/Source/Core/InputCommon/ControllerEmu/StickGate.cpp +++ b/Source/Core/InputCommon/ControllerEmu/StickGate.cpp @@ -4,6 +4,7 @@ #include "InputCommon/ControllerEmu/StickGate.h" +#include #include #include "Common/Common.h" @@ -277,8 +278,8 @@ ReshapableInput::ReshapeData ReshapableInput::Reshape(ControlState x, ControlSta // Scale to the gate shape/radius: dist *= gate_max_dist; - return {MathUtil::Clamp(std::cos(angle) * dist, -1.0, 1.0), - MathUtil::Clamp(std::sin(angle) * dist, -1.0, 1.0)}; + return {std::clamp(std::cos(angle) * dist, -1.0, 1.0), + std::clamp(std::sin(angle) * dist, -1.0, 1.0)}; } } // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp index 8b885cad68..1cb76b2d25 100644 --- a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include @@ -15,7 +16,6 @@ #include #include "Common/FileUtil.h" -#include "Common/MathUtil.h" #include "Common/StringUtil.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/ControllerInterface/Pipes/Pipes.h" @@ -123,7 +123,7 @@ void PipeDevice::AddAxis(const std::string& name, double value) void PipeDevice::SetAxis(const std::string& entry, double value) { - value = MathUtil::Clamp(value, 0.0, 1.0); + value = std::clamp(value, 0.0, 1.0); double hi = std::max(0.0, value - 0.5) * 2.0; double lo = (0.5 - std::min(0.5, value)) * 2.0; auto search_hi = m_axes.find(entry + " +"); diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index f84f3b01c6..da1e5fc918 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include #include diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index fc417962a0..3190a25965 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -4,6 +4,7 @@ #include "VideoBackends/D3D/Render.h" +#include #include #include #include diff --git a/Source/Core/VideoBackends/Software/EfbInterface.cpp b/Source/Core/VideoBackends/Software/EfbInterface.cpp index 9548dece5a..0f74d4ebde 100644 --- a/Source/Core/VideoBackends/Software/EfbInterface.cpp +++ b/Source/Core/VideoBackends/Software/EfbInterface.cpp @@ -514,7 +514,7 @@ static u32 GammaCorrection(u32 color, const float gamma_rcp) for (int i = BLU_C; i <= RED_C; i++) { out_color[i] = static_cast( - MathUtil::Clamp(std::pow(in_colors[i] / 255.0f, gamma_rcp) * 255.0f, 0.0f, 255.0f)); + std::clamp(std::pow(in_colors[i] / 255.0f, gamma_rcp) * 255.0f, 0.0f, 255.0f)); } u32 out_color32; diff --git a/Source/Core/VideoBackends/Software/Rasterizer.cpp b/Source/Core/VideoBackends/Software/Rasterizer.cpp index 9db10f8ae0..e530e80e54 100644 --- a/Source/Core/VideoBackends/Software/Rasterizer.cpp +++ b/Source/Core/VideoBackends/Software/Rasterizer.cpp @@ -77,7 +77,7 @@ static void Draw(s32 x, s32 y, s32 xi, s32 yi) float dx = vertexOffsetX + (float)(x - vertex0X); float dy = vertexOffsetY + (float)(y - vertex0Y); - s32 z = (s32)MathUtil::Clamp(ZSlope.GetValue(dx, dy), 0.0f, 16777215.0f); + s32 z = (s32)std::clamp(ZSlope.GetValue(dx, dy), 0.0f, 16777215.0f); if (bpmem.UseEarlyDepthTest() && g_ActiveConfig.bZComploc) { diff --git a/Source/Core/VideoBackends/Software/Tev.cpp b/Source/Core/VideoBackends/Software/Tev.cpp index 4b7c41347c..8b2d776835 100644 --- a/Source/Core/VideoBackends/Software/Tev.cpp +++ b/Source/Core/VideoBackends/Software/Tev.cpp @@ -2,11 +2,11 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" -#include "Common/MathUtil.h" #include "VideoBackends/Software/DebugUtil.h" #include "VideoBackends/Software/EfbInterface.h" #include "VideoBackends/Software/Tev.h" @@ -777,7 +777,7 @@ void Tev::Draw() // Based on that, choose the index such that points which are far away from the z-axis use the // 10th "k" value and such that central points use the first value. float floatindex = 9.f - std::abs(offset) * 9.f; - floatindex = MathUtil::Clamp(floatindex, 0.f, 9.f); // TODO: This shouldn't be necessary! + floatindex = std::clamp(floatindex, 0.f, 9.f); // TODO: This shouldn't be necessary! // Get the two closest integer indices, look up the corresponding samples const int indexlower = (int)floatindex; @@ -798,7 +798,7 @@ void Tev::Draw() ze -= bpmem.fog.GetC(); // clamp 0 to 1 - float fog = MathUtil::Clamp(ze, 0.f, 1.f); + float fog = std::clamp(ze, 0.f, 1.f); switch (bpmem.fog.c_proj_fsel.fsel) { diff --git a/Source/Core/VideoBackends/Software/TransformUnit.cpp b/Source/Core/VideoBackends/Software/TransformUnit.cpp index 8a2b4e7fb8..d8b7763669 100644 --- a/Source/Core/VideoBackends/Software/TransformUnit.cpp +++ b/Source/Core/VideoBackends/Software/TransformUnit.cpp @@ -12,7 +12,6 @@ #include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/Swap.h" @@ -192,8 +191,8 @@ static void TransformTexCoordRegular(const TexMtxInfo& texinfo, int coordNum, bo // Makes differences in Rogue Squadron 3 (Hoth sky) and The Last Story (shadow culling) if (dst->z == 0.0f) { - dst->x = MathUtil::Clamp(dst->x / 2.0f, -1.0f, 1.0f); - dst->y = MathUtil::Clamp(dst->y / 2.0f, -1.0f, 1.0f); + dst->x = std::clamp(dst->x / 2.0f, -1.0f, 1.0f); + dst->y = std::clamp(dst->y / 2.0f, -1.0f, 1.0f); } } @@ -359,9 +358,9 @@ void TransformColor(const InputVertexData* src, OutputVertexData* dst) LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol); } - int light_x = MathUtil::Clamp(static_cast(lightCol.x), 0, 255); - int light_y = MathUtil::Clamp(static_cast(lightCol.y), 0, 255); - int light_z = MathUtil::Clamp(static_cast(lightCol.z), 0, 255); + int light_x = std::clamp(static_cast(lightCol.x), 0, 255); + int light_y = std::clamp(static_cast(lightCol.y), 0, 255); + int light_z = std::clamp(static_cast(lightCol.z), 0, 255); chancolor[1] = (matcolor[1] * (light_x + (light_x >> 7))) >> 8; chancolor[2] = (matcolor[2] * (light_y + (light_y >> 7))) >> 8; chancolor[3] = (matcolor[3] * (light_z + (light_z >> 7))) >> 8; @@ -393,7 +392,7 @@ void TransformColor(const InputVertexData* src, OutputVertexData* dst) LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol); } - int light_a = MathUtil::Clamp(static_cast(lightCol), 0, 255); + int light_a = std::clamp(static_cast(lightCol), 0, 255); chancolor[0] = (matcolor[0] * (light_a + (light_a >> 7))) >> 8; } else diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp index ee53005b93..ef9b6f7265 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp @@ -267,10 +267,10 @@ bool SwapChain::CreateSwapChain() size.width = std::max(g_renderer->GetBackbufferWidth(), 1); size.height = std::max(g_renderer->GetBackbufferHeight(), 1); } - size.width = MathUtil::Clamp(size.width, surface_capabilities.minImageExtent.width, - surface_capabilities.maxImageExtent.width); - size.height = MathUtil::Clamp(size.height, surface_capabilities.minImageExtent.height, - surface_capabilities.maxImageExtent.height); + size.width = std::clamp(size.width, surface_capabilities.minImageExtent.width, + surface_capabilities.maxImageExtent.width); + size.height = std::clamp(size.height, surface_capabilities.minImageExtent.height, + surface_capabilities.maxImageExtent.height); // Prefer identity transform if possible VkSurfaceTransformFlagBitsKHR transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; diff --git a/Source/Core/VideoCommon/BPFunctions.cpp b/Source/Core/VideoCommon/BPFunctions.cpp index 2aa325f8f7..e725927860 100644 --- a/Source/Core/VideoCommon/BPFunctions.cpp +++ b/Source/Core/VideoCommon/BPFunctions.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" @@ -90,8 +92,8 @@ void SetViewport() { // There's no way to support oversized depth ranges in this situation. Let's just clamp the // range to the maximum value supported by the console GPU and hope for the best. - min_depth = MathUtil::Clamp(min_depth, 0.0f, GX_MAX_DEPTH); - max_depth = MathUtil::Clamp(max_depth, 0.0f, GX_MAX_DEPTH); + min_depth = std::clamp(min_depth, 0.0f, GX_MAX_DEPTH); + max_depth = std::clamp(max_depth, 0.0f, GX_MAX_DEPTH); } if (g_renderer->UseVertexDepthRange()) @@ -131,10 +133,10 @@ void SetViewport() { const float max_width = static_cast(g_renderer->GetCurrentFramebuffer()->GetWidth()); const float max_height = static_cast(g_renderer->GetCurrentFramebuffer()->GetHeight()); - x = MathUtil::Clamp(x, 0.0f, max_width - 1.0f); - y = MathUtil::Clamp(y, 0.0f, max_height - 1.0f); - width = MathUtil::Clamp(width, 1.0f, max_width - x); - height = MathUtil::Clamp(height, 1.0f, max_height - y); + x = std::clamp(x, 0.0f, max_width - 1.0f); + y = std::clamp(y, 0.0f, max_height - 1.0f); + width = std::clamp(width, 1.0f, max_width - x); + height = std::clamp(height, 1.0f, max_height - y); } // Lower-left flip. diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 523a681884..222b1ba9ab 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -14,6 +14,7 @@ #include "VideoCommon/RenderBase.h" +#include #include #include #include @@ -218,11 +219,11 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16) { // if Z is in 16 bit format you must return a 16 bit integer - ret = MathUtil::Clamp(static_cast(depth * 65536.0f), 0, 0xFFFF); + ret = std::clamp(static_cast(depth * 65536.0f), 0, 0xFFFF); } else { - ret = MathUtil::Clamp(static_cast(depth * 16777216.0f), 0, 0xFFFFFF); + ret = std::clamp(static_cast(depth * 16777216.0f), 0, 0xFFFFFF); } return ret; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d0e12a9171..f6c9fdc407 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -556,7 +556,7 @@ static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex, // distance they kick in at is important to preserve at any resolution. // Correct this with the upscaling factor of custom textures. s64 lod_offset = std::log2(g_renderer->GetEFBScale() / custom_tex_scale) * 256.f; - state.lod_bias = MathUtil::Clamp(state.lod_bias + lod_offset, -32768, 32767); + state.lod_bias = std::clamp(state.lod_bias + lod_offset, -32768, 32767); // Anisotropic also pushes mips farther away so it cannot be used either state.anisotropic_filtering = 0; diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp index 5fbe34a098..b80ea9b999 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp @@ -7,7 +7,6 @@ #include #include "Common/CommonTypes.h" -#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/Swap.h" @@ -705,9 +704,9 @@ void TexDecoder_DecodeTexel(u8* dst, const u8* src, int s, int t, int imageWidth // We do the inverse BT.601 conversion for YCbCr to RGB // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion - u8 R = MathUtil::Clamp(int(1.164f * Y + 1.596f * V), 0, 255); - u8 G = MathUtil::Clamp(int(1.164f * Y - 0.392f * U - 0.813f * V), 0, 255); - u8 B = MathUtil::Clamp(int(1.164f * Y + 2.017f * U), 0, 255); + u8 R = std::clamp(int(1.164f * Y + 1.596f * V), 0, 255); + u8 G = std::clamp(int(1.164f * Y - 0.392f * U - 0.813f * V), 0, 255); + u8 B = std::clamp(int(1.164f * Y + 2.017f * U), 0, 255); dst[t * imageWidth + s] = 0xff000000 | B << 16 | G << 8 | R; } break; @@ -770,13 +769,13 @@ void TexDecoder_DecodeXFB(u8* dst, const u8* src, u32 width, u32 height, u32 str // We do the inverse BT.601 conversion for YCbCr to RGB // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion - u8 R1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); - u8 G1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); - u8 B1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); + u8 R1 = static_cast(std::clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); + u8 G1 = static_cast(std::clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B1 = static_cast(std::clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); - u8 R2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); - u8 G2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); - u8 B2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); + u8 R2 = static_cast(std::clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); + u8 G2 = static_cast(std::clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B2 = static_cast(std::clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); u32 rgba = 0xff000000 | B1 << 16 | G1 << 8 | R1; std::memcpy(dst_ptr, &rgba, sizeof(rgba)); diff --git a/Source/Core/VideoCommon/TextureDecoder_x64.cpp b/Source/Core/VideoCommon/TextureDecoder_x64.cpp index 7d41dbee53..9d76483656 100644 --- a/Source/Core/VideoCommon/TextureDecoder_x64.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_x64.cpp @@ -9,7 +9,6 @@ #include "Common/CPUDetect.h" #include "Common/CommonTypes.h" #include "Common/Intrinsics.h" -#include "Common/MathUtil.h" #include "Common/MsgHandler.h" #include "Common/Swap.h" diff --git a/Source/UnitTests/Common/MathUtilTest.cpp b/Source/UnitTests/Common/MathUtilTest.cpp index daca01bb74..c0609bbb92 100644 --- a/Source/UnitTests/Common/MathUtilTest.cpp +++ b/Source/UnitTests/Common/MathUtilTest.cpp @@ -6,18 +6,6 @@ #include "Common/MathUtil.h" -TEST(MathUtil, Clamp) -{ - EXPECT_EQ(1, MathUtil::Clamp(1, 0, 2)); - EXPECT_EQ(1.0, MathUtil::Clamp(1.0, 0.0, 2.0)); - - EXPECT_EQ(2, MathUtil::Clamp(4, 0, 2)); - EXPECT_EQ(2.0, MathUtil::Clamp(4.0, 0.0, 2.0)); - - EXPECT_EQ(0, MathUtil::Clamp(-1, 0, 2)); - EXPECT_EQ(0.0, MathUtil::Clamp(-1.0, 0.0, 2.0)); -} - TEST(MathUtil, IntLog2) { EXPECT_EQ(0, IntLog2(1)); From 9133e8f1befbebd87c6e61f0e454f3ae2754285a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 4 May 2019 23:54:25 +0200 Subject: [PATCH 6/6] Require CMake 3.10 and use CMAKE_CXX_STANDARD Removes the need to add -std= flags manually. CMake 3.10 is available in Ubuntu 18.04, which is the oldest LTS version we support. --- CMakeLists.txt | 2 +- Source/Android/app/build.gradle | 1 + Source/CMakeLists.txt | 18 +++--------------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f51b8af77c..5bd5ad7b9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ ######################################## # General setup # -cmake_minimum_required(VERSION 3.5.0) +cmake_minimum_required(VERSION 3.10) set(CMAKE_OSX_ARCHITECTURES "x86_64") # Minimum OS X version. # This is inserted into the Info.plist as well. diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index 4139d7c956..f5fe47863f 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -60,6 +60,7 @@ android { externalNativeBuild { cmake { path "../../../CMakeLists.txt" + version "3.10.2" } } diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 2899476e34..7d435e1ca2 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -9,21 +9,9 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") add_definitions(-D_CRT_SECURE_NO_DEPRECATE) endif() -if(CMAKE_C_COMPILER_ID MATCHES "MSVC") - # enable the latest C++ standard feature set, - # and also disable MSVC specific extensions - # to be even more standards compliant. - check_and_add_flag(CPPLATEST /std:c++latest) - check_and_add_flag(STANDARD_COMPLIANCE /permissive-) -else() - # Enable C++17 - # CMAKE_CXX_STANDARD cannot be used because it requires cmake 3.8+. - check_and_add_flag(CXX17 -std=c++17) - if(NOT FLAG_CXX_CXX17) - # Fall back to -std=c++1z - check_and_add_flag(CXX1Z -std=c++1z) - endif() -endif() +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) # These aren't actually needed for C11/C++11 # but some dependencies require them (LLVM, libav).