From 99fbdaf75b18dd4cdaad1e93fa2a4ad82b0591aa Mon Sep 17 00:00:00 2001
From: merry <git@mary.rs>
Date: Fri, 15 Jul 2022 18:37:48 +0100
Subject: [PATCH] common/setting: Make ranged a property of the type

- Avoids new GCC 12 warnings when Type is of form std::optional<T>
- Makes more sense this way, because ranged is not a property which would change over time
---
 src/common/settings.h                         | 67 +++++++++----------
 src/yuzu/configuration/config.cpp             | 16 ++---
 src/yuzu/configuration/config.h               | 16 ++---
 src/yuzu/configuration/configuration_shared.h | 10 +--
 src/yuzu_cmd/config.cpp                       |  4 +-
 src/yuzu_cmd/config.h                         |  4 +-
 6 files changed, 59 insertions(+), 58 deletions(-)

diff --git a/src/common/settings.h b/src/common/settings.h
index 3583a2e709..368046e871 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -106,7 +106,7 @@ struct ResolutionScalingInfo {
  * configurations. Specifying a default value and label is required. A minimum and maximum range can
  * be specified for sanitization.
  */
-template <typename Type>
+template <typename Type, bool ranged = false>
 class Setting {
 protected:
     Setting() = default;
@@ -126,8 +126,8 @@ public:
      * @param default_val Intial value of the setting, and default value of the setting
      * @param name Label for the setting
      */
-    explicit Setting(const Type& default_val, const std::string& name)
-        : value{default_val}, default_value{default_val}, ranged{false}, label{name} {}
+    explicit Setting(const Type& default_val, const std::string& name) requires(!ranged)
+        : value{default_val}, default_value{default_val}, label{name} {}
     virtual ~Setting() = default;
 
     /**
@@ -139,9 +139,9 @@ public:
      * @param name Label for the setting
      */
     explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val,
-                     const std::string& name)
-        : value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
-          ranged{true}, label{name} {}
+                     const std::string& name) requires(ranged)
+        : value{default_val},
+          default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {}
 
     /**
      *  Returns a reference to the setting's value.
@@ -158,7 +158,7 @@ public:
      * @param val The desired value
      */
     virtual void SetValue(const Type& val) {
-        Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val};
+        Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
         std::swap(value, temp);
     }
 
@@ -188,7 +188,7 @@ public:
      * @returns A reference to the setting
      */
     virtual const Type& operator=(const Type& val) {
-        Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val};
+        Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
         std::swap(value, temp);
         return value;
     }
@@ -207,7 +207,6 @@ protected:
     const Type default_value{}; ///< The default value
     const Type maximum{};       ///< Maximum allowed value of the setting
     const Type minimum{};       ///< Minimum allowed value of the setting
-    const bool ranged;          ///< The setting has sanitization ranges
     const std::string label{};  ///< The setting's label
 };
 
@@ -219,8 +218,8 @@ protected:
  *
  * By default, the global setting is used.
  */
-template <typename Type>
-class SwitchableSetting : virtual public Setting<Type> {
+template <typename Type, bool ranged = false>
+class SwitchableSetting : virtual public Setting<Type, ranged> {
 public:
     /**
      * Sets a default value, label, and setting value.
@@ -228,7 +227,7 @@ public:
      * @param default_val Intial value of the setting, and default value of the setting
      * @param name Label for the setting
      */
-    explicit SwitchableSetting(const Type& default_val, const std::string& name)
+    explicit SwitchableSetting(const Type& default_val, const std::string& name) requires(!ranged)
         : Setting<Type>{default_val, name} {}
     virtual ~SwitchableSetting() = default;
 
@@ -241,8 +240,8 @@ public:
      * @param name Label for the setting
      */
     explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val,
-                               const std::string& name)
-        : Setting<Type>{default_val, min_val, max_val, name} {}
+                               const std::string& name) requires(ranged)
+        : Setting<Type, true>{default_val, min_val, max_val, name} {}
 
     /**
      * Tells this setting to represent either the global or custom setting when other member
@@ -290,7 +289,7 @@ public:
      * @param val The new value
      */
     void SetValue(const Type& val) override {
-        Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
+        Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
         if (use_global) {
             std::swap(this->value, temp);
         } else {
@@ -306,7 +305,7 @@ public:
      * @returns A reference to the current setting value
      */
     const Type& operator=(const Type& val) override {
-        Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
+        Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
         if (use_global) {
             std::swap(this->value, temp);
             return this->value;
@@ -374,15 +373,15 @@ struct Values {
     Setting<std::string> audio_device_id{"auto", "output_device"};
     Setting<std::string> sink_id{"auto", "output_engine"};
     Setting<bool> audio_muted{false, "audio_muted"};
-    SwitchableSetting<u8> volume{100, 0, 100, "volume"};
+    SwitchableSetting<u8, true> volume{100, 0, 100, "volume"};
 
     // Core
     SwitchableSetting<bool> use_multi_core{true, "use_multi_core"};
     SwitchableSetting<bool> use_extended_memory_layout{false, "use_extended_memory_layout"};
 
     // Cpu
-    SwitchableSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
-                                                CPUAccuracy::Paranoid, "cpu_accuracy"};
+    SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
+                                                      CPUAccuracy::Paranoid, "cpu_accuracy"};
     // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
     Setting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"};
     Setting<bool> cpu_debug_mode{false, "cpu_debug_mode"};
@@ -409,7 +408,7 @@ struct Values {
         true, "cpuopt_unsafe_ignore_global_monitor"};
 
     // Renderer
-    SwitchableSetting<RendererBackend> renderer_backend{
+    SwitchableSetting<RendererBackend, true> renderer_backend{
         RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"};
     Setting<bool> renderer_debug{false, "debug"};
     Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
@@ -423,28 +422,28 @@ struct Values {
     SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"};
     // *nix platforms may have issues with the borderless windowed fullscreen mode.
     // Default to exclusive fullscreen on these platforms for now.
-    SwitchableSetting<FullscreenMode> fullscreen_mode{
+    SwitchableSetting<FullscreenMode, true> fullscreen_mode{
 #ifdef _WIN32
         FullscreenMode::Borderless,
 #else
         FullscreenMode::Exclusive,
 #endif
         FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
-    SwitchableSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"};
-    SwitchableSetting<int> max_anisotropy{0, 0, 5, "max_anisotropy"};
+    SwitchableSetting<int, true> aspect_ratio{0, 0, 3, "aspect_ratio"};
+    SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
     SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
-    SwitchableSetting<u16> speed_limit{100, 0, 9999, "speed_limit"};
+    SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
     SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
-    SwitchableSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
-                                                GPUAccuracy::Extreme, "gpu_accuracy"};
+    SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
+                                                      GPUAccuracy::Extreme, "gpu_accuracy"};
     SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
     SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
     SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
     SwitchableSetting<bool> use_vsync{true, "use_vsync"};
-    SwitchableSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"};
+    SwitchableSetting<u16, true> fps_cap{1000, 1, 1000, "fps_cap"};
     Setting<bool> disable_fps_limit{false, "disable_fps_limit"};
-    SwitchableSetting<ShaderBackend> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
-                                                    ShaderBackend::SPIRV, "shader_backend"};
+    SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
+                                                          ShaderBackend::SPIRV, "shader_backend"};
     SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
     SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
 
@@ -460,10 +459,10 @@ struct Values {
     s64 custom_rtc_differential;
 
     Setting<s32> current_user{0, "current_user"};
-    SwitchableSetting<s32> language_index{1, 0, 17, "language_index"};
-    SwitchableSetting<s32> region_index{1, 0, 6, "region_index"};
-    SwitchableSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"};
-    SwitchableSetting<s32> sound_index{1, 0, 2, "sound_index"};
+    SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"};
+    SwitchableSetting<s32, true> region_index{1, 0, 6, "region_index"};
+    SwitchableSetting<s32, true> time_zone_index{0, 0, 45, "time_zone_index"};
+    SwitchableSetting<s32, true> sound_index{1, 0, 2, "sound_index"};
 
     // Controls
     InputSetting<std::array<PlayerInput, 10>> players;
@@ -485,7 +484,7 @@ struct Values {
     Setting<bool> tas_loop{false, "tas_loop"};
 
     Setting<bool> mouse_panning{false, "mouse_panning"};
-    Setting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
+    Setting<u8, true> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
     Setting<bool> mouse_enabled{false, "mouse_enabled"};
 
     Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 9686412d07..a57b2e019d 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -143,8 +143,8 @@ void Config::ReadBasicSetting(Settings::Setting<std::string>& setting) {
     }
 }
 
-template <typename Type>
-void Config::ReadBasicSetting(Settings::Setting<Type>& setting) {
+template <typename Type, bool ranged>
+void Config::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) {
     const QString name = QString::fromStdString(setting.GetLabel());
     const Type default_value = setting.GetDefault();
     if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) {
@@ -164,16 +164,16 @@ void Config::WriteBasicSetting(const Settings::Setting<std::string>& setting) {
     qt_config->setValue(name, QString::fromStdString(value));
 }
 
-template <typename Type>
-void Config::WriteBasicSetting(const Settings::Setting<Type>& setting) {
+template <typename Type, bool ranged>
+void Config::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
     const QString name = QString::fromStdString(setting.GetLabel());
     const Type value = setting.GetValue();
     qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
     qt_config->setValue(name, value);
 }
 
-template <typename Type>
-void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type>& setting) {
+template <typename Type, bool ranged>
+void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
     const QString name = QString::fromStdString(setting.GetLabel());
     const Type& value = setting.GetValue(global);
     if (!global) {
@@ -1421,8 +1421,8 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value)
     return result;
 }
 
-template <typename Type>
-void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type>& setting) {
+template <typename Type, bool ranged>
+void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting) {
     QString name = QString::fromStdString(setting.GetLabel());
     const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
     setting.SetGlobal(use_global);
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 9ca878d232..d511b3dbd9 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -159,8 +159,8 @@ private:
      *
      * @param The setting
      */
-    template <typename Type>
-    void ReadGlobalSetting(Settings::SwitchableSetting<Type>& setting);
+    template <typename Type, bool ranged>
+    void ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting);
 
     /**
      * Sets a value to the qt_config using the setting's label and default value. If the config is a
@@ -168,8 +168,8 @@ private:
      *
      * @param The setting
      */
-    template <typename Type>
-    void WriteGlobalSetting(const Settings::SwitchableSetting<Type>& setting);
+    template <typename Type, bool ranged>
+    void WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting);
 
     /**
      * Reads a value from the qt_config using the setting's label and default value and applies the
@@ -177,15 +177,15 @@ private:
      *
      * @param The setting
      */
-    template <typename Type>
-    void ReadBasicSetting(Settings::Setting<Type>& setting);
+    template <typename Type, bool ranged>
+    void ReadBasicSetting(Settings::Setting<Type, ranged>& setting);
 
     /** Sets a value from the setting in the qt_config using the setting's label and default value.
      *
      * @param The setting
      */
-    template <typename Type>
-    void WriteBasicSetting(const Settings::Setting<Type>& setting);
+    template <typename Type, bool ranged>
+    void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
 
     ConfigType type;
     std::unique_ptr<QSettings> qt_config;
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index 77802a367b..56800b6ff4 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -27,8 +27,9 @@ enum class CheckState {
 // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting
 void ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, const QCheckBox* checkbox,
                          const CheckState& tracker);
-template <typename Type>
-void ApplyPerGameSetting(Settings::SwitchableSetting<Type>* setting, const QComboBox* combobox) {
+template <typename Type, bool ranged>
+void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting,
+                         const QComboBox* combobox) {
     if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
         setting->SetValue(static_cast<Type>(combobox->currentIndex()));
     } else if (!Settings::IsConfiguringGlobal()) {
@@ -45,8 +46,9 @@ void ApplyPerGameSetting(Settings::SwitchableSetting<Type>* setting, const QComb
 // Sets a Qt UI element given a Settings::Setting
 void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>* setting);
 
-template <typename Type>
-void SetPerGameSetting(QComboBox* combobox, const Settings::SwitchableSetting<Type>* setting) {
+template <typename Type, bool ranged>
+void SetPerGameSetting(QComboBox* combobox,
+                       const Settings::SwitchableSetting<Type, ranged>* setting) {
     combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
                                                      : static_cast<int>(setting->GetValue()) +
                                                            ConfigurationShared::USE_GLOBAL_OFFSET);
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 903e022972..9db7115a20 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -99,8 +99,8 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& sett
     setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
 }
 
-template <typename Type>
-void Config::ReadSetting(const std::string& group, Settings::Setting<Type>& setting) {
+template <typename Type, bool ranged>
+void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
     setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
                                                         static_cast<long>(setting.GetDefault())));
 }
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h
index ccf77d6684..32c03075f5 100644
--- a/src/yuzu_cmd/config.h
+++ b/src/yuzu_cmd/config.h
@@ -33,6 +33,6 @@ private:
      * @param group The name of the INI group
      * @param setting The yuzu setting to modify
      */
-    template <typename Type>
-    void ReadSetting(const std::string& group, Settings::Setting<Type>& setting);
+    template <typename Type, bool ranged>
+    void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
 };