#pragma once #include #include #include #include #include #include "Export.h" #include #include #include namespace uns { // 前置声明捕获器 struct RangeCapturer; struct PairCapturer; struct FuncCapturer; struct TimeCapturer; // 终极 Variant 池:容纳所有可能解包出的原子形态 using LogVariant = std::variant< bool, char, int, unsigned int, long long, unsigned long long, double, std::string_view, const void*, std::string, // 专门用于承载宽字符转换后的 UTF-8 临时字符串 RangeCapturer, // 专门用于承载 std::vector / std::list 等容器 PairCapturer, // 专门用于承载 std::pair (支持 std::map) FuncCapturer, //承载 std::function TimeCapturer //承载时间 >; // --- 编译期类型推导工具链 --- template struct is_container : std::false_type { }; // 识别标准容器(排除字符串本身) template struct is_container().begin()), decltype(std::declval().end())>> : std::integral_constant && !std::is_same_v> { }; template struct is_pair : std::false_type { }; template struct is_pair> : std::true_type { }; // --- 延迟桥接结构体 --- struct LogArg; struct RangeCapturer { const void* ptr; void (*to_log_args)(const void*, std::vector&); }; struct PairCapturer { const void* ptr; void (*to_log_args)(const void*, std::vector&); }; struct FuncCapturer { const void* code_ptr; // 真正改变:这里存真正的函数代码地址 bool is_closure; // 标记:这究竟是个纯函数,还是个 Lambda 闭包 }; // 升级版 Trait:不仅识别,还提取原生函数指针类型(R(*)(Args...)) template struct function_traits { static constexpr bool is_func = false; using pointer_type = void*; }; template struct function_traits> { static constexpr bool is_func = true; using pointer_type = R(*)(Args...); // 提取出原生函数指针类型 }; enum class TimeMode { Point, TMPoint, Duration }; struct TimeCapturer { TimeMode mode{ TimeMode::Point }; std::tm _tm{}; std::chrono::system_clock::time_point tp{}; std::chrono::nanoseconds duration{ 0 }; std::string format_spec; // "%Y-%m-%d %H:%M:%S" or empty // 可选:单位策略控制 bool smart_unit = true; }; template struct is_time_point : std::false_type { }; template struct is_time_point> : std::true_type { }; template<> struct is_time_point : std::true_type { }; template inline constexpr bool is_time_point_v = is_time_point::value; template struct is_duration : std::false_type { }; template struct is_duration> : std::true_type { }; template inline constexpr bool is_duration_v = is_duration::value; inline TimeCapturer MakeTimeCapturer(std::chrono::system_clock::time_point tp) { TimeCapturer c; c.mode = TimeMode::Point; c.tp = tp; return c; } template inline TimeCapturer MakeTimeCapturer(std::chrono::duration d) { TimeCapturer c; c.mode = TimeMode::Duration; c.duration = std::chrono::duration_cast(d); c.smart_unit = true; return c; } inline TimeCapturer MakeTimeCapturer(const std::tm& tm) { TimeCapturer c; c.mode = TimeMode::TMPoint; c._tm = tm; return c; } // --- 宽字符转换声明(实现卸载到 .cpp) --- std::string UNSWSC_DLL_EXPORT ConvertWStringToUtf8(std::wstring_view wstr); // --- 核心包装类 --- struct LogArg { LogVariant value; template LogArg(T&& val) { using D = std::decay_t; // 1. 窄字符串系列(0拷贝) if constexpr (std::is_same_v || std::is_same_v) value = std::string_view(val); else if constexpr (std::is_same_v || std::is_same_v) value = val ? std::string_view(val) : std::string_view(""); // 2. 宽字符串系列(特殊处理:触发内部 UTF-8 转换) else if constexpr (std::is_same_v || std::is_same_v) value = ConvertWStringToUtf8(val); else if constexpr (std::is_same_v || std::is_same_v) value = val ? ConvertWStringToUtf8(val) : std::string(""); // 3. 基础原子类型(防范 wchar_t 被误判为整数) else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) value = ConvertWStringToUtf8(std::wstring_view((const wchar_t*)&val, 1)); else if constexpr (std::is_same_v) value = static_cast(val); else if constexpr (std::is_same_v || std::is_same_v) value = static_cast(val); // 3.5 时间点类型系列(防止时间对象退化为未知类型) else if constexpr (is_time_point_v) value = MakeTimeCapturer(val); else if constexpr (is_duration_v) value = MakeTimeCapturer(val); // 4. 全整型变种矩阵 (short, int, long, long long, unsigned...) else if constexpr (std::is_integral_v && std::is_signed_v) { if constexpr (sizeof(D) <= sizeof(int)) value = static_cast(val); else value = static_cast(val); } else if constexpr (std::is_integral_v && std::is_unsigned_v) { if constexpr (sizeof(D) <= sizeof(unsigned int)) value = static_cast(val); else value = static_cast(val); } // 5. 浮点矩阵 else if constexpr (std::is_floating_point_v) value = static_cast(val); // 6. 指针 else if constexpr (std::is_pointer_v) value = static_cast(val); // 7. 标准库容器(关键点:利用 Lambda 闭包在不引入 fmt 的情况下擦除容器类型!) else if constexpr (is_container::value) { value = RangeCapturer{ &val, [] (const void* p, std::vector& out) { for (const auto& item : *static_cast(p)) out.emplace_back(item); // 递归包装子元素 } }; } // 8. 键值对(支持 Map 展开) else if constexpr (is_pair::value) { value = PairCapturer{ &val, [] (const void* p, std::vector& out) { const auto& pair = *static_cast(p); out.emplace_back(pair.first); out.emplace_back(pair.second); } }; } else if constexpr (function_traits::is_func) { using TargetPtr = typename function_traits::pointer_type; // 关键点:尝试用 target() 拿底层指针 // std::function::target() 返回的是 T*,所以如果 T 是函数指针,返回的就是“函数指针的指针” if (auto* const* func_ptr = val.template target()) // 情况 A:内部装的是普通纯函数或静态成员函数 value = FuncCapturer{ reinterpret_cast(*func_ptr), false }; else // 情况 B:内部装的是 Lambda 表达式或带状态的仿函数, 此时它在堆/栈上有一个闭包实体,我们退而求其次,打印这个闭包对象的地址 value = FuncCapturer{ static_cast(&val), true }; } else value = std::string_view(""); } }; }