C++可变参数模板与函数对象实现多条件向量过滤的折叠表达式用法
编译报错的核心原因
你的代码存在两处违反C++语法规则的问题,直接触发编译错误:
- 可变参数包展开缺少合法的表达式上下文:C++规定参数包不能脱离运算符结构单独展开,你把
...直接放在函数调用的结尾位置,编译器根本识别不了这部分语义,自然会抛出“意外标记...、预期右括号”的语法提示 - 完美转发的模板参数写法错误:
std::forward需要在尖括号位置传入对应参数的类型,你误把运行时的值参数filters写在了模板参数位,属于明显的语法错误
要实现“保留原容器中满足全部过滤规则的元素”的需求,确实需要使用C++17引入的折叠表达式才能简洁完成多过滤器的组合判断。
正确实现步骤
1. 修正基础语法问题
你定义的两个函数对象结构体结尾漏掉了C++强制要求的分号,需要补上:
struct EvenNumber { bool operator()(int const num) const { return num % 2 == 0; } }; struct GreaterThenFive { bool operator()(int const num) const { return num > 5; } };
2. 用逻辑与折叠实现多过滤器判断
折叠表达式的核心作用就是把可变参数包中的所有元素和指定运算符做组合求值,针对“所有过滤器都通过才保留元素”的逻辑,我们可以用一元左折叠的写法,把每个过滤器的调用结果用&&运算符串联:
#include <vector> #include <utility> // std::forward 所在头文件 template <typename... Filters> std::vector<int> filter_out(std::vector<int> const& vec, Filters&&... filters) { std::vector<int> result; for (int const num : vec) { // 逻辑与折叠:展开后等价于把所有过滤器的返回值做连续逻辑与运算 if ((... && std::forward<Filters>(filters)(num))) { result.push_back(num); } } return result; }
实现逻辑说明
- 上述折叠写法的展开效果完全符合需求:当传入2个过滤器时,判断逻辑等价于
过滤器1(num) && 过滤器2(num) - 当没有传入任何过滤器时,逻辑与折叠的默认求值结果为
true,对应原容器元素全部保留的行为,和预期逻辑完全自洽 - 相比手写递归展开可变参数的传统写法,折叠表达式更简洁,且编译器生成的机器码效率没有差异
3. 调整示例调用的写法
你原本写的示例调用filter_out({1, 2, 3, 4, 5, 6, 7}, ...) 会因为C++模板推导规则,无法把花括号初始化列表识别为std::vector<int>类型,需要显式构造容器:
auto result = filter_out( std::vector<int>{1, 2, 3, 4, 5, 6, 7}, EvenNumber{}, GreaterThenFive{} ); // 最终result中只会保留数值6,是唯一同时满足“偶数”“大于5”两个规则的元素
注:如果项目使用C++14及更早标准,没有折叠表达式支持,就需要通过递归模板的方式手动展开可变参数,实现复杂度会高很多。
内容的提问来源于stack exchange,提问作者JerryThePineapple
相关产品推荐
相关产品推荐

