编译期依赖注入通过五步实现:一定义服务契约接口,二构建依赖图元数据,三实现单例容器注册表,四构造注入上下文模板,五支持多配置变体策略选择。

一、定义编译期可解析的服务契约接口
通过模板参数约束服务类型,使依赖声明在编译期即具备类型完整性与契约一致性,避免运行时类型擦除或虚函数调用开销。该步骤确立所有可注入服务的静态接口边界。
1、声明空基类模板 ServiceBase
2、在 ServiceBase 内定义 static constexpr bool is_service = true; 成员,供 SFINAE 或 requires 子句识别。
3、为每个具体服务定义唯一空结构体标签,例如 struct LoggerService {} 和 struct ConfigService {}。
二、构建依赖图元数据生成器
利用模板递归展开与参数包展开机制,在编译期推导组件所需依赖集合,并生成唯一、扁平化的依赖索引序列,支撑后续实例化顺序判定。
1、定义模板别名 requires_services
2、对每个组件类型 C,特化 component_dependencies
3、使用 std::tuple
三、实现编译期单例容器注册表
借助静态局部变量与函数模板的唯一实例化特性,在首次访问时构造服务对象,并通过类型擦除无关的纯模板机制保证线程安全与零成本抽象。
1、定义函数模板 template
2、在函数体内声明静态局部变量 S instance{},其构造仅发生一次且由编译器保障初始化顺序。
3、返回该静态变量的引用,类型为 S&,不涉及指针或 std::any 等运行时机制。
四、构造依赖注入上下文模板
将组件类型与其依赖服务标签绑定,生成一个可直接实例化的注入上下文,在构造时自动解析并传入所有依赖项,全过程无宏、无反射、无运行时查找。
1、定义模板类 inject_context
2、在构造函数中使用 std::apply 与参数包展开,依次调用 service_instance() 获取每个依赖引用。
3、将获取的依赖引用完美转发至 Component 的构造函数,触发 Component{dep1, dep2, ...} 实例化。
五、支持多配置变体的编译期策略选择
通过模板非类型参数或概念约束区分不同部署环境下的服务实现,使同一组件可在开发、测试、生产等场景下链接不同服务实例,且切换完全发生在编译期。
1、定义枚举 enum class BuildProfile { Debug, Test, Release };
2、为每个服务标签 S 定义特化模板 service_implementation,指定对应 Profile 下的实际类型。
3、在 service_instance() 中依据当前编译宏(如 __DEBUG__)或模板参数推导 Profile,再转发至对应特化实现的实例化入口。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











