繁体   English   中英

为什么隐式转换不适用于模板化的 function 参数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM