diff options
| author | Léo Lam <leo@innovatetechnologi.es> | 2018-05-11 22:38:44 +0200 |
|---|---|---|
| committer | Léo Lam <leo@innovatetechnologi.es> | 2018-05-12 18:10:26 +0200 |
| commit | 6763a3fce1df5a949900dd976393c7fe89fa4aec (patch) | |
| tree | cdf3ad1c04d6746d62d7f53ff0a2c46e547727b9 /Source/Core/Common/Config | |
| parent | 7dca7c237eb9ae40765e581317df6df4b4fc1ad4 (diff) | |
Config: Add support for enums
This makes it possible to use enums as the config type.
Default values are now clearer and there's no need for casts
when calling Config::Get/Set anymore.
In order to add support for enums, the common code was updated to
handle enums by using the underlying type when loading/saving settings.
A copy constructor is also provided for conversions from
`ConfigInfo<Enum>` to `ConfigInfo<underlying_type<Enum>>`
so that enum settings can still easily work with code that doesn't care
about the actual enum values (like Graphics{Choice,Radio} in DolphinQt2
which only treat the setting as an integer).
Diffstat (limited to 'Source/Core/Common/Config')
| -rw-r--r-- | Source/Core/Common/Config/ConfigInfo.h | 23 | ||||
| -rw-r--r-- | Source/Core/Common/Config/Layer.h | 17 |
2 files changed, 39 insertions, 1 deletions
diff --git a/Source/Core/Common/Config/ConfigInfo.h b/Source/Core/Common/Config/ConfigInfo.h index fc36ecee03..c5c4cc49a1 100644 --- a/Source/Core/Common/Config/ConfigInfo.h +++ b/Source/Core/Common/Config/ConfigInfo.h @@ -5,11 +5,19 @@ #pragma once #include <string> +#include <type_traits> #include "Common/Config/Enums.h" namespace Config { +namespace detail +{ +// std::underlying_type may only be used with enum types, so make sure T is an enum type first. +template <typename T> +using UnderlyingType = typename std::enable_if_t<std::is_enum<T>{}, std::underlying_type<T>>::type; +} // namespace detail + struct ConfigLocation { System system; @@ -24,6 +32,21 @@ struct ConfigLocation template <typename T> struct ConfigInfo { + ConfigInfo(const ConfigLocation& location_, const T& default_value_) + : location{location_}, default_value{default_value_} + { + } + + // Make it easy to convert ConfigInfo<Enum> into ConfigInfo<UnderlyingType<Enum>> + // so that enum settings can still easily work with code that doesn't care about the enum values. + template <typename Enum, + std::enable_if_t<std::is_same<T, detail::UnderlyingType<Enum>>::value>* = nullptr> + ConfigInfo(const ConfigInfo<Enum>& other) + : location{other.location}, default_value{static_cast<detail::UnderlyingType<Enum>>( + other.default_value)} + { + } + ConfigLocation location; T default_value; }; diff --git a/Source/Core/Common/Config/Layer.h b/Source/Core/Common/Config/Layer.h index e2af6a24ae..3e01b83fed 100644 --- a/Source/Core/Common/Config/Layer.h +++ b/Source/Core/Common/Config/Layer.h @@ -8,6 +8,7 @@ #include <memory> #include <optional> #include <string> +#include <type_traits> #include <vector> #include "Common/Config/ConfigInfo.h" @@ -25,8 +26,13 @@ std::string ValueToString(double value); std::string ValueToString(int value); std::string ValueToString(bool value); std::string ValueToString(const std::string& value); +template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr> +std::string ValueToString(T value) +{ + return ValueToString(static_cast<std::underlying_type_t<T>>(value)); +} -template <typename T> +template <typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr> std::optional<T> TryParse(const std::string& str_value) { T value; @@ -35,6 +41,15 @@ std::optional<T> TryParse(const std::string& str_value) return value; } +template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr> +std::optional<T> TryParse(const std::string& str_value) +{ + const auto result = TryParse<std::underlying_type_t<T>>(str_value); + if (result) + return static_cast<T>(*result); + return {}; +} + template <> inline std::optional<std::string> TryParse(const std::string& str_value) { |
