简体   繁体   English

C ++模板:没有匹配的调用函数

[英]C++ template: no matching function for call

I cannot understand why this program fails to compile both with g++ 7.3 or clang++ 5.0 using -std=c++14. 我无法理解为什么这个程序无法用g ++ 7.3或clang ++ 5.0使用-std = c ++ 14进行编译。

A can be initialized from a const int as shown. 可以从const int初始化A ,如图所示。 A const reference to A can also be create from a const int but call to f(const A &) with a const int fails. 甲常量引用A也可以从一个创建const int但来电f(const A &)const int失败。 Why? 为什么?

#include <iostream>

struct V {
  int i;
  template <class T>
  V(const T &t) : i{t} {}
};

struct A {
  int i;
  A(V v) : i{v.i} {}
};

void f(const A &) {}

int main() {
  const auto i = 42;
  const A a1{i};              // OK
  std::cout << a1.i << '\n';  // 42
  const A &a2 = A{i};         // OK
  std::cout << a2.i << '\n';  // 42
  f(i);                       // no matching function for call to 'f'
  return 0;
}

Converting i to an A for the purpose of the function call will require two user defined conversions ( int -> V -> A ). 出于函数调用的目的将i转换为A将需要两个用户定义的转换( int -> V -> A )。 The standard places a hard limit of a single user defined conversion on each implicit conversion sequence. 该标准对每个隐式转换序列设置单个用户定义转换的硬限制。

The same would happen if you were to try and bind a2 to i "directly". 如果您尝试将a2 “直接”绑定到i也会发生同样的情况。 So you need to do a functional style cast ( A{i} ) when giving an argument to f as well. 因此,在为f赋予参数时,您还需要执行函数样式转换( A{i} )。

Given f(i); 鉴于f(i); , copy initialization is applied. ,应用复制初始化 And i (with type const int ) needs to be converted to A , two user-defined conversions are required; 并且i (使用类型const int )需要转换为A ,需要两个用户定义的转换; from const int to V , and from V to A . const intV ,从VA But only one user-defined conversion is allowed in one implicit conversion sequence. 但在一个隐式转换序列中只允许一个用户定义的转换。

Bot const A a1{i}; Bot const A a1{i}; and const A &a2 = A{i}; const A &a2 = A{i}; are direct initialization , only one implicit conversion from i (with type const int ) to the argument of A 's constructor (ie V ) is required, so they work fine. 直接初始化 ,只需要从i (使用类型const int )到A的构造函数(即V )的参数进行一次隐式转换,因此它们可以正常工作。

Note the difference between copy initialization and direct initialization, 注意复制初始化和直接初始化之间的区别,

In addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, eg direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor. 此外,复制初始化中的隐式转换必须直接从初始化器生成T,而例如,直接初始化需要从初始化器到T的构造函数的参数的隐式转换。

As a workaround, you can perform explicit conversion on i before passing it to f() . 作为一种变通方法,您可以在将其传递给f()之前对i执行显式转换。

You need two consecutive implicit type conversion here however C++ can do single conversion implicitley for you. 这里你需要两个连续的隐式类型转换,但是C ++可以为你做单个转换implicitley。 If you want to let the compiler to generate the correct typed code for you, use template for the function f like following. 如果您想让编译器为您生成正确的类型代码,请使用template作为函数f ,如下所示。

template <typename T>
void f(const T & x) { std::cout << x << std::endl;}

The reason why you need two type conversion is because of having only one constructor which takes type V in the struct. 你需要两个类型转换的原因是因为只有一个构造函数在结构中采用了类型V If you want to get rid of two type conversion as a second solution, you can add another constructor which takes int as a parameter like following 如果你想摆脱两种类型转换作为第二种解决方案,你可以添加另一个构造函数,它将int作为参数,如下所示

struct A {
    int i;
    A(V v) : i{v.i} {}
    A(int theI) : i{theI} { }
};

Two user defined conversions are not supported in copy initialization. 复制初始化不支持两个用户定义的转换。 Simple work around to the problem is to wrap i with A while passing to funtion f with f(A(i)) 解决这个问题的简单方法是用A包裹我,同时用f(A(i))传递给f

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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