C++如何不额外加模板参数、不使用std::function传任意返回类型函数
解决方案
有两种完全符合要求的单模板参数实现方案,均无需使用std::function,也不需要显式声明第二个模板参数,可兼容任意返回类型的入参函数。
方案1:C++11及以上全兼容版本
通过模板萃取技术自动从函数指针类型中提取元素类型,仅需声明一个代表函数类型的模板参数:
// 函数指针类型萃取工具,无需手动调用 template <typename> struct func_traits; template <typename ReturnType, typename ElementType> struct func_traits<ReturnType(*)(ElementType&)> { using element_type = ElementType; }; template <typename Func> void map(Func f, typename func_traits<Func>::element_type* collection, unsigned length) { for(unsigned i = 0; i < length; i++) f(collection[i]); }
说明
- 模板参数
Func会自动匹配任意返回类型、接收单个非const引用参数的函数指针,返回值会在调用时自动丢弃,完全合法无未定义行为 - 无需手动声明元素类型模板参数,萃取工具会自动从入参函数的参数中提取元素类型
- 天然支持无捕获lambda作为入参(无捕获lambda可隐式转换为函数指针)
方案2:C++20及以上极简版本
使用C++20引入的函数参数auto简写特性,代码更简洁:
template <typename T> void map(auto (*f)(T&), T* collection, unsigned length) { for(unsigned i = 0; i < length; i++) f(collection[i]); }
说明
- 参数列表中的
auto会自动匹配任意返回类型,无需显式声明第二个模板参数 - 语法更简洁,不需要额外的萃取工具代码
两种方案都可以直接运行你提供的示例代码,无需修改任何调用逻辑,同时支持传入返回非void类型的函数,例如:
int increment(int& i) { return ++i; } // 可以直接传入map,不需要做任何转换 map(&increment, integers, 4);
内容的提问来源于stack exchange,提问作者Alix R.
相关产品推荐
相关产品推荐

