You need to enable JavaScript to run this app. 如何实现同时支持模板值参数与普通函数参数的C++模板函数
优惠活动
大模型
产品
解决方案
定价
更多

如何实现同时支持模板值参数与普通函数参数的C++模板函数

解决方案

核心思路

将重复的逻辑抽离为独立的通用核心函数,再通过两个重载的对外接口分别适配静态模板参数、动态函数参数的场景,完全消除代码冗余的同时保留两类场景的性能特性。

C++20 实现(符合预期调用形式)

#include <functional>

template <typename T>
T default_fun(const T* a, const T* b) {
    T d = a[0] - b[0];
    return d*d;
}

template <typename T>
using funtype = std::function<T(const T* a, const T* b)>;

// 核心公共实现,仅编写一次
template<typename T, typename Callable>
T core_fun(size_t s, const T* a, const T* b, Callable&& callable) {
    T acc = 0;
    for(size_t i = 0; i < s; ++i) {
        acc += std::forward<Callable>(callable)(a + i, b + i);
    }
    return acc;
}

// 重载1:静态模板参数版本
template<typename T, auto dist = default_fun<T>>
T static_dynamic_fun(size_t s, const T* a, const T* b) {
    return core_fun<T>(s, a, b, dist);
}

// 重载2:动态函数参数版本
template<typename T>
T static_dynamic_fun(size_t s, const T* a, const T* b, const funtype<T>& dist) {
    return core_fun<T>(s, a, b, dist);
}

调用示例(完全符合需求)

// 动态传参
static_dynamic_fun<double>(size, a.data(), b.data(), default_fun<double>);
// 静态模板传参
static_dynamic_fun<double, default_fun<double>>(size, a.data(), b.data());
// 带捕获lambda的动态调用
int bias = 10;
static_dynamic_fun<double>(size, a.data(), b.data(), [bias](const double* a, const double* b) {
    return (a[0] - b[0]) * (a[0] - b[0]) + bias;
});

性能验证

编译后观察汇编可以确认:

  • 静态版本的default_fun调用会被完全inline,和原有static_fun的性能完全一致
  • 动态版本的std::function调用行为和原有dynamic_fun完全一致

C++11/14 兼容实现

由于C++11/14不支持auto作为非类型模板参数,需要调整静态版本的模板参数声明:

// 静态版本适配C++11/14
template<typename T, typename Dist = T(*)(const T*, const T*), Dist dist = &default_fun<T>>
T static_dynamic_fun(size_t s, const T* a, const T* b) {
    return core_fun<T>(s, a, b, dist);
}

其余核心实现、动态重载完全不变,调用形式和C++20版本一致。


可选优化(动态场景也保留自动inline能力)

如果希望传入无捕获lambda、普通函数等静态已知可调用对象时,不需要手动走模板参数也能自动获得inline优化,可以把动态重载的参数改为通用可调用对象,避免强制转std::function的开销:

template<typename T, typename Callable>
T static_dynamic_fun(size_t s, const T* a, const T* b, Callable&& dist) {
    return core_fun<T>(s, a, b, std::forward<Callable>(dist));
}

只有当确实需要运行时动态切换函数、传入带捕获的lambda时,再主动包装为std::function即可,兼顾灵活性和性能。

内容的提问来源于stack exchange,提问作者Mat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 03:45:02