编译期依赖注入容器通过模板元编程实现零运行时开销的服务绑定与构造。它支持服务抽象、类型匹配、单例/瞬态生命周期、依赖拓扑排序及安全注入宏,全程在编译期完成类型检查与实例化。

一、定义依赖注入容器的模板元编程结构
编译期依赖注入需在模板实例化阶段完成类型绑定与对象构造,避免运行时反射或虚函数开销。该结构通过嵌套模板别名与特化机制,将服务接口与其实现类在编译期关联。
1、声明服务抽象基类模板,使用空基类优化(EBO)确保零大小开销。
2、定义注入容器模板类,接受可变参数包,每个参数为服务-实现映射对,例如 service
3、利用 std::tuple 存储所有实现类型的实例化占位符,并通过 std::index_sequence 在编译期展开构造。
二、实现服务查找与实例化的编译期类型匹配逻辑
服务获取必须不依赖运行时类型信息(RTTI),而是通过 SFINAE 和 std::is_constructible 等特性,在模板参数推导过程中完成类型合法性校验与精确匹配。
1、在容器模板中定义 get() 成员函数模板,其返回类型由传入的服务接口类型推导得出。
2、使用 decltype(auto) 保持返回值类别(左值/右值引用)与底层存储一致。
3、借助 std::enable_if_t
三、支持单例与瞬态生命周期的编译期策略分离
不同服务需在编译期确定其生命周期语义,单例要求全局唯一实例,瞬态则每次请求新建对象;二者不可混用,须通过独立模板参数区分。
1、引入标签类型 singleton_tag 与 transient_tag,作为服务映射对的第三个模板参数。
2、容器内部依据标签类型选择不同的存储方式:单例使用 static inline 变量实现线程安全的首次初始化,瞬态则直接调用 std::make_unique 或聚合构造。
3、对瞬态服务,禁用拷贝构造并强制移动语义,确保资源所有权清晰转移。
四、处理构造依赖图的编译期拓扑排序与递归实例化
当某服务的构造函数依赖其他已注册服务时,必须保证依赖项先于被依赖项完成构造;该顺序不能靠运行时检测,而需在模板展开过程中由编译器推导出无环依赖关系。
1、为每个服务实现类添加静态成员函数 requires(),返回一个类型列表,列出其构造所需的其他服务接口类型。
2、在容器实例化期间,对所有注册服务执行编译期图遍历,使用 std::integer_sequence 模拟 DFS 栈,检测循环依赖并生成错误信息。
3、按拓扑序依次实例化各服务,将前序构造结果以非类型模板参数形式传递给后续构造函数调用点。
五、提供类型安全的注入点宏与友元访问控制
用户代码中需以最小侵入方式声明依赖,避免手动传递容器或暴露内部实现;宏用于在类定义中注入依赖字段,并自动生成符合编译期约束的构造函数签名。
1、定义宏 INJECT_DEPS(...),展开为私有成员变量声明及带依赖参数的构造函数重载。
2、该宏生成的构造函数参数列表严格对应所列依赖类型,且每个参数标记为 const auto& 以适配任意生命周期策略。
3、容器模板被声明为类的友元,允许其直接访问私有注入字段,同时禁止外部代码绕过注入机制直接构造对象。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











