C++ 反射实现:从 0 到依赖注入容器

背景 C++ 一直缺少反射(Reflection),虽然 C++20 引入了 std::reflect,但目前编译器支持还很有限。 实际项目中,我们经常需要: 根据字符串创建对象 自动注入依赖 序列化/反序列化 这篇文章聊聊怎么在 C++ 里实现一套轻量反射系统。 反射的核心:类型注册 反射的本质是在运行时动态查询类型信息。实现思路很简单——用全局注册表。 1. 基础类型注册表 #include <functional> #include <unordered_map> #include <string> #include <memory> class TypeRegistry { public: template<typename T> static void registerType(const std::string& name) { creators()[name] = []() -> std::any { return std::make_any<T>(); }; } static std::any create(const std::string& name) { auto it = creators().find(name); if (it != creators().end()) { return it->second(); } throw std::runtime_error("Unknown type: " + name); } private: static auto& creators() { static std::unordered_map<std::string, std::function<std::any()>> map; return map; } }; 2. 宏简化注册 #define REGISTER_TYPE(T) \ namespace { \ struct Registrar##T { \ Registrar##T() { \ TypeRegistry::registerType<T>(#T); \ } \ }; \ static Registrar##T registrar_##T; \ } 3. 使用 struct User { std::string name; int age; }; REGISTER_TYPE(User) int main() { auto any_user = TypeRegistry::create("User"); auto& user = std::any_cast<User&>(any_user); user.name = "BvBeJ"; user.age = 28; } 进阶:带构造函数参数 上面的实现只能调用默认构造函数。实际场景往往需要传参: ...

2026年4月6日 · 2 分钟 · BvBeJ

C++ 协程:从 asyncio 理解现代异步编程

背景 现代编程离不开异步。Python 有 asyncio,JavaScript 有 async/await,Go 有 goroutine。C++20 终于引入了协程(Coroutines)。 今天从 Python asyncio 的视角来看看 C++ 协程怎么用。 Python asyncio 的模式 async def fetch(url: str) -> str: # 模拟异步IO await asyncio.sleep(1) return f"data from {url}" async def main(): results = await asyncio.gather( fetch("a.com"), fetch("b.com"), fetch("c.com"), ) print(results) asyncio.run(main()) 核心概念:async def 定义协程函数,await 挂起等待,asyncio.gather 并发执行。 C++20 协程入门 C++ 协程的关键类型: co_await — 挂起协程 co_return — 返回值(相当于 return) co_yield — 产出值(用于生成器) std::suspend_never / std::suspend_always — 挂起策略 简单例子:模拟异步任务 #include <coroutine> #include <future> #include <iostream> template<typename T> struct Task { struct promise_type { T value; std::exception_ptr error; auto get_return_object() { return Task{std::coroutine_handle<promise_type>::from_promise(*this)}; } auto initial_suspend() { return std::suspend_never{}; } auto final_suspend() noexcept { return std::suspend_always{}; } void return_value(T v) { value = v; } void unhandled_exception() { error = std::current_exception(); } }; std::coroutine_handle<promise_type> handle; Task(std::coroutine_handle<promise_type> h) : handle(h) {} ~Task() { if (handle) handle.destroy(); } T get() { handle.resume(); return handle.promise().value; } }; // 模拟异步操作 Task<int> async_fetch() { std::cout << "开始异步任务...\n"; co_await std::suspend_always{}; // 挂起,模拟异步等待 std::cout << "异步任务完成\n"; co_return 42; } int main() { auto task = async_fetch(); std::cout << "做一些其他事情...\n"; int result = task.get(); std::cout << "结果: " << result << "\n"; } 和 Python asyncio 对比 Python C++ async def Task<T> 返回类型 await co_await return value co_return value asyncio.sleep(1) std::suspend_always{} 事件循环自动调度 手动 resume() 实际应用:HTTP 客户端 Task<Response> http_get(const std::string& url) { co_await socket_.async_connect(url); co_await socket_.async_write(request_); Response resp = co_await socket_.async_read(); co_return resp; } Task<std::vector<Response>> fetch_all(const std::vector<std::string>& urls) { std::vector<Task<Response>> tasks; for (const auto& url : urls) { tasks.push_back(http_get(url)); } std::vector<Response> results; for (auto& task : tasks) { results.push_back(task.get()); } co_return results; } 坑点 协程不能用在模板参数里 — std::vector<Task<int>> 可以,但 Task<Task<int>> 不行 生命周期管理 — 协程句柄必须手动 destroy(),除非用 RAII 封装 调试困难 — 栈帧被编译器切分,gdb 支持还在完善中 总结 C++20 协程还很年轻,库支持不如 Python 完善。但对于构建高性能网络服务,它的零成本抽象是其他语言难以比拟的。 ...

2026年4月5日 · 2 分钟 · BvBeJ