StringUtil: Use concepts instead of enable_if.

This commit is contained in:
Jordan Woyak 2025-04-03 17:46:31 -05:00
parent e4525ca7ee
commit 20874124c2
2 changed files with 18 additions and 27 deletions

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <charconv> #include <charconv>
#include <concepts>
#include <cstdarg> #include <cstdarg>
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
@ -18,22 +19,8 @@
#include <vector> #include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/EnumUtils.h"
namespace detail #include "Common/TypeUtils.h"
{
template <typename T>
constexpr bool IsBooleanEnum()
{
if constexpr (std::is_enum_v<T>)
{
return std::is_same_v<std::underlying_type_t<T>, bool>;
}
else
{
return false;
}
}
} // namespace detail
std::string StringFromFormatV(const char* format, va_list args); std::string StringFromFormatV(const char* format, va_list args);
@ -73,7 +60,7 @@ void TruncateToCString(std::string* s);
bool TryParse(const std::string& str, bool* output); bool TryParse(const std::string& str, bool* output);
template <typename T> template <typename T>
requires(std::is_integral_v<T> || (std::is_enum_v<T> && !detail::IsBooleanEnum<T>())) requires(std::is_integral_v<T> || (std::is_enum_v<T> && !Common::BooleanEnum<T>))
bool TryParse(const std::string& str, T* output, int base = 0) bool TryParse(const std::string& str, T* output, int base = 0)
{ {
char* end_ptr = nullptr; char* end_ptr = nullptr;
@ -111,8 +98,7 @@ bool TryParse(const std::string& str, T* output, int base = 0)
return true; return true;
} }
template <typename T> template <Common::BooleanEnum T>
requires(detail::IsBooleanEnum<T>())
bool TryParse(const std::string& str, T* output) bool TryParse(const std::string& str, T* output)
{ {
bool value; bool value;
@ -123,7 +109,7 @@ bool TryParse(const std::string& str, T* output)
return true; return true;
} }
template <typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr> template <std::floating_point T>
bool TryParse(std::string str, T* const output) bool TryParse(std::string str, T* const output)
{ {
// Replace commas with dots. // Replace commas with dots.
@ -169,10 +155,9 @@ std::string ValueToString(double value);
std::string ValueToString(int value); std::string ValueToString(int value);
std::string ValueToString(s64 value); std::string ValueToString(s64 value);
std::string ValueToString(bool value); std::string ValueToString(bool value);
template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr> std::string ValueToString(Common::Enum auto value)
std::string ValueToString(T value)
{ {
return ValueToString(static_cast<std::underlying_type_t<T>>(value)); return ValueToString(Common::ToUnderlying(value));
} }
// Generates an hexdump-like representation of a binary data blob. // Generates an hexdump-like representation of a binary data blob.
@ -180,15 +165,13 @@ std::string HexDump(const u8* data, size_t size);
namespace Common namespace Common
{ {
template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr> std::from_chars_result FromChars(std::string_view sv, std::integral auto& value, int base = 10)
std::from_chars_result FromChars(std::string_view sv, T& value, int base = 10)
{ {
const char* const first = sv.data(); const char* const first = sv.data();
const char* const last = first + sv.size(); const char* const last = first + sv.size();
return std::from_chars(first, last, value, base); return std::from_chars(first, last, value, base);
} }
template <typename T, typename std::enable_if_t<std::is_floating_point_v<T>>* = nullptr> std::from_chars_result FromChars(std::string_view sv, std::floating_point auto& value,
std::from_chars_result FromChars(std::string_view sv, T& value,
std::chars_format fmt = std::chars_format::general) std::chars_format fmt = std::chars_format::general)
{ {
const char* const first = sv.data(); const char* const first = sv.data();

View file

@ -133,4 +133,12 @@ private:
} m_value; } m_value;
}; };
template <typename T>
concept Enum = std::is_enum_v<T>;
template <typename T, typename Underlying>
concept TypedEnum = std::is_same_v<std::underlying_type_t<T>, Underlying>;
template <typename T>
concept BooleanEnum = TypedEnum<T, bool>;
} // namespace Common } // namespace Common