【问题标题】:C++ error: no matching function for call to 'print_size'C++ 错误:没有用于调用“print_size”的匹配函数
【发布时间】:2018-05-23 14:34:04
【问题描述】:

我有这个代码:

#include <iostream>
#include <vector>

template<typename T>
void print_size(std::vector<T> a)
{
    std::cout << a.size() << '\n';
}

int main()
{
    std::vector<int> v {1, 2, 3};
    print_size(v);

    auto w = {1, 2, 3};
    // print_size(w); // error: no matching function for call to 'print_size'
                      // candidate template ignored: could not match 'vector' against 'initializer_list'
}

...编译和运行没有任何问题。但是如果我启用注释掉的行,它会产生错误no matching function for call to 'print_size'

我想知道在 C++11 及更高版本中编写此代码的正确方法是什么。

【问题讨论】:

  • ` 因为 C++11 我们应该尝试在任何地方使用 auto` - 不。 AAA 是个糟糕的主意。 C++11 中正确惯用的方式是 C++17 中的 std::vector&lt;int&gt; w{1, 2, 3};std::vector w{1, 2, 3}
  • 对于 AAA,auto w = std::vector&lt;int&gt;{1, 2, 3};...
  • 你的auto w被自动识别为initializer_list,这是合理的。您不能指望编译器将其识别为std::vector&lt;int&gt;,因为{x, x, x} 不一定是vector(可能是任何类型的容器或原始数组)并且x 不一定是int
  • 为什么提供一个不起作用的代码并要求一种基于意见的修复方法?我相信最多有两到三种方法可以解决它。如果答案中记录了这两种或三种方式,那么它应该是一个客观的答案。

标签: c++ c++11 initializer-list auto


【解决方案1】:

对于auto w = {1, 2, 3};w 的类型将是std::initializer_list&lt;int&gt;,而print_size(w); 失败,因为模板参数T 无法推断; template argument deduction 不考虑隐式转换。

类型推导不考虑隐式转换(除了上面列出的类型调整):这是重载解析的工作,稍后会发生。

您可以显式指定模板参数,

print_size<int>(w);

或者您可以将w 改为std::vector&lt;int&gt;;如果您坚持使用auto,则需要明确指定类型。

auto w = std::vector<int>{1, 2, 3};
print_size(w);

【讨论】:

    【解决方案2】:

    问题是print_size 的参数类型。 您的auto w = {1, 2, 3}; 的类型为std::initializer_list&lt;int&gt;,这与vector&lt;T&gt; 不匹配,没有自动转换。

    所以你可以这样纠正print_size

    template<class T>
    void print_size(std::initializer_list<T> a)
    {
        std::cout << a.size() << '\n';
    }
    

    或者更好地改变模板的参数化方式:

    template<class T>
    void print_size(const T& a)
    {
        std::cout << a.size() << '\n';
    }
    

    【讨论】:

      【解决方案3】:

      不幸的是,如果没有 C++17 推导指南,编译器无法从 std::initializer_list&lt;T&gt; 类型的参数中推导出 std::vector&lt;T&gt; 参数的 T

      我建议为 print_size(std::initializer_list&lt;T&gt; const&amp;) 添加重载。

      【讨论】:

        【解决方案4】:

        铸造 w 将是一个解决方案

            print_size((std::vector<int>)w);
        

        【讨论】:

        • 强制转换只会调用构造函数,因此使用std::vector&lt;int&gt;{w} 会更直接。
        猜你喜欢
        • 2016-01-18
        • 2014-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多