C++17中模板参数包的偏序规则
Partial ordering rules of template parameter pack in C++17
这是来自 temp.deduct.partial 的示例。
template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more specialized
// than the variadic templates #1 and #2
为什么 f(1, 2, 3)
调用 #2
?
CWG1395之前很容易理解。 #2
不能从#1
推导出来,因为Args
是参数包,而T1
不是,所以#2
比#1
更特化。
但是CWG1395之后如何理解这个例子呢?现在看来T1
可以从Args
推导出来
Similarly, if A
was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.
CWG1395 似乎没有更改与您从标准中引用的示例相关的任何内容。请记住,发布 CWG1935 是为了允许例如
template<class T>
void print(ostream &os, const T &t) {
os << t;
}
template <class T, class... Args>
void print(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
print(os, rest...);
}
int main() {
print(cout, 42);
print(cout, 42, 1.23);
}
在问题 1395 之前,调用 print(os, rest...)
的参数包扩展永远无法与 void print(ostream &os, const T &t)
的模板参数 T
匹配,因为函数参数包必须显式地匹配模板参数包:
If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.
随着更改,第一个 print
函数现在可以与函数参数包调用匹配,并且被认为比 13.10.3.5 [temp.deduct.partial] 第 10 段中的第二个重载更专业:
If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and if G has a trailing paramter pack for which F does not have a corresponding parameter, and if F does not have a trailing parameter pack, then F is more specialized than G.
您上面的示例与函数参数包无关,因此不受更改的影响,因此 [temp.deduct.type]/13.10.3.6 §10 的规则仍然适用。
这是来自 temp.deduct.partial 的示例。
template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more specialized
// than the variadic templates #1 and #2
为什么 f(1, 2, 3)
调用 #2
?
CWG1395之前很容易理解。 #2
不能从#1
推导出来,因为Args
是参数包,而T1
不是,所以#2
比#1
更特化。
但是CWG1395之后如何理解这个例子呢?现在看来T1
可以从Args
推导出来
Similarly, if
A
was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.
CWG1395 似乎没有更改与您从标准中引用的示例相关的任何内容。请记住,发布 CWG1935 是为了允许例如
template<class T>
void print(ostream &os, const T &t) {
os << t;
}
template <class T, class... Args>
void print(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
print(os, rest...);
}
int main() {
print(cout, 42);
print(cout, 42, 1.23);
}
在问题 1395 之前,调用 print(os, rest...)
的参数包扩展永远无法与 void print(ostream &os, const T &t)
的模板参数 T
匹配,因为函数参数包必须显式地匹配模板参数包:
If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.
随着更改,第一个 print
函数现在可以与函数参数包调用匹配,并且被认为比 13.10.3.5 [temp.deduct.partial] 第 10 段中的第二个重载更专业:
If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and if G has a trailing paramter pack for which F does not have a corresponding parameter, and if F does not have a trailing parameter pack, then F is more specialized than G.
您上面的示例与函数参数包无关,因此不受更改的影响,因此 [temp.deduct.type]/13.10.3.6 §10 的规则仍然适用。