summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Config
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2018-05-11 22:38:44 +0200
committerLéo Lam <leo@innovatetechnologi.es>2018-05-12 18:10:26 +0200
commit6763a3fce1df5a949900dd976393c7fe89fa4aec (patch)
treecdf3ad1c04d6746d62d7f53ff0a2c46e547727b9 /Source/Core/Common/Config
parent7dca7c237eb9ae40765e581317df6df4b4fc1ad4 (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.h23
-rw-r--r--Source/Core/Common/Config/Layer.h17
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)
{