对不可推导的函数模板参数的误解
Misunderstanding about non-deducible function template arguments
来自 C++ 模板 - 完整指南第 2 版:
Moreover, such parameters can't usefully be placed after a template parameter pack or appear in a partial specialization, because there would be no way to explicitly specify or deduce them.
template<typename ...Ts, int N>
void f(double (&)[N+1], Ts ... ps); // useless declaration because N
// cannot be specified or deduced
where such parameters指的是(我认为)那些永远无法推导的模板参数对应的模板参数。 IE。在上面的例子中 N
是无法推导的参数,因为 N+1
“太复杂了,无法推导”。
但为什么无法指定呢?我知道不可能指定 N
并推导 ...Ts
,但为什么不能指定它们?换句话说,通过以下方式指定 Ts=[int]
和 N=2
有什么问题?
double x[3];
f<int,2>(x,1);
I.e. in the example above N
is the parameter that cannot be deduced because N+1
is "too complicated to be deduced".
形式上,这是 [temp.deduct.type]/5.3
The non-deduced contexts are:
- [...]
- /5.3 A non-type template argument or an array bound in which a subexpression references a template parameter.
正如以下问答中所涵盖的那样:
特别是在函数模板的模板头中
template<typename ...Ts, int N>
// ... function template
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).
特别是根据函数模板的特殊规则(由于函数模板参数推导),模板参数 N
必须可以从函数的参数列表 中推导出来。根据 [temp.deduct.type]/5.3,它不是,并且永远不会调用以下示例中的 f
(过载解析永远不会将其视为可行的候选者):
template<typename ...Ts, int N>
void f(double (&)[N+1], Ts ... ps);
而以下函数都可以通过重载解析找到:
template<typename ...Ts, int N>
void g(double (&)[N], Ts ... ps); // N deducible from function parameter
template<typename ...Ts, int N = 2> // N has a default-template-argument
void h(double (&)[N+1], Ts ... ps);
But why specifying it is not possible?
正如在 Q&A 链接中所讨论的,虽然“编译器支持这一点是有意义的”,但标准并不支持,并且领先的模板参数包贪婪地包含所有显式提供的模板参数,即使是那些会作为扩展包的一部分无效(例如,类型模板参数包的非类型模板参数)。
来自 C++ 模板 - 完整指南第 2 版:
Moreover, such parameters can't usefully be placed after a template parameter pack or appear in a partial specialization, because there would be no way to explicitly specify or deduce them.
template<typename ...Ts, int N> void f(double (&)[N+1], Ts ... ps); // useless declaration because N // cannot be specified or deduced
where such parameters指的是(我认为)那些永远无法推导的模板参数对应的模板参数。 IE。在上面的例子中 N
是无法推导的参数,因为 N+1
“太复杂了,无法推导”。
但为什么无法指定呢?我知道不可能指定 N
并推导 ...Ts
,但为什么不能指定它们?换句话说,通过以下方式指定 Ts=[int]
和 N=2
有什么问题?
double x[3];
f<int,2>(x,1);
I.e. in the example above
N
is the parameter that cannot be deduced becauseN+1
is "too complicated to be deduced".
形式上,这是 [temp.deduct.type]/5.3
The non-deduced contexts are:
- [...]
- /5.3 A non-type template argument or an array bound in which a subexpression references a template parameter.
正如以下问答中所涵盖的那样:
特别是在函数模板的模板头中
template<typename ...Ts, int N> // ... function template
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).
特别是根据函数模板的特殊规则(由于函数模板参数推导),模板参数 N
必须可以从函数的参数列表 中推导出来。根据 [temp.deduct.type]/5.3,它不是,并且永远不会调用以下示例中的 f
(过载解析永远不会将其视为可行的候选者):
template<typename ...Ts, int N> void f(double (&)[N+1], Ts ... ps);
而以下函数都可以通过重载解析找到:
template<typename ...Ts, int N>
void g(double (&)[N], Ts ... ps); // N deducible from function parameter
template<typename ...Ts, int N = 2> // N has a default-template-argument
void h(double (&)[N+1], Ts ... ps);
But why specifying it is not possible?
正如在 Q&A 链接中所讨论的,虽然“编译器支持这一点是有意义的”,但标准并不支持,并且领先的模板参数包贪婪地包含所有显式提供的模板参数,即使是那些会作为扩展包的一部分无效(例如,类型模板参数包的非类型模板参数)。