268 lines
9.5 KiB
C++
268 lines
9.5 KiB
C++
#pragma once
|
|
|
|
|
|
|
|
#include "magic_enum/include/magic_enum/magic_enum.hpp"
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#include <memory>
|
|
|
|
#include "remove_const.hpp"
|
|
|
|
|
|
namespace Psc {
|
|
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;
|
|
};
|
|
}
|
|
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;
|
|
};
|
|
}
|
|
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; };
|
|
}
|
|
|
|
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_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());
|
|
}
|
|
}
|