c++ - 为什么 C++ 编译器无法推断 lambda 参数的类型?

标签 c++ template-argument-deduction

我有以下代码,无法编译

template <typename T>
void call_with(std::function<void(T)> f, T val) {
    f(val);
}

int main() {
    auto print = [](int x) { std::cout << x; };
    call_with(print, 42);
}

编译错误看起来像这样

tst.cpp:17:2: error: no matching function for call to 'call_with'
        call_with(print, 42);
        ^~~~~~~~~
tst.cpp:11:6: note: candidate template ignored: could not match 'function<void (type-parameter-0-0)>' against
      '(lambda at tst.cpp:16:15)'
void call_with(std::function<void(T)> f, T val) {
     ^
1 error generated

我尝试用 g++ tst.cpp -o tst -std=c++17 编译它

所以我知道有时 C++ 可以在某些条件下推导出模板参数,但我想知道为什么在这种情况下它无法编译此代码。看起来类型 T 不能有任何其他选项可以是任何东西,但 int 和 f绝不是 std::function<void(int)> .

最佳答案

因为print不是std::function<void(int)> .并且它可以转换为多个有效类型。

尝试运行

    auto print = [](int x) { std::cout << x; };
    std::cout << typeid(print).name()<<"\n";
    std::function<void(unsigned __int64)> print_a = std::function<void(unsigned __int64)>(print);
    std::cout << typeid(print_a).name() << "\n";
    auto print_b = std::function<void(unsigned __int64)>(print);
    std::cout << typeid(print_b).name() << "\n";

你将会得到

class <lambda_d103cbf184cf5bdcf1494399ee6d564a>
class std::function<void __cdecl(unsigned __int64)>
class std::function<void __cdecl(unsigned __int64)>

这显示 printlambda ,并且可以转换为多种std::function<void(T)>像:

    auto print = [](int x) { std::cout << x; };
    auto print2 = std::function<void(unsigned __int64)>(print);
    auto print3 = std::function<void(unsigned short)>(print);
    auto print4 = std::function<void(char)>(print);

精确的std::function<void(int)>可以推导出对象:

std::function<void(int)> print = [](int x) { std::cout << x; };
call_with(print, 42);

并且42也需要是正确的类型才能推导

std::function<void(int)> + int意味着T=int

std::function<void(short)> + short意味着T=short

但是std::function<void(short)> + int无法推论。 所以你会得到编译错误:

std::function<void(short)> print = [](short x) { std::cout << x; };
call_with(print, 42);

正确的版本是

std::function<void(short)> print = [](short x) { std::cout << x; };
call_with(print, short(42));

关于c++ - 为什么 C++ 编译器无法推断 lambda 参数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65060766/

相关文章:

c++ - 带有 size_t 模板参数的函数

c++ - 为什么在某些特定情况下拥有多个线程(并行处理)会降低性能?

c++ - 使用 C++ 将字符转换为字节表示

c++ - 构造函数的初始化列表中的函数调用是否按顺序排列?

c++ - 使用可变参数模板进行隐式转换

c++ - 仅当给出超过 n 个参数时,如何启用可变参数模板构造函数?

c++ - OpenGL - 具有多个纹理的蒙版

c++ - Poco DateTimeFormatter - 使用当前时区打印时间戳

c++ - 具有相同类型的可变模板参数的构造函数无法编译

c++ - 使用 std::make_unique 构造实例时类模板推断类型的方式?