c++ - 为什么隐式转换不应用于模板化函数参数?

标签 c++ templates gcc c++17 implicit-conversion

我遇到了一些模板问题,这些问题已缩小到以下示例(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);
          |                        ^
    
    根本错误似乎是:

    types ‘const T’ and ‘int’ have incompatible cv-qualifiers


    我理解从字面上看这意味着什么,但我不明白为什么会这样。我的期望是,调用item<int> :: operator item<const int> () const时将应用butNotWhenTemplated(i)转换运算符,就像调用conversionToConstRefWorks(i)时所应用的那样,并且int将选择T
    我的主要问题是:为什么不编译?
    我的另一个问题是:出于本文范围之外的原因,butNotWhenTemplated必须是模板,并且必须为所有<const T>参数指定item,并且在调用它时我无法显式指定模板参数。有没有办法使这些约束条件起作用?
    Here it is on ideone(GCC 8.3)。

    最佳答案

    item<int> i;
    template <typename T> void butNotWhenTemplated (const item<const T> &) { }
    butNotWhenTemplated(i); 
    
    根据template argument substitution规则,找不到与T匹配的item<const T>item<int>。在考虑任何转换(内置或用户定义的)之前,这将以硬错误方式失败。

    Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later. However, if deduction succeeds for all parameters that participate in template argument deduction, and all template arguments that aren't deduced are explicitly specified or defaulted, then the remaining function parameters are compared with the corresponding function arguments.

    关于c++ - 为什么隐式转换不应用于模板化函数参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65401573/

    相关文章:

    c - 检测明显的字节序问题

    gcc - mfence 和 asm volatile 的区别 ("": : : "memory")

    c++ - 不知道如何使用 popt 库

    c++ - 将值插入已发布的图像?

    C++ 类重载 : is it possible to make compiler see which one to use based on template?

    c++ - std::function 带模板,类型问题,没有匹配的调用函数

    C++:单例?如何将参数传递给构造函数?

    c++ - 为什么 QObject::disconnect(const QMetaObject::Connection &connection) 采用 const 参数来修改它?

    c++ - 模板类的模板友元函数

    c++ - arm gcc5 的交叉编译 - 正确使用 memcpy