C++11可变参数模板参数类型推导失败问题排查与解决
C++11下可变参数模板函数适配元组的实现问题
C++14可行方案
在C++14中可直接用std::apply实现将元组参数传递给函数的功能,示例代码如下:
#include <tuple> template <typename T, typename U> void my_func(T &&t, U &&u) {} int main(int argc, char *argv[argc]) { std::tuple<int, float> my_tuple; std::apply([](auto &&... args) { my_func(args...); }, my_tuple); return 0; }
自行实现C++11方案的编译失败问题
尝试自行实现C++11下的适配逻辑,但调用u.apply(f)时出现类型推导失败的编译错误,完整尝试代码如下:
#include <iostream> #include <tuple> using namespace std; template <typename... T> struct parameter_pack : public parameter_pack<T>... { parameter_pack(const T&... t) : parameter_pack<T>(t)... {} // C++11 尝试的版本 template <template <typename...> class Func> void apply(Func<T...> f) { f(parameter_pack<T>::h...); } // C++14 可行版本 // template <typename Func> // void apply(Func f) { // f(parameter_pack<T>::h...); // } // 更新:可行的C++11方案 //void apply(void (*f)(const T&...)) { // f(parameter_pack<T>::h...); //} }; template <typename H> struct parameter_pack<H> { parameter_pack(const H& h) : h(h) {} const H& h; }; template <typename... T> parameter_pack<T...> make_parameter_pack(const T&... t) { return parameter_pack<T...>(t...); } // 测试用重载函数f template <typename H> void f(const H& h) { std::cout << h << std::endl; } template <typename H, typename... T> void f(const H& h, const T&... t) { f(h); f(t...); } int main() { auto u = make_parameter_pack(1, 1.1, "hello"); std::cout << std::endl; // C++11 调用失败 u.apply(f); // 编译器报错 // C++14 可行调用方式 // auto lambda = [&](const auto&... args) { // f(args...); // }; // u.apply(lambda); }
编译器报错信息
<source>:49:7: error: no matching member function for call to 'apply' 49 | u.apply(f); | ~~^~~~~ <source>:12:10: note: candidate template ignored: couldn't infer template argument 'Func' 12 | void apply(Func<T...> f) { | ^ 1 error generated. Compiler returned: 1
类型推导失败的原因
尝试的C++11版本中,apply的模板参数是template <typename...> class Func,这要求传入的参数是模板类的实例,但f是重载的函数模板,并非模板类。编译器无法从函数模板f推导出对应的模板类参数Func,因此匹配失败。
可行的C++11解决方案
使用函数指针作为apply的参数(代码中已标记为更新的解决方案):
void apply(void (*f)(const T&...)) { f(parameter_pack<T>::h...); }
该方案可行的原因是:当调用u.apply(f)时,编译器会根据parameter_pack的模板参数int, double, const char*,自动推导出匹配的f重载版本,生成对应的函数指针类型void(*)(const int&, const double&, const char* const&),与apply的参数类型完全匹配,因此可以正常编译运行。
内容的提问来源于stack exchange,提问作者Patrick Fromberg
相关产品推荐
相关产品推荐

