C++模板参数推导失败求助:调用start()函数报错
C++模板参数推导冲突问题解决
问题根源
你的start模板函数中,FunctionArgs这个模板参数包被同时用于两个场景:
std::function的参数列表:std::function<FunctionResult(const bool&, FunctionArgs...)>,这里推导出来的是带引用的类型(比如const Source&、Population&)- 函数的可变参数:
FunctionArgs... args,这里从你传入的实参(source是Source类型、population是Population类型)推导出来的是不带引用的原始类型
编译器无法为同一个模板参数包推导两组矛盾的类型,因此触发报错。
解决方法
方法1:拆分模板参数包(推荐)
把std::function的参数和函数实参的模板参数分开,避免推导冲突,同时用完美转发提升灵活性:
#include <memory> #include <functional> #include <utility> #include <tuple> // 假设StoppableThread是已定义的线程类 class StoppableThread {}; template <typename FunctionResult, typename... FuncParams, typename... Args> inline std::shared_ptr<StoppableThread> start( std::function<FunctionResult(const bool&, FuncParams...)> function, Args&&... args) { return std::make_shared<StoppableThread>( [func = std::move(function), args_tuple = std::make_tuple(std::forward<Args>(args)...)](const bool& stopFlag) { std::apply([&stopFlag, &func](auto&&... unpackedArgs) { func(stopFlag, std::forward<decltype(unpackedArgs)>(unpackedArgs)...); }, args_tuple); } ); }
FuncParams从std::function的类型推导,Args从传入的实参推导,两者互不干扰,完美转发还能保留实参的左值/右值属性。
方法2:接受任意可调用对象(更通用)
放弃限定std::function,让start接受任意可调用类型(lambda、函数指针、绑定对象等),彻底绕开std::function的模板推导问题:
#include <memory> #include <functional> #include <tuple> #include <utility> class StoppableThread {}; template <typename Func, typename... Args> inline std::shared_ptr<StoppableThread> start(Func&& func, Args&&... args) { return std::make_shared<StoppableThread>( [func = std::forward<Func>(func), args_tuple = std::make_tuple(std::forward<Args>(args)...)](const bool& stopFlag) { std::apply([&stopFlag, &func](auto&&... unpackedArgs) { func(stopFlag, std::forward<decltype(unpackedArgs)>(unpackedArgs)...); }, args_tuple); } ); }
这种方式不仅解决了推导问题,还让start函数的适用范围更广,不需要强制把可调用对象包装成std::function。
方法3:显式指定模板参数(繁琐但可行)
如果一定要保留原函数结构,可以显式指定FunctionArgs的模板参数,注意要带上引用类型:
auto searchThread = start<void, const Source&, Population&, const std::vector<Parameter>&, const size_t&, const size_t&>( threadedSearch, source, population, variationsParameters, randomCandidatesCount, lineageCount);
这种方式需要手动匹配std::function的参数类型,代码冗余且容易出错,不推荐。
内容的提问来源于stack exchange,提问作者Mathieu Rodic
相关产品推荐
相关产品推荐

