C++17中如何迭代模板参数,简化模板函数重复调用代码?
C++17 简化模板函数调用的重复代码方案
你定义了两个模板函数:
template <class T> T &func1(int param, const T &component) { return do_something<T>(param, component); } template <class T> T &func2(int param, const T &component) { return do_something_else<T>(param, component); }
调用时需要为每个类型手动编写重复的lambda样板代码,例如:
auto object1 = some_func( [this](int param, Type1 component) { return func1<Type1>(param, component); }, [this](int param, Type2 component) { return func1<Type2>(param, component); } );
随着涉及类型增多,重复代码量急剧增加,希望简化为以下形式:
auto object1 = some_template_func<Type1, Type2>(&func1); auto object2 = some_template_func<Type1, Type2>(&func2);
实现方案
由于C++17无法直接将函数模板作为函数参数传递(函数模板本身并非具体的函数对象),我们可以通过泛型lambda结合可变模板参数展开来消除重复代码,具体实现如下:
1. 实现核心简化函数 some_template_func
这个模板函数接受可变数量的目标类型,以及一个泛型可调用对象,自动为每个类型生成对应的lambda并传递给原有的some_func:
#include <type_traits> // 类内成员函数版本(需要捕获this) template <typename... Types, typename Func> auto some_template_func(Func func) { return some_func( // 为每个Types类型生成适配lambda [this, func](int param, Types component) { return func(param, component); }... ); } // 全局函数版本(无需捕获this) template <typename... Types, typename Func> auto some_template_func(Func func) { return some_func( [func](int param, Types component) { return func(param, component); }... ); }
2. 简化调用方式
直接用泛型lambda包装func1/func2,传递给some_template_func即可:
// 调用func1的简化写法 auto object1 = some_template_func<Type1, Type2>( [](int param, const auto& component) { using T = std::decay_t<decltype(component)>; return func1<T>(param, component); } ); // 调用func2的简化写法 auto object2 = some_template_func<Type1, Type2>( [](int param, const auto& component) { using T = std::decay_t<decltype(component)>; return func2<T>(param, component); } );
进一步优化:封装包装逻辑
如果觉得每次写lambda麻烦,可以把包装逻辑抽成复用的辅助函数,让调用更接近你期望的形式:
// 通用模板函数包装器 auto wrap_func = [](auto func_template) { return [func_template](int param, const auto& component) { using T = std::decay_t<decltype(component)>; return func_template.template operator()<T>(param, component); }; }; // 先将func1/func2包装为仿函数(兼容函数模板) struct Func1Wrapper { template <typename T> T& operator()(int param, const T& component) { return func1<T>(param, component); } }; struct Func2Wrapper { template <typename T> T& operator()(int param, const T& component) { return func2<T>(param, component); } };
此时调用会更简洁:
auto object1 = some_template_func<Type1, Type2>(wrap_func(Func1Wrapper{})); auto object2 = some_template_func<Type1, Type2>(wrap_func(Func2Wrapper{}));
关键说明
std::decay_t用于处理参数的cv限定符和引用,确保类型推导准确;- 可变模板参数
Types...配合C++17的折叠表达式,自动展开为每个类型对应的lambda参数; - 泛型lambda是C14引入的特性,C17完全支持,能完美适配模板函数的类型推导需求。
内容的提问来源于stack exchange,提问作者mexx
相关产品推荐
相关产品推荐

