c++ - 为什么隐式转换不适用于模板化函数参数?
问题描述
我遇到了一些模板问题,我已将其范围缩小到以下示例 (C++17):
template <typename T> struct item {
operator item<const T> () const { return item<const T>(); }
};
void conversionToConstRefWorks (const item<const int> &) { }
template <typename T>
void butNotWhenTemplated (const item<const T> &) { }
int main () {
item<int> i;
item<const int> ci;
// these all compile fine:
conversionToConstRefWorks(ci);
conversionToConstRefWorks(i);
butNotWhenTemplated(ci);
// but this one fails:
butNotWhenTemplated(i);
}
在那个例子中:
item<T>
有一个隐式转换运算符到item<const T>
, 和- 转换似乎有效
conversionToConstRefWorks()
,但是 - 转换似乎错过了
butNotWhenTemplated()
,其中 anitem<const int>
可以很好地传递,但传递 anitem<int>
无法编译。
该示例的编译失败(GCC 9.3):
g++ --std=c++17 -W -Wall -pedantic -Wno-unused-variable const_interop.cpp -o const_interop
const_interop.cpp: In function ‘int main()’:
const_interop.cpp:54:24: error: no matching function for call to ‘butNotWhenTemplated(item<int>&)’
54 | butNotWhenTemplated(i);
| ^
const_interop.cpp:40:6: note: candidate: ‘template<class T> void butNotWhenTemplated(const item<const T>&)’
40 | void butNotWhenTemplated (const item<const T> &) {
| ^~~~~~~~~~~~~~~~~~~
const_interop.cpp:40:6: note: template argument deduction/substitution failed:
const_interop.cpp:54:24: note: types ‘const T’ and ‘int’ have incompatible cv-qualifiers
54 | butNotWhenTemplated(i);
| ^
根本错误似乎是:
'const T' 和 'int' 类型具有不兼容的 cv 限定符
我理解字面意义上的意思,但我不明白为什么会这样。我的期望是item<int> :: operator item<const int> () const
调用时会应用转换运算符,butNotWhenTemplated(i)
就像调用时应用它一样conversionToConstRefWorks(i)
,并且int
会为T
.
我的主要问题是:为什么不编译?
我的另一个问题是:由于本文范围之外的原因,butNotWhenTemplated
必须是模板并且必须指定<const T>
所有item
参数,并且在调用它时我无法显式指定模板参数。有没有办法在这些限制条件下完成这项工作?
这里是 ideone (GCC 8.3)。
解决方案
item<int> i;
template <typename T> void butNotWhenTemplated (const item<const T> &) { }
butNotWhenTemplated(i);
根据模板参数替换规则,找不到T
匹配item<const T>
项item<int>
。在考虑任何转换(内置或用户定义)之前,这会以硬错误方式失败。
类型推导不考虑隐式转换(除了上面列出的类型调整):这是重载解析的工作,稍后会发生。但是,如果参与模板实参推导的所有参数推导成功,并且所有未推导的模板实参都被显式指定或默认,则剩余的函数参数将与相应的函数实参进行比较。
推荐阅读
- x86 - WinDbg 是否显示 [MOV r32,r/m32] 的错误操作码?
- jenkins - 我在哪里可以找到文件系统上 jenkins 配置中的“启用代理 → 主访问控制”选项?
- mysql - 如何加快 NOT IN 查询?
- bitbucket - 仅 Haproxy 公共 jenkin webhook
- php - 将一列拆分为三列
- javascript - 类型不可分配给条件类型
- javascript - 左键单击列表元素并隐藏剩余的元素
- css - scss 渲染错误 [内部错误:未找到要读取的文件或无法读取:]
- gnu-parallel - 如何将输入文件中的子字符串作为要在 GNU 并行中执行的程序的参数?
- authentication - 我需要在没有中间件的情况下在 NestJS 中进行身份验证