c++ - 对不可演绎函数模板参数的误解
问题描述
来自C++ 模板 - 完整指南第 2 版:
此外,此类参数不能有用地放置在模板参数包之后或出现在部分特化中,因为没有办法明确指定或推导出它们。
template<typename ...Ts, int N> void f(double (&)[N+1], Ts ... ps); // useless declaration because N // cannot be specified or deduced
其中这些参数指的是(我认为)与那些永远无法推断的模板参数相对应的模板参数。即在上面的例子N
中是不能推导的参数,因为N+1
“太复杂而无法推导”。
但是为什么指定它是不可能的?我知道不可能指定N
并...Ts
推导出来,但是为什么不能全部指定呢?换句话说,指定Ts=[int]
和N=2
通过以下有什么问题?
double x[3];
f<int,2>(x,1);
解决方案
即在上面的例子
N
中是不能推导的参数,因为N+1
“太复杂而无法推导”。
形式上,这是[temp.deduct.type]/5.3
未推断的上下文是:
- [...]
- /5.3 非类型模板参数或绑定的数组,其中子表达式引用模板参数。
正如以下问答中已经介绍的那样:
特别是在功能模板的模板头中
template<typename ...Ts, int N> // ... function template
函数模板的模板形参包后面不应有另一个模板形参,除非该模板形参可以从函数模板的形参类型列表([dcl.fct])推导出来或具有默认实参([temp.fct]) 。扣除])。
特别是根据函数模板的特殊规则(由于函数模板参数推导),模板参数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);
但是为什么指定它是不可能的?
正如链接到问答中所讨论的那样,尽管“编译器支持这一点是有意义的”,但标准没有,并且领先的模板参数包贪婪地包含所有显式提供的模板参数,即使是那些作为一部分无效的模板参数扩展包(例如类型模板参数包的非类型模板参数)。
推荐阅读
- node.js - Puppeteer - 单击 div 不起作用
- javascript - 如何从 Promisse.all 获取每个 json,然后在 setState 中分配 Json 属性
- mysqli - 如何为 CASE WHEN THEN SELECT 语句赋予别名
- python - Pyspark应用不同的基于reduce函数的键
- javascript - 在完成之前不会再次向内部 observable 发出的 RxJS 运算符
- firebase - 无法使用我的 Firebase 会话设置带有谷歌存储的存储桶
- javascript - Webpack 热中间件不工作
- python - python 3.5 Flask 安装在 apache 2.4 上
- ios - UILabel 中的不同文本在 UICollectionView 单元格中保持相同的字体大小
- java - 如何将自定义插件发布到本地 Maven,然后在另一个本地项目中使用?