如何实现同时支持模板值参数与普通函数参数的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
相关产品推荐
相关产品推荐

