遇到如下代码,对于 func2
没有看懂。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
template<typename T>
struct DataStruct {
DataStruct(int i, T n): index(i), value(n) {}
int index;
T value;
};
template<typename T>
auto func1(string prefix, int i, T n) {
cout << __FUNCTION__ << "(" << prefix << ", " << i << ", " << n << ")" << endl;
}
template<typename... T> // mark 1
auto func2(string p, const DataStruct<T>&&... s) { // mark 2
(func1(p, s.index, s.value), ...); // mark 3
}
int main() {
func2<string>("hi ", DataStruct<string>(12, "Tom"), DataStruct<string>(29, "Mason"), DataStruct<int>(100, 999));
cout << "done\n";
}
// execute result
/*
func1(hi , 12, Tom)
func1(hi , 29, Mason)
func1(hi , 100, 999)
done
*/
|
查询后得知是 C++
的可变模板(variadic template
)和折叠表达式(fold expression
)。
可变模板(Variadic Template)¶
可变模板是 C++11 引入的功能,允许模板接受不定数量的模板参数。这对于需要处理多个参数类型或数量的情况非常有用。例如:
1
2
3
4
5
6
7
|
void coutX() {} // 终止条件
template<typename T, typename... Types>
void coutX(const T& t, const Types&... args) {
cout << t << endl; // cout 1st argument
coutX(args...); // 对可变参数递归调用 coutX
}
|
其中非模板重载函数 contX()
是递归调用的终止条件。
折叠表达式(Fold Expression)¶
折叠表达式是 C++17
为配合 Variadic Template
使用引入的功能,它允许在模板展开过程中进行一元或二元操作。折叠表达式有两种形式:左折叠和右折叠。
对应的展开关系如下:
Fold Expression |
Evaluation |
(E op ...) |
(E1 op (... op (EN-1 op EN))) |
(... op E) |
(((E1 op E2) op ...) op EN) |
(E op ... op I) |
(E1 op (... op (EN−1 op (EN op I)))) |
(I op ... op E) |
((((I op E1) op E2) op ...) op EN) |
其中
- 左折叠形式:
(expr op ...)
,其中 expr
是一个表达式,op
是二元操作符。
- 右折叠形式:
(... op expr)
,同样,expr
是一个表达式,op
是二元操作符。
1
2
3
4
|
template<typename... T> // variadic template
auto func2(string p, const DataStruct<T>&&... s) { // variadic template
(func1(p, s.index, s.value), ...); // fold expression
}
|
在上面的例子中,func2
函数的实现使用了右折叠表达式(expr op ...)
。其对应关系如下:
expr
: func1(p, s.index, s.value)
op
: ,
...
: ...
另一个 (I op ... op E)
折叠表达式的例子:
1
2
3
4
5
|
template<typename... Values>
auto sum(Values const&... values) {
return (0 + ... + values);
}
sum(1, 2, 3, 4); // same as (0 + 1 + 2 + 3 + 4)
|
其中
I
: 0
op
: +
...
: ...
op
: +
E
: values
对于前面 contX
的例子,在使用 C++17
的 Fold Expression
后就不需要再手动实现递归和终止条件,可简化如下:
1
2
3
|
void coutX(const Types&... args) {
cout << ... << args << endl;
}
|