C++可变参数模板遍历的双括号语法作用及使用规则是什么
C++ 折叠表达式相关问题解答
你在查阅std::integer_sequence资料碰到的这段tuple打印代码,核心用到了C++17引入的折叠表达式特性,针对你提的几个问题逐一说明:
双层括号的作用
代码里的((os << (Is == 0? "" : ", ") << std::get<Is>(t)), ...)就是折叠表达式的典型写法,两层括号的作用完全不同:
- 最外层的括号是折叠表达式的强制语法要求,所有折叠表达式都必须被包裹在这层括号里,少了编译器根本识别不了这是折叠语法。
- 内层括号用来包裹单次执行的输出逻辑:因为逗号运算符是C++中优先级最低的运算符,如果不加这层括号,折叠展开时的运算顺序会完全错乱,编译直接报错。内层括号把单次索引对应的输出操作打包成一个整体,配合逗号运算符从左到右求值的规则,逐次执行每个参数包元素对应的逻辑。
这行代码编译期展开后等价于顺序执行:
os << "" << std::get<0>(t); os << ", " << std::get<1>(t); os << ", " << std::get<2>(t); // ... 按索引顺序直到最后一个元素
全程没有运行时循环开销,是编译期遍历参数包的最高效写法之一。
是否仅支持非类型模板参数?
不是。折叠表达式对所有类型的参数包都生效:
- 既可以展开你例子里的
std::size_t... Is这类非类型模板参数包 - 也可以展开类型模板参数包
- 还可以直接展开函数的可变参数包
比如下面的求和函数就是直接展开函数参数包,和非类型模板参数没有关系:
template<typename... Args> auto add_all(Args... args) { return (args + ...); }
遍历顺序是否必须与参数顺序一致?
顺序由折叠方向和运算符本身的求值规则共同决定:
- 你代码里用的是右折叠写法
(表达式, ...),配合逗号运算符(逗号运算符严格要求从左到右求值,先算左操作数再算右操作数),执行顺序和参数包的声明顺序完全一致。 - 就算换成左折叠写法
(..., 表达式),配合逗号运算符的时候执行顺序也和参数包顺序一致,不会乱序。只有用+、<<这类没有强制左到右求值要求的运算符时,折叠方向才会改变运算的结合顺序。
是否支持反向遍历?
完全支持,不需要改动传入的索引序列生成逻辑,只要在展开时调整索引计算即可。最常见的写法是先拿到参数包的总长度,展开时用总长度减去当前索引得到倒序的位置,示例代码如下:
template<class Ch, class Tr, class Tuple, std::size_t... Is> void print_tuple_reverse(std::basic_ostream<Ch,Tr>& os, const Tuple& t, std::index_sequence<Is...>) { constexpr std::size_t total_size = sizeof...(Is); bool first_elem = true; (( [&](){ auto reverse_idx = total_size - 1 - Is; os << (first_elem ? "" : ", ") << std::get<reverse_idx>(t); first_elem = false; }() ), ...); }
调用时只要正常传入正序生成的std::index_sequence即可实现反向遍历。
能否跳过指定序号的元素?
可以,而且没有额外运行时开销。只要在单次元素的处理逻辑里加入if constexpr编译期判断,不符合条件的分支会在编译阶段直接被删掉,根本不会生成对应代码。比如跳过索引为2的元素,写法如下:
template<class Ch, class Tr, class Tuple, std::size_t... Is> void print_tuple_skip(std::basic_ostream<Ch,Tr>& os, const Tuple& t, std::index_sequence<Is...>) { bool first_elem = true; (( [&](){ if constexpr (Is != 2) { // 编译期判断,直接跳过索引2的元素 os << (first_elem ? "" : ", ") << std::get<Is>(t); first_elem = false; } }() ), ...); }
除了按序号跳过,你还可以写任意编译期可判断的过滤规则,比如只打印能转换成int的元素、跳过值为空的元素等等,灵活度很高。
内容的提问来源于stack exchange,提问作者Type Definition
相关产品推荐
相关产品推荐

