使用Boost.DI时动态绑定接口数组的Lambda表达式未执行问题
boost::di动态创建Log实现数组时Lambda未执行问题分析与解决
在使用boost::di进行依赖注入时,用于根据运行时条件动态创建Log接口实现类(ConsoleLog、FileLog)数组的Lambda表达式未执行,注入器配置完成后Lambda完全未被调用。
相关代码
#include <boost/di.hpp> #include <iostream> #include <memory> #include <vector> namespace di = boost::di; struct Log { virtual ~Log() = default; virtual void log(const std::string& message) = 0; }; struct ConsoleLog : Log { void log(const std::string& message) override { std::cout << "ConsoleLog: " << message << std::endl; } }; struct FileLog : Log { void log(const std::string& message) override { std::cout << "FileLog: " << message << std::endl; } }; class A { public: A(std::vector<std::shared_ptr<Log>>& logs) : logs_(logs) { std::cout << logs_.size() << std::endl; for (auto& p : logs_) { p->log("test A"); } } private: std::vector<std::shared_ptr<Log>>& logs_; }; int main() { bool needConsole = true; bool needFile = false; auto injector = di::make_injector( di::bind<Log*[]>().to([&](const auto& injector) -> std::vector<std::shared_ptr<Log>> { std::vector<std::shared_ptr<Log>> logs; std::cout << "Lambda executing" << std::endl; if (needConsole) { logs.push_back(injector.template create<std::shared_ptr<ConsoleLog>>()); } if (needFile) { logs.push_back(injector.template create<std::shared_ptr<FileLog>>()); } return logs; }).in(di::singleton) ); auto a = injector.create<A>(); return 0; }
已排查步骤
- 直接调用Lambda测试:手动调用该Lambda创建
std::vector<std::shared_ptr<Log>>,确认Lambda逻辑本身无问题; - 简化Lambda逻辑:移除条件判断,仅创建单个ConsoleLog实例,Lambda仍未触发;
- 添加日志输出:在Lambda内部及调用前后添加日志,确认Lambda未执行。
问题原因分析
核心问题是绑定类型与依赖类型不匹配:
- 代码中绑定的类型是
Log*[](C风格数组类型),但类A的构造函数依赖的是std::vector<std::shared_ptr<Log>>,boost::di无法将数组类型的绑定匹配到vector类型的依赖,因此不会触发对应的Lambda; - Lambda的返回值是
std::vector<std::shared_ptr<Log>>,与绑定的数组类型完全不兼容,导致绑定规则无效。
此外,构造函数中使用std::vector<std::shared_ptr<Log>>&非const引用,boost::di默认会创建临时对象,可能引发引用失效的问题,也是潜在隐患。
解决建议
1. 修正绑定类型
将绑定的类型改为与依赖一致的std::vector<std::shared_ptr<Log>>,让boost::di能正确匹配依赖并触发Lambda。
2. 调整构造函数参数
将构造函数的参数改为const std::vector<std::shared_ptr<Log>>&或直接传值,避免临时对象引用失效的问题。
3. 优化Lambda实现
如果目标类无额外依赖,直接用std::make_shared创建实例更简洁;若需要通过injector管理依赖,可保留injector参数传入Lambda。
修正后代码示例
#include <boost/di.hpp> #include <iostream> #include <memory> #include <vector> namespace di = boost::di; struct Log { virtual ~Log() = default; virtual void log(const std::string& message) = 0; }; struct ConsoleLog : Log { void log(const std::string& message) override { std::cout << "ConsoleLog: " << message << std::endl; } }; struct FileLog : Log { void log(const std::string& message) override { std::cout << "FileLog: " << message << std::endl; } }; class A { public: // 改为const引用,避免临时对象引用失效 A(const std::vector<std::shared_ptr<Log>>& logs) : logs_(logs) { std::cout << logs_.size() << std::endl; for (const auto& p : logs_) { p->log("test A"); } } private: const std::vector<std::shared_ptr<Log>>& logs_; }; int main() { bool needConsole = true; bool needFile = false; auto injector = di::make_injector( // 绑定正确的vector类型 di::bind<std::vector<std::shared_ptr<Log>>>().to([&]() { std::vector<std::shared_ptr<Log>> logs; std::cout << "Lambda executing" << std::endl; if (needConsole) { logs.push_back(std::make_shared<ConsoleLog>()); // 若需通过injector创建,可保留以下代码 // logs.push_back(injector.create<std::shared_ptr<ConsoleLog>>()); } if (needFile) { logs.push_back(std::make_shared<FileLog>()); } return logs; }).in(di::singleton) ); auto a = injector.create<A>(); return 0; }
内容的提问来源于stack exchange,提问作者truing Matthews
相关产品推荐
相关产品推荐

