【问题标题】:C++ template: no matching function for callC++ 模板:没有匹配的调用函数
【发布时间】:2018-06-27 05:43:30
【问题描述】:

我不明白为什么这个程序无法使用 -std=c++14 编译 g++ 7.3 或 clang++ 5.0。

A 可以从 const int 初始化,如图所示。也可以从const int 创建对A 的常量引用,但使用const int 调用f(const A &) 失败。为什么?

#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;
}

【问题讨论】:

    标签: c++ templates initialization implicit-conversion


    【解决方案1】:

    给定f(i);,应用copy initialization。而i(类型为const int)需要转换为A,需要用户自定义转换两次;从const int 到V,从V 到A。但在一个隐式转换序列中只允许进行一次用户自定义转换。

    机器人const A a1{i}; 和const A &amp;a2 = A{i}; 是direct initialization,只需要从i(类型为const int)到A 的构造函数(即V)的参数的一次隐式转换,所以他们工作正常。

    注意复制初始化和直接初始化的区别,

    此外,复制初始化中的隐式转换必须直接从初始化器生成 T,而例如直接初始化需要从初始化程序隐式转换为 T 的构造函数的参数。

    作为一种解决方法,您可以在将i 传递给f() 之前对其执行显式转换。

    【讨论】:

      【解决方案2】:

      为了函数调用的目的将i 转换为A 将需要两次用户定义的转换(int -&gt; V -&gt; A)。该标准对每个隐式转换序列设置了单个用户定义转换的硬限制。

      如果您尝试“直接”将a2 绑定到i,也会发生同样的情况。因此,在向 f 提供参数时,您还需要进行函数式风格转换 (A{i})。

      【讨论】:

        【解决方案3】:

        您需要在这里进行两次连续的隐式类型转换,但是 C++ 可以为您进行一次隐式转换。如果您想让编译器为您生成正确的类型代码,请将template 用于函数f,如下所示。

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

        之所以需要两种类型转换,是因为结构中只有一个构造函数,它采用V 类型。如果您想摆脱两种类型转换作为第二种解决方案,您可以添加另一个以int 作为参数的构造函数,如下所示

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

        【讨论】:

          【解决方案4】:

          复制初始化不支持两个用户定义的转换。解决这个问题的简单方法是用 A 包裹 i ,同时用 f(A(i)) 传递给函数f

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-11
            • 2011-03-03
            • 2013-01-26
            • 2017-09-26
            • 1970-01-01
            相关资源
            最近更新 更多