[英]Why is implicit conversion not applied to templated function parameter?
我遇到了一些模板问题,我已将其缩小为以下示例 (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()
中似乎错过了转换,其中可以很好地传递item<const int>
但传递item<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
conversion operator 将在调用butNotWhenTemplated(i)
时应用,就像在调用conversionToConstRefWorks(i)
时应用的一样,并且该int
将被选择用于T
。
我的主要问题是:为什么不编译?
我的另一个问题是:出于本文 scope 之外的原因, butNotWhenTemplated
必须是一个模板并且必须为所有item
参数指定<const T>
,并且我无法在调用它时明确指定模板参数。 有没有办法使它在这些约束下工作?
这是在 ideone (GCC 8.3) 上。
item<int> i;
template <typename T> void butNotWhenTemplated (const item<const T> &) { }
butNotWhenTemplated(i);
根据模板参数替换规则,无法为item<const T>
T
匹配item<int>
的 T。 在考虑任何转换(内置或用户定义的)之前,这会以硬错误方式失败。
类型推导不考虑隐式转换(除了上面列出的类型调整):这是稍后发生的重载决议的工作。 但是,如果所有参与模板实参推导的参数都推导成功,并且所有未推导的模板arguments都是显式指定或默认的,则将剩余的function参数与对应的function arguments进行比较。
试试这个重载:
template <typename T>
void butNotWhenTemplated(const item<const T>&) { }
template <typename T>
void butNotWhenTemplated(const item<T>& x) {
butNotWhenTemplated<const T>(x);
}
附录:
您试图通过对 const 的引用传递,但即使在非模板情况下,隐式转换也会创建 object 的副本。 您可能想在这里重新考虑您的设计。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.