更新
This commit is contained in:
+284
-302
@@ -1,319 +1,301 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include "magic_enum/include/magic_enum/magic_enum.hpp"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "remove_const.hpp"
|
||||
#include <sstream>
|
||||
#include "Core/Base/global_include.h"
|
||||
|
||||
|
||||
#include "magic_enum/include/magic_enum/magic_enum.hpp"
|
||||
#include "remove_const.hpp"
|
||||
namespace Psc {
|
||||
template<class T>
|
||||
class Copyable_Atomic {
|
||||
public:
|
||||
using value_type = T;
|
||||
Copyable_Atomic() = default;
|
||||
Copyable_Atomic(T value) : value_(value) {}
|
||||
Copyable_Atomic(const Copyable_Atomic& other) : value_(other.load()) {}
|
||||
Copyable_Atomic& operator=(const Copyable_Atomic& other) {
|
||||
store(other.load());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Copyable_Atomic& operator=(T value) {
|
||||
store(value);
|
||||
return *this;
|
||||
}
|
||||
T load(std::memory_order order = std::memory_order_seq_cst) const {
|
||||
return value_.load(order);
|
||||
}
|
||||
void store(T value, std::memory_order order = std::memory_order_seq_cst) {
|
||||
value_.store(value, order);
|
||||
}
|
||||
operator T() const {
|
||||
return load();
|
||||
}
|
||||
private:
|
||||
std::atomic<T> value_{};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
namespace PV {
|
||||
template<typename T> struct is_copyable_atomic_helper : std::false_type {};
|
||||
template<typename U> struct is_copyable_atomic_helper<Copyable_Atomic<U>> : std::true_type {};
|
||||
template<typename T> struct is_copyable_atomic : is_copyable_atomic_helper<clean_t<T>> {};
|
||||
template<typename T> struct copyable_atomic_value;
|
||||
template<typename U> struct copyable_atomic_value<Copyable_Atomic<U>> {
|
||||
using type = U;
|
||||
};
|
||||
template <class T>
|
||||
class Copyable_Atomic {
|
||||
public:
|
||||
using value_type = T;
|
||||
Copyable_Atomic() = default;
|
||||
Copyable_Atomic(T value) : value_(value) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic<T>::value;
|
||||
|
||||
template<typename T>
|
||||
using copyable_atomic_value_t = typename PV::copyable_atomic_value<clean_t<T>>::type;
|
||||
|
||||
template<typename T> struct always_false : std::false_type {};
|
||||
template<typename T> using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
namespace PV {
|
||||
template<typename T> struct is_optional_helper : std::false_type {};
|
||||
template<typename U> struct is_optional_helper<std::optional<U>> : std::true_type {};
|
||||
template<typename T> struct is_optional : is_optional_helper<clean_t<T>> {};
|
||||
template<typename T> struct optional_value;
|
||||
template<typename U> struct optional_value<std::optional<U>> {
|
||||
using type = U;
|
||||
};
|
||||
Copyable_Atomic(const Copyable_Atomic& other) : value_(other.load()) {
|
||||
}
|
||||
template<typename T> constexpr bool is_optional_v = PV::is_optional<T>::value;
|
||||
template<typename T> using optional_value_t = typename PV::optional_value<clean_t<T>>::type;
|
||||
|
||||
namespace PV {
|
||||
template<typename T> struct is_atomic_helper : std::false_type {};
|
||||
template<typename U> struct is_atomic_helper<std::atomic<U>> : std::true_type {};
|
||||
template<typename T> struct is_atomic : is_atomic_helper<clean_t<T>> {};
|
||||
template<typename T> struct atomic_value;
|
||||
template<typename U> struct atomic_value<std::atomic<U>> {
|
||||
using type = U;
|
||||
};
|
||||
Copyable_Atomic& operator=(const Copyable_Atomic& other) {
|
||||
store(other.load());
|
||||
return *this;
|
||||
}
|
||||
template<typename T> constexpr bool is_atomic_v = PV::is_atomic<T>::value;
|
||||
template<typename T> using atomic_value_t = typename PV::atomic_value<clean_t<T>>::type;
|
||||
|
||||
|
||||
namespace PV {
|
||||
template<typename T> struct is_shared_ptr_helper : std::false_type {};
|
||||
template<typename U> struct is_shared_ptr_helper<std::shared_ptr<U>> : std::true_type {};
|
||||
template<typename T> struct is_shared_ptr : is_shared_ptr_helper<clean_t<T>> {};
|
||||
|
||||
template<typename T> struct shared_ptr_value;
|
||||
template<typename U> struct shared_ptr_value<std::shared_ptr<U>> { using type = U; };
|
||||
Copyable_Atomic& operator=(T value) {
|
||||
store(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> constexpr bool is_shared_ptr_v = PV::is_shared_ptr<T>::value;
|
||||
template<typename T> using shared_ptr_value_t = typename PV::shared_ptr_value<clean_t<T>>::type;
|
||||
|
||||
|
||||
// 泛型函数:将枚举类型和所有值转换为字符串,并返回
|
||||
template <typename EnumType>
|
||||
std::string get_enum_def_str() {
|
||||
std::string result;
|
||||
result += "enum " + std::string(magic_enum::enum_type_name<EnumType>());
|
||||
result += "{\n";
|
||||
for (auto e : magic_enum::enum_values<EnumType>()) {
|
||||
result += "\t";
|
||||
result += magic_enum::enum_name(e); // 获取枚举值的名字
|
||||
result += "\n";
|
||||
T load(std::memory_order order = std::memory_order_seq_cst) const {
|
||||
return value_.load(order);
|
||||
}
|
||||
void store(T value, std::memory_order order = std::memory_order_seq_cst) {
|
||||
value_.store(value, order);
|
||||
}
|
||||
operator T() const {
|
||||
return load();
|
||||
}
|
||||
private:
|
||||
std::atomic<T> value_{};
|
||||
};
|
||||
template <typename T>
|
||||
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
namespace PV {
|
||||
template <typename T>
|
||||
struct is_copyable_atomic_helper : std::false_type {};
|
||||
template <typename U>
|
||||
struct is_copyable_atomic_helper<Copyable_Atomic<U>> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_copyable_atomic : is_copyable_atomic_helper<clean_t<T>> {};
|
||||
template <typename T>
|
||||
struct copyable_atomic_value;
|
||||
template <typename U>
|
||||
struct copyable_atomic_value<Copyable_Atomic<U>> {
|
||||
using type = U;
|
||||
};
|
||||
} // namespace PV
|
||||
template <typename T>
|
||||
constexpr bool is_copyable_atomic_v = PV::is_copyable_atomic<T>::value;
|
||||
template <typename T>
|
||||
using copyable_atomic_value_t = typename PV::copyable_atomic_value<clean_t<T>>::type;
|
||||
template <typename T>
|
||||
struct always_false : std::false_type {};
|
||||
template <typename T>
|
||||
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
namespace PV {
|
||||
template <typename T>
|
||||
struct is_optional_helper : std::false_type {};
|
||||
template <typename U>
|
||||
struct is_optional_helper<std::optional<U>> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_optional : is_optional_helper<clean_t<T>> {};
|
||||
template <typename T>
|
||||
struct optional_value;
|
||||
template <typename U>
|
||||
struct optional_value<std::optional<U>> {
|
||||
using type = U;
|
||||
};
|
||||
} // namespace PV
|
||||
template <typename T>
|
||||
constexpr bool is_optional_v = PV::is_optional<T>::value;
|
||||
template <typename T>
|
||||
using optional_value_t = typename PV::optional_value<clean_t<T>>::type;
|
||||
namespace PV {
|
||||
template <typename T>
|
||||
struct is_atomic_helper : std::false_type {};
|
||||
template <typename U>
|
||||
struct is_atomic_helper<std::atomic<U>> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_atomic : is_atomic_helper<clean_t<T>> {};
|
||||
template <typename T>
|
||||
struct atomic_value;
|
||||
template <typename U>
|
||||
struct atomic_value<std::atomic<U>> {
|
||||
using type = U;
|
||||
};
|
||||
} // namespace PV
|
||||
template <typename T>
|
||||
constexpr bool is_atomic_v = PV::is_atomic<T>::value;
|
||||
template <typename T>
|
||||
using atomic_value_t = typename PV::atomic_value<clean_t<T>>::type;
|
||||
namespace PV {
|
||||
template <typename T>
|
||||
struct is_shared_ptr_helper : std::false_type {};
|
||||
template <typename U>
|
||||
struct is_shared_ptr_helper<std::shared_ptr<U>> : std::true_type {};
|
||||
template <typename T>
|
||||
struct is_shared_ptr : is_shared_ptr_helper<clean_t<T>> {};
|
||||
template <typename T>
|
||||
struct shared_ptr_value;
|
||||
template <typename U>
|
||||
struct shared_ptr_value<std::shared_ptr<U>> {
|
||||
using type = U;
|
||||
};
|
||||
} // namespace PV
|
||||
template <typename T>
|
||||
constexpr bool is_shared_ptr_v = PV::is_shared_ptr<T>::value;
|
||||
template <typename T>
|
||||
using shared_ptr_value_t = typename PV::shared_ptr_value<clean_t<T>>::type;
|
||||
// 泛型函数:将枚举类型和所有值转换为字符串,并返回
|
||||
template <typename EnumType>
|
||||
std::string get_enum_def_str() {
|
||||
std::string result;
|
||||
result += "enum " + std::string(magic_enum::enum_type_name<EnumType>());
|
||||
result += "{\n";
|
||||
for (auto e : magic_enum::enum_values<EnumType>()) {
|
||||
result += "\t";
|
||||
result += magic_enum::enum_name(e); // 获取枚举值的名字
|
||||
result += "\n";
|
||||
}
|
||||
result += "}\n";
|
||||
return result;
|
||||
}
|
||||
template <typename EnumType>
|
||||
EnumType to_enum(const std::string& str) {
|
||||
auto opt = magic_enum::enum_cast<EnumType>(str);
|
||||
if (opt.has_value()) {
|
||||
return opt.value(); // 返回枚举值
|
||||
}
|
||||
std::cerr << std::string(magic_enum::enum_type_name<EnumType>()) + " 字符串转换枚举值错误!str:[" + str + "]\n" +
|
||||
get_enum_def_str<EnumType>() + "\n";
|
||||
Psc::fail_fast("");
|
||||
return EnumType();
|
||||
}
|
||||
template <typename EnumType>
|
||||
std::optional<EnumType> to_enum2(const std::string& str) {
|
||||
auto opt = magic_enum::enum_cast<EnumType>(str);
|
||||
if (opt.has_value()) {
|
||||
return opt.value(); // 返回枚举值
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
// 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。
|
||||
template <typename, typename = void>
|
||||
struct has_free_to_string : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_free_to_string<T, std::void_t<decltype(other_to_string(std::declval<T>()))>> : std::true_type {};
|
||||
template <typename, typename = void>
|
||||
struct has_member_to_string : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_member_to_string<T, std::void_t<decltype(std::declval<T>().to_string())>> : std::true_type {};
|
||||
template <typename T, typename decay = std::decay_t<T>,
|
||||
typename C = remove_recursive_top_const_t<remove_recursive_low_const_t<decay>>>
|
||||
std::string to_string(T&& v) {
|
||||
// 处理 std::string
|
||||
if constexpr (std::is_same_v<C, std::string>) {
|
||||
return std::forward<T>(v);
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, void*>) {
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex
|
||||
<< reinterpret_cast<std::uintptr_t>(v);
|
||||
return ss.str();
|
||||
}
|
||||
// 处理 char* 类型
|
||||
else if constexpr (std::is_same_v<C, char*>) {
|
||||
return std::string(v);
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, const char*>) {
|
||||
return std::string(v);
|
||||
}
|
||||
// 处理 wchar_t* 类型
|
||||
else if constexpr (std::is_same_v<C, wchar_t*>) {
|
||||
std::wstring ws(v);
|
||||
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, const wchar_t*>) {
|
||||
std::wstring ws(v);
|
||||
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
|
||||
}
|
||||
// 处理 std::wstring 类型
|
||||
else if constexpr (std::is_same_v<C, std::wstring>) {
|
||||
return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string
|
||||
}
|
||||
// 处理枚举类型
|
||||
else if constexpr (std::is_enum_v<C>) {
|
||||
return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举
|
||||
}
|
||||
// 处理 bool 类型
|
||||
else if constexpr (std::is_same_v<C, bool>) {
|
||||
return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换
|
||||
}
|
||||
// 处理 std::nullptr_t 类型
|
||||
else if constexpr (std::is_same_v<C, std::nullptr_t>) {
|
||||
return std::string("null"); // 对 nullptr 做特殊处理
|
||||
}
|
||||
// 处理算术类型(整数或浮点数)
|
||||
else if constexpr (std::is_arithmetic_v<C>) {
|
||||
return std::to_string(v); // 使用 std::to_string 转换数值类型
|
||||
}
|
||||
else if constexpr (is_atomic_v<C>) {
|
||||
return to_string(v.load());
|
||||
}
|
||||
else if constexpr (is_copyable_atomic_v<C>) {
|
||||
return to_string(v.load());
|
||||
}
|
||||
else if constexpr (is_optional_v<C>) {
|
||||
return v.has_value() ? to_string(v.value()) : "nullopt";
|
||||
}
|
||||
else if constexpr (is_shared_ptr_v<C>) {
|
||||
if (v) {
|
||||
return v->to_string();
|
||||
}
|
||||
result += "}\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename EnumType>
|
||||
EnumType to_enum(const std::string& str) {
|
||||
auto opt = magic_enum::enum_cast<EnumType>(str);
|
||||
if (opt.has_value()) {
|
||||
return opt.value(); // 返回枚举值
|
||||
else {
|
||||
return std::string("null");
|
||||
}
|
||||
std::cerr << std::string(magic_enum::enum_type_name<EnumType>()) +
|
||||
" 字符串转换枚举值错误!str:" + str + "\n" +
|
||||
get_enum_def_str<EnumType>()
|
||||
+ "\n";
|
||||
Psc::fail_fast("");
|
||||
|
||||
return EnumType();
|
||||
}
|
||||
|
||||
template <typename EnumType>
|
||||
std::optional<EnumType> to_enum2(const std::string& str) {
|
||||
auto opt = magic_enum::enum_cast<EnumType>(str);
|
||||
if (opt.has_value()) {
|
||||
return opt.value(); // 返回枚举值
|
||||
else {
|
||||
// 没有匹配上 最后走这条路径
|
||||
if constexpr (has_free_to_string<C>::value) {
|
||||
return other_to_string(v);
|
||||
}
|
||||
else if constexpr (has_member_to_string<C>::value) {
|
||||
return v.to_string();
|
||||
}
|
||||
else {
|
||||
static_assert(sizeof(C) == 0, "Psc to_string not available for this type");
|
||||
}
|
||||
}
|
||||
return std::string("");
|
||||
}
|
||||
template <typename EnumType>
|
||||
std::optional<EnumType> int_to_enum(int enum_value) {
|
||||
// 静态断言,确保 EnumType 是枚举类型
|
||||
static_assert(std::is_enum_v<EnumType>, "EnumType must be an enum type");
|
||||
// 使用 magic_enum 获取所有的枚举值
|
||||
auto enum_values = magic_enum::enum_values<EnumType>();
|
||||
// 检查是否存在匹配的枚举值
|
||||
for (auto value : enum_values) {
|
||||
if (static_cast<int>(value) == enum_value) {
|
||||
return value; // 返回匹配的枚举值
|
||||
}
|
||||
}
|
||||
// 如果没有匹配的枚举值,返回 std::nullopt
|
||||
return std::nullopt;
|
||||
}
|
||||
template <typename EnumType>
|
||||
std::optional<std::string> enum_int_to_string(int enum_value) {
|
||||
auto tmp = int_to_enum<EnumType>(enum_value);
|
||||
if (!tmp.has_value())
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 其余未考虑到的类型直接实现 other_to_string(T) 就可以了。
|
||||
template<typename, typename = void>
|
||||
struct has_free_to_string : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct has_free_to_string<T,
|
||||
std::void_t<decltype(other_to_string(std::declval<T>()))>
|
||||
> : std::true_type {};
|
||||
|
||||
template<typename, typename = void>
|
||||
struct has_member_to_string : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct has_member_to_string<T,
|
||||
std::void_t<decltype(std::declval<T>().to_string())>
|
||||
> : std::true_type {};
|
||||
|
||||
|
||||
template <typename T,
|
||||
typename decay = std::decay_t<T>,
|
||||
typename C = remove_recursive_top_const_t<remove_recursive_low_const_t<decay>>
|
||||
>
|
||||
std::string to_string(T&& v) {
|
||||
// 处理 std::string
|
||||
if constexpr (std::is_same_v<C, std::string>) {
|
||||
return std::forward<T>(v);
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, void*>) {
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::setw(sizeof(void*) * 2) << std::setfill('0') << std::hex << reinterpret_cast<std::uintptr_t>(v);
|
||||
return ss.str();
|
||||
}
|
||||
// 处理 char* 类型
|
||||
else if constexpr (std::is_same_v<C, char*>) {
|
||||
return std::string(v);
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, const char*>) {
|
||||
return std::string(v);
|
||||
}
|
||||
// 处理 wchar_t* 类型
|
||||
else if constexpr (std::is_same_v<C, wchar_t*>) {
|
||||
std::wstring ws(v);
|
||||
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
|
||||
}
|
||||
else if constexpr (std::is_same_v<C, const wchar_t*>) {
|
||||
std::wstring ws(v);
|
||||
return std::string(ws.begin(), ws.end()); // 简单转换为 std::string
|
||||
}
|
||||
// 处理 std::wstring 类型
|
||||
else if constexpr (std::is_same_v<C, std::wstring>) {
|
||||
return std::string(v.begin(), v.end()); // 将 std::wstring 转为 std::string
|
||||
}
|
||||
// 处理枚举类型
|
||||
else if constexpr (std::is_enum_v<C>) {
|
||||
return std::string(magic_enum::enum_name(v)); // 使用 magic_enum 转换枚举
|
||||
}
|
||||
// 处理 bool 类型
|
||||
else if constexpr (std::is_same_v<C, bool>) {
|
||||
return v ? std::string("true") : std::string("false"); // 对 bool 类型进行自定义转换
|
||||
}
|
||||
// 处理 std::nullptr_t 类型
|
||||
else if constexpr (std::is_same_v<C, std::nullptr_t>) {
|
||||
return std::string("null"); // 对 nullptr 做特殊处理
|
||||
}
|
||||
// 处理算术类型(整数或浮点数)
|
||||
else if constexpr (std::is_arithmetic_v<C>) {
|
||||
return std::to_string(v); // 使用 std::to_string 转换数值类型
|
||||
}
|
||||
else if constexpr (is_atomic_v<C>) {
|
||||
return to_string(v.load());
|
||||
}
|
||||
else if constexpr (is_copyable_atomic_v<C>) {
|
||||
return to_string(v.load());
|
||||
}
|
||||
else if constexpr (is_optional_v<C>) {
|
||||
return v.has_value() ? to_string(v.value()) : "nullopt";
|
||||
}
|
||||
else if constexpr (is_shared_ptr_v<C>) {
|
||||
if (v) {
|
||||
return v->to_string();
|
||||
} else {
|
||||
return std::string("null");
|
||||
}
|
||||
} else {
|
||||
// 没有匹配上 最后走这条路径
|
||||
if constexpr (has_free_to_string<C>::value) {
|
||||
return other_to_string(v);
|
||||
}
|
||||
else if constexpr (has_member_to_string<C>::value) {
|
||||
return v.to_string();
|
||||
} else {
|
||||
static_assert(sizeof(C) == 0, "Psc to_string not available for this type");
|
||||
}
|
||||
}
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename EnumType>
|
||||
std::optional<EnumType> int_to_enum(int enum_value) {
|
||||
// 静态断言,确保 EnumType 是枚举类型
|
||||
static_assert(std::is_enum_v<EnumType>, "EnumType must be an enum type");
|
||||
// 使用 magic_enum 获取所有的枚举值
|
||||
auto enum_values = magic_enum::enum_values<EnumType>();
|
||||
// 检查是否存在匹配的枚举值
|
||||
for (auto value : enum_values) {
|
||||
if (static_cast<int>(value) == enum_value) {
|
||||
return value; // 返回匹配的枚举值
|
||||
}
|
||||
}
|
||||
// 如果没有匹配的枚举值,返回 std::nullopt
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename EnumType>
|
||||
std::optional<std::string> enum_int_to_string(int enum_value) {
|
||||
auto tmp = int_to_enum<EnumType>(enum_value);
|
||||
if (!tmp.has_value()) return std::nullopt;
|
||||
return to_string(tmp.value());
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
std::vector<Enum> split_flags(Enum flags)
|
||||
{
|
||||
static_assert(std::is_enum_v<Enum>, "Template parameter must be an enum type");
|
||||
std::vector<Enum> setFlags;
|
||||
for (auto flag : magic_enum::enum_values<Enum>())
|
||||
{
|
||||
if ((flags & flag) == flag)
|
||||
{
|
||||
setFlags.push_back(flag);
|
||||
}
|
||||
}
|
||||
return setFlags;
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
class enum_error_category : public std::error_category {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum");
|
||||
|
||||
public:
|
||||
const char* name() const noexcept override {
|
||||
// enum_type_name 返回 string_view,静态存储即可
|
||||
static constexpr auto name_sv = magic_enum::enum_type_name<E>();
|
||||
return name_sv.data();
|
||||
}
|
||||
|
||||
std::string message(int ev) const override {
|
||||
auto opt = magic_enum::enum_name(static_cast<E>(ev));
|
||||
if (!opt.empty())
|
||||
return std::string(opt);
|
||||
Psc::fail_fast_core_dump();
|
||||
return "unknown enum error";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
std::error_code make_ec(E e) {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum");
|
||||
static enum_error_category<E> cat;
|
||||
return {static_cast<int>(e), cat};
|
||||
}
|
||||
inline std::error_code get_sys_ec() {
|
||||
return std::error_code(get_error_code(), std::system_category());
|
||||
}
|
||||
|
||||
inline unexpected<std::error_code> get_sys_ex() {
|
||||
return unexpected<std::error_code>(get_sys_ec());
|
||||
return to_string(tmp.value());
|
||||
}
|
||||
template <typename Enum>
|
||||
std::vector<Enum> split_flags(Enum flags) {
|
||||
static_assert(std::is_enum_v<Enum>, "Template parameter must be an enum type");
|
||||
std::vector<Enum> setFlags;
|
||||
for (auto flag : magic_enum::enum_values<Enum>()) {
|
||||
if ((flags & flag) == flag) {
|
||||
setFlags.push_back(flag);
|
||||
}
|
||||
}
|
||||
return setFlags;
|
||||
}
|
||||
template <typename E>
|
||||
class enum_error_category : public std::error_category {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum");
|
||||
public:
|
||||
const char* name() const noexcept override {
|
||||
// enum_type_name 返回 string_view,静态存储即可
|
||||
static constexpr auto name_sv = magic_enum::enum_type_name<E>();
|
||||
return name_sv.data();
|
||||
}
|
||||
std::string message(int ev) const override {
|
||||
auto opt = magic_enum::enum_name(static_cast<E>(ev));
|
||||
if (!opt.empty())
|
||||
return std::string(opt);
|
||||
Psc::fail_fast_core_dump();
|
||||
return "unknown enum error";
|
||||
}
|
||||
};
|
||||
template <typename E>
|
||||
std::error_code make_ec(E e) {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum");
|
||||
static enum_error_category<E> cat;
|
||||
return {static_cast<int>(e), cat};
|
||||
}
|
||||
inline std::error_code get_sys_ec() {
|
||||
return std::error_code(get_error_code(), std::system_category());
|
||||
}
|
||||
inline unexpected<std::error_code> get_sys_ex() {
|
||||
return unexpected<std::error_code>(get_sys_ec());
|
||||
}
|
||||
} // namespace Psc
|
||||
|
||||
Reference in New Issue
Block a user