You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:07:08