C++11可变参数模板n元for_each的类型推导失败问题求助
C++11 n元for_each模板参数推导失败问题解决
问题描述
我正在为嵌入式项目实现基于C++11的n元for_each(不支持更高版本标准),但遇到了可变参数模板函数的类型推导失败问题。实现代码及测试用例如下:
// My implementation attempt size_t get_len() { return 0; } template <typename A, size_t N, typename... Args> size_t get_len(A (&head)[N], Args... tail) { size_t n_t = get_len(tail...); return N < n_t ? N : n_t; } template <typename A, size_t N, typename... Args> size_t get_len(std::array<A, N> &head, Args... tail) { size_t n_t = get_len(tail...); return N < n_t ? N : n_t; } template <typename A, typename... Args> size_t get_len(std::vector<A> &head, Args... tail) { size_t n_h = head.size(); size_t n_t = get_len(tail...); return n_h < n_t ? n_h : n_t; } template <typename F, typename... Args> void forEach(F f, Args &...args) { auto length = get_len(args...); for (int i = 0; i < length; i++) { f(args[i]...); } } // Example n-ary function #include <iostream> template <typename T> void print(T arg) { std::cout << arg << std::endl; } template <typename T, typename... Types> void print(T arg, Types... args) { std::cout << arg << ", "; print(args...); } // Test - failing std::vector<int> a = { 0, 1, 2, 3, 4 }; std::vector<int> a1 = { 10, 11, 12, 13, 14 }; forEach(print, a, a1);
编译时报错:
/Users/username/Documents/dev/arduino/pure/pure.ino: In function 'void setup()': /Users/username/Documents/dev/arduino/pure/pure.ino:20:23: error: no matching function for call to 'forEach(<unresolved overloaded function type>, std::vector<int>&, std::vector<int>&)' forEach(print, a, a1); ^ In file included from /Users/username/Documents/dev/arduino/pure/pure.ino:1: /Users/username/Documents/dev/arduino/libraries/pure/src/pure.hpp:13:6: note: candidate: 'template<class F, class It_A> void forEach(F, It_A&)' void forEach(F f, It_A &iterable) ^~~~~~~ /Users/username/Documents/dev/arduino/pure/pure.ino:20:23: note: template argument deduction/substitution failed: /Users/username/Documents/dev/arduino/pure/pure.ino:20:23: note: candidate expects 2 arguments, 3 provided forEach(print, a, a1); ^ In file included from /Users/username/Documents/dev/arduino/pure/pure.ino:1: /Users/username/Documents/dev/arduino/libraries/pure/src/pure.hpp:53:6: note: candidate: 'template<class F, class ... Args> void forEach(F, Args& ...)' void forEach(F f, Args &...args) ^~~~~~~ /Users/username/Documents/dev/arduino/pure/pure.ino:20:23: note: template argument deduction/substitution failed: /Users/username/Documents/dev/arduino/pure/pure.ino:20:23: note: couldn't deduce template parameter 'F' forEach(print, a, a1); ^ exit status 1 Compilation error: no matching function for call to 'forEach(<unresolved overloaded function type>, std::vector<int>&, std::vector<int>&)'
核心问题是编译器无法推导forEach的模板参数F类型,原因是传入的print是重载模板函数,编译器无法自动确定要选用哪个重载版本。
解决方案
1. 显式强制转换函数类型
直接将print转换为目标重载版本的函数指针类型,明确告知编译器要使用的函数:
// 指定接收两个int参数的print版本 forEach(static_cast<void(*)(int, int)>(print), a, a1);
2. 使用无捕获Lambda封装调用
C++11支持无捕获lambda,其类型是唯一且明确的,编译器可以正常推导:
forEach([](int x, int y) { print(x, y); }, a, a1);
3. 添加非模板重载函数
如果业务场景中参数类型相对固定,可以为print添加对应参数的非模板重载,让编译器直接匹配:
void print(int arg1, int arg2) { std::cout << arg1 << ", " << arg2 << std::endl; }
之后直接调用forEach(print, a, a1)即可编译通过。
4. 使用函数对象替代模板函数
定义一个包含模板operator()的函数对象类,其类型是明确的,避免重载带来的推导问题:
struct Print { template <typename... Types> void operator()(Types... args) const { print_impl(args...); } private: template <typename T> static void print_impl(T arg) { std::cout << arg << std::endl; } template <typename T, typename... Rest> static void print_impl(T arg, Rest... rest) { std::cout << arg << ", "; print_impl(rest...); } };
调用方式:
forEach(Print{}, a, a1);
内容的提问来源于stack exchange,提问作者lighthouse
相关产品推荐
相关产品推荐

