首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

将lambda包装为std::function会产生错误的结果(这是模板参数推导的危险)

将lambda包装为std::function会产生错误的结果,这是因为模板参数推导的危险。lambda表达式是一种匿名函数,可以在需要函数对象的地方使用。而std::function是一个通用的函数封装器,可以存储、复制、调用任何可调用对象(函数、函数指针、成员函数指针、函数对象等)。

当我们将lambda表达式包装为std::function时,编译器需要进行模板参数推导,以确定std::function的模板参数类型。然而,lambda表达式的类型是一个匿名类型,无法直接推导出来。因此,编译器会尝试将lambda表达式转换为函数指针类型,然后再进行推导。但是,这种转换只适用于没有捕获变量的lambda表达式,对于有捕获变量的lambda表达式,转换为函数指针类型会导致错误的结果。

为了避免这种错误,我们可以使用auto关键字来推导lambda表达式的类型,然后将其直接赋值给std::function,而不是进行模板参数推导。示例代码如下:

代码语言:txt
复制
auto lambda = [](int x) { return x * 2; };
std::function<int(int)> func(lambda);

在这个例子中,lambda表达式的类型被推导为一个匿名类型,并使用auto关键字进行声明。然后,我们将lambda表达式直接赋值给std::function,并指定函数的参数类型和返回类型。

需要注意的是,使用auto关键字推导lambda表达式的类型时,需要确保lambda表达式在声明时已经完整定义了参数类型和返回类型。否则,编译器无法推导出正确的类型,仍然会产生错误的结果。

总结起来,将lambda包装为std::function时,应该使用auto关键字来推导lambda表达式的类型,以避免模板参数推导的错误结果。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++11常用新特性快速一览

而这依然产生问题,导致了 C++ 中重载特性会发生混乱,考虑: void foo(char *); void foo(int); 对于这两个函数来说,如果 NULL 又被定义为了 0 那么 foo(...那么在运行时,这个 lambda 表达式就会返回一个匿名实例,是一个右值。所以,我们上面的 lambda 表达式结果就是一个个闭。...,但是返回 lambda 表达式却引用了该变量,当调用这个表达式时,引用是一个垃圾值,产生没有意义结果。...,这很危险,因为你仍然有可能在类对象析构后使用这个 lambda 表达式,那么类似“悬挂引用”问题也产生。...当然,如果你在使用了 mova(a) 之后,还继续使用 a,那无疑是搬起石头砸自己脚,还是导致严重运行错误

2.5K50

Modern c++快速浅析

因为这是一个拷贝指针操作,因此保留原指针不可更改指向性并没有太大意义 auto 大多数情况下auto推断出来结果模板类型推导结果是一样,不同点在于对大括号初始物处理 值与指针等推导 const...对于非模板类型参数而言,使用auto进行自动推断方便很多 template auto是可选项而不是必选项 •对于部分情景而言,使用auto能够避免不少低级错误,如Effective...int arr[pFunc(100)]; 捕获生命周期 C++中其实并没有闭概念,更准确应该lambda划分为带捕获lambda以及不带捕获lambda 在C#这种具备GC机制语言中,闭能够延长捕获变量生命周期...(理解为能够延长生命周期按引用捕获) 而C++中按引用捕获并不能延长对象生命周期,且按引用捕获导致lambda表达式包含了对局部对象引用,这很可能导致空悬引用 std::function<void...C++11后若访问到已delete函数,那么会在编译阶段就得到错误错误诊断提前了 = delete 可以用来修饰任何函数,包括非成员函数和模板具现 template void

15710

浅谈 C++ 元编程

1.4.1 狭义模板 目前最新 C++ 模板分成了 4 类:类模板 (class template),函数模板 (function template),别名模板 (alias template) ...函数 _Factor 有两个重载:一个是对任意非负整数,一个是对 0 为参数。前者利用递归产生结果,后者直接返回结果。...定义 TupleToNullable,拆解元组中所有类型,转化为参数,再把参数中所有类型分别传入 TypeToNullable,最后得到结果重新组装为元组。...而对于模板实参内容检查,则是在实例化过程中完成。所以,程序设计者在编译前,很难发现实例化时可能产生错误。...在元编程中,很多时候只关心推导结果,而不是过程。例如,代码中只关心最后 Factor == 24,而不需要中间过程中产生临时模板。但是在 N 很大时候,编译产生很多临时模板

2.9K60

Chapter 6:Lambda Expressions

每个lambda都会使得编译器产生一个独一无二closure class。一个lambda语句变成它closure class成员函数中可执行指令。 2....默认情况下,从lambda表达式产生内部成员函数operator(),是const属性,这使得闭里面的所有数据成员在lambda体内都是const属性,而bind对象里面移动过来data...类中是一个模板,但是如果normalize函数区分左值参数和右值参数,上面的写法不完全对,要实现完美转发的话需要做两点改动 把x声明为一个通用引用 使用std::forward把x转发给normalize...return normalize(std::forward(x); }; //1,decltype推导x类型A //2.std::forward根据A推导模板参数类型...,得到左值引用参数;右值作用在通用引用参数,得到右值引用参数 尽管decltype在把右值参数推导为右值引用类型而不是非引用类型(std::forward中T要求),但是最终转发结果一样

1.7K50

Effective Modern C++翻译(6)-条款5:auto比显示类型声明要更好

使用auto让你在声明变量时省略掉类型,同时也防止了手动类型声明带来正确性和性能上困扰;虽然按照语言预先定义规则,一些auto类型推导结果,在程序员视角来看却是难以接受,在这种情况下,知道...,就像你声明函数指针时候,你必须标注出函数类型,当你声明std::function时候,你也必须通过模板参数标注出函数类型,例如你可以声明一个叫funcstd::function对象,它可以指向以下函数类型可调用对象...&, const std::unique_ptr&)> func; 因为lambda表达式产生可调用对象,闭也可以通过std::function对象表示,这意味着我们可以声明新版本...,并且需要空间也一样,而用std::function声明变量持有的闭std::function模板一个实例,对任何给定函数原型,所需要内存大小都是一样,如果分配大小不足,std::function...,所以在使用auto还是std::function声明一个闭较量中,auto获胜了(一个类似的参数可以通过auto或者std::function产生,持有std::bind调用结果,但是根据条款

866100

C++11新特性学习笔记

C++11括大量新特性:包括lambda表达式,类型推导关键字auto、 decltype,和模板大量改进。...(2, 1.0); // OK:args含有两个实参int和double 省略号“…”作用有两个: \1) 声明一个参数,这个参数中可以包含0到任意个模板参数 \2) 在模板定义右边,可以参数展开成一个一个独立参数...6.2 可变参数模板类 6.2.1 继承方式展开参数 可变参数模板展开一般需要定义2 ~ 3个类,包含类声明和特化模板类: template class BMW{};...C++11中,新增加了一个std::function模板,它是对C++中现有的可调用实体一种类型安全包裹。...9.2.3.3 lambda类型 lambda表达式类型在C++11中被称为“闭类型”,每一个lambda表达式则会产生一个临时对象(右值)。因此,严格地lambda函数并非函数指针。

2K20

C++11新特性学习笔记

C++11括大量新特性:包括lambda表达式,类型推导关键字auto、 decltype,和模板大量改进。...(2, 1.0); // OK:args含有两个实参int和double 省略号“…”作用有两个: \1) 声明一个参数,这个参数中可以包含0到任意个模板参数 \2) 在模板定义右边,可以参数展开成一个一个独立参数...6.2 可变参数模板类 6.2.1 继承方式展开参数 可变参数模板展开一般需要定义2 ~ 3个类,包含类声明和特化模板类: template class BMW{};...C++11中,新增加了一个std::function模板,它是对C++中现有的可调用实体一种类型安全包裹。...9.2.3.3 lambda类型 lambda表达式类型在C++11中被称为“闭类型”,每一个lambda表达式则会产生一个临时对象(右值)。因此,严格地lambda函数并非函数指针。

2.2K20

Effective Modern C++翻译(3)-条款2:明白auto类型推导

模板类型推导涉及了模板,函数和参数,但是auto类型推导却没有涉及其中任何一个。...//同上 这是由于auto类型推导一个特殊规则,当变量使用大括号初始化式(braced initializer)初始化时候,被推导类型是std::initializer_list,如果这个类型不能被推导出来...std::initializer_list模板类型,而模板类型推导面对大括号初始化式(braced initializer)时,代码将不会通过(这是由于完美转发perfect forwarding结果...lambda表达式可能需要在参数声明时使用auto,不管怎样,这些auto使用,采用模板类型推导规则,而不是auto类型推导规则,这意味着,大括号初始化式造成类型推导失败,所以一个带有...auto用于C++14lambda产生一个通用lambda(generic lambda))参数类型说明符时, std::vector v; auto resetV = [&v](const

682100

C++进阶:C++11(列表初始化、右值引用与移动构造移动赋值、可变参数模版...Args、lambda表达式、function包装器)

模板参数允许在模板参数列表中接受任意数量参数,并通过展开(expansion)来处理这些参数。...一个基础模版: // Args是一个模板参数,args是一个函数形参参数 // 声明一个参数Args...args,这个参数中可以包含0到任意个模板参数。...我们无法直接获取参数args中每个参数,只能通过展开参数方式来获取参数每个参数这是使用可变模版参数一个主要特点,也是最大难点,即如何展开可变模版参数。...返回值类型 -> return-type:用于指定Lambda函数返回值类型,可以省略,编译器根据返回语句进行推导(一般情况都不写)。...通过std::function模板参数,可以指定存储可调用对象类型。 存储可调用对象:std::function可以存储各种可调用对象,如函数指针、函数对象、Lambda表达式等。

5600

【C++】C++11 新特性

C语言有一些不同,下面是一个基本可变参数函数模板: // Args是一个模板参数,args是一个函数形参参数 // 声明一个参数Args...args,这个参数中可以包含0到任意个模板参数。...“参数”,它里面包含了0到N(N>=0)个模版参数参数参数个数 在可变参数函数模板中我们可以使用 sizeof…(args) 来求得参数参数个数: 2、取出参数每个参数 既然可以使用...11标准中并不允许以这种方式来取出参数参数,而是使用另外两种非常晦涩方式来完成,如下: 方法一:递归函数方式展开参数参数第一个参数赋值给 val,剩下 n-1 个参数以类似于递归子问题方式逐个取出...,然后这个对象深拷贝或者移动拷贝到容器中,而 std::emplace() 则通过使用可变参数模板、万能模板等技术,直接在容器中构造对象,避免了对象拷贝和移动; 对于不需要进行深拷贝自定义类型来说...,并且也不需要我们在 function 参数中显式声明;这样我们就可以通过绑定让我们普通成员函数和类静态成员函数以及 lambda 表达式、函数指针一样定义为统一类型了;如下: 需要说明

1.3K10

CC++开发基础——lambda表达式与std::bind闭

本章主要内容: 一,lambda表达式 1.基本概念 2.关于捕获子句 3.常见捕获方式 二,闭std::bind模板 1.什么是闭...所以下面这两个捕获子句产生编译错误: [&, &counter] [=, &counter, number] 方式四,捕获this指针 如果一个对象成员函数中有lambda表达式,那么这个lambda...: 3 6 9 12 二,闭std::bind模板 1.什么是闭( Closure)这个概念起源于函数式编程,是指外部变量与函数之间绑定,可以这样理解,捕获了外部变量lambda表达式是一种闭...std::bind可以预先指定函数所有参数,也可以函数部分参数预先指定好,剩下参数等真正调用时候再指定。 3.std::bind用法 假如有一个计算两个数字相加函数。...int add(int first, int second) { return first + second; } std::bind函数名作为其第一个参数,后面的参数用"_1,_2"这样占位符来预留

86730

Effective Modern C++翻译(5)-条款4:了解如何观察推导类型

他们可能想知道如果我用一个万能引用(见条款26)替代一个左值常量形参(例如在函数参数列表中用T&&替代const T&)模板类型推导结果会改变吗?...编译器诊断 知道编译器对某一类型推导结果一个有效方法是让它产生一个编译期错误,因为错误报告肯定会提到导致错误类型。...== "Type Displayer" 尝试实例化这个模板产生一个错误信息,因为没有模板定义,想要查看x和y类型只需要用它们类型实例化TD TD xType; // 引起错误信息包括了...和std::type_info::name来产生用户自定义格式字符串表达) 如果你经常需要使用这个方法,并且认为花费在调试,文档,维护上努力是值得,那么这是一个合理方法(If you’d use...typeid更好代码, 你需要注意到很多编译器都提供了语言扩展来产生一个函数签名字符串表达,包括从模板中实例化函数,模板模板参数类型。

69680

【Cocos2d-x游戏开发】细数Cocos2d-x开发中那些常用C++11知识

void foo(char *); 5.Lambda特性 lambda表达式是一个非常好新特性,当你需要在程序中添加一个新临时函数时,直接使用Lambda函数,让你感觉到原来写程序还可以这么爽~...,这种参数集合一般被称为闭,[ ]中可以填写下面的几种类型参数,将定义lambda函数作用域内变量传入函数体中。   ...[=,&a]除了a用引用方式传入,其他变量都以传值方式传入   下面让我们通过一个例子来了解一下,当在lambda中使用了“=”传入参数,且对引用参数或者外部参数进行赋值操作之后,产生意想不到结果...使用std::function可以存储Lambda函数,比如可以用function来存储func0,用function来存储func1,带有参数函数可以直接在()内输入参数类型...,静态函数和类公有成员函数,前两者和lambda用法一样,直接函数名赋值给function对象即可(无法识别重载函数),但类成员函数需要使用bind来绑定: ClassA *obj =

46630

C++17常用新特性

2 C++17新特性 2.1 折叠表达式 从C++17开始,可以使用二元操作符对形参参数进行计算,这一特性主要针对可变参数模板进行提升,可以分为左折叠和右折叠。支持二元操作符多达32个。...return 0; } 运行结果: sum1=6 sum2=16 2.2 类模板实参推导模板进行实例化时,不需要指定模板参数,编译器根据传入实参进行类型推导。...根据变量及变量模板初始化或者声明进行推导 std::pair p(2, 4.5); // 推导std::pair p(2, 4.5); std::tuple t(...作为非类型模板参数模板参数中使用auto作为关键字时,模板实例化传入非类型值,auto可以推导参数类型。...::cout<<"sum1="<<sum1<<<em>std</em>::endl; return 0; } 代码运行<em>结果</em>为:3; 需要注意<em>的</em>是C++17目前还不支持<em>参数</em>类型是浮点型<em>的</em><em>推导</em>。

2.1K20

C++11

再将临时对象拷贝到ret变量时候,会调用移动构造,临时对象资源转移到ret中,发生两次拷贝(这里某些先进版本编译器优化此过程,不会产生临时对象,直接str内资源转移到ret中,只有一次移动构造...完美换发 完美转发是指在函数模板中,完全依照模板参数类型,参数传递给函数模板中调用另外一个函数。...可变参数模板 C++11新特性可变参数模板能够让您创建可以接受可变参数函数模板和类模板。...下面是一个基本可变参数函数模板: // Args是一个模板参数,args是一个函数形参参数 // 声明一个参数Args...args,这个参数中可以包含0到任意个模板参数。...我们无法直接获取参数args中每个参数,只能通过展开参数方式来获取参数每个参数这是使用可变模版参数一个主要特点,也是最大难点,即如何展开可变模版参数

7910

Chapter 2: auto

声明并初始化 在模板函数中可以使用auto来完成变量自动类型推导 例如: template void dwim(It b, It e) { for(; b!...*p1 < *p2; }; 相比之下,使用function对象来保存上述结果,代码如下: std::function&, const...使用std::function声明变量对于任何函数都是固定大小空间,如果空间不足,就会在堆上申请内存来存储这个闭。...另外,由于限制内联,函数对象不得不产生一次间接函数调用。 结果是:std::function对象通常使用更多内存,执行速度也比auto要慢。...2.当auto推导错误类型时使用显式类型初始化方式 当表达式返回类型是代理类类型时,不能使用auto 例1: //提取出Widget对象特征,并以vector形式返回 //每一个

1.1K70

【笔记】C++2.0新特性

样例代码里面模板类型名后面的...称为模板参数(template parameters pack), 函数参数部分类型名后面的...称为函数模板类型(function template types...pack), 函数调用时候出现在参数...称为函数参数(function parameters pack) 可以用sizeof......; // 等价于 std::vector> foo; 模板别名能在特定情境下发挥作用, 核心就是它可以在编译阶段模板参数数量整合缩减....由于编译器无法在模板推导模板参数正确形式, 也就是模板参数默认值在编译阶段是无法展现....和Lambda中, 替代了旧版本中不好用typeof 返回值: 在模板编程中, 我们不仅希望能自动推导参数类型, 还希望按照得到类型来推导返回值, 如今可以借助尾置返回模板函数写为下面的形式.

87020

C++20新特性个人总结

2.2  修改const限定成员指针  2.3  允许lambda表达值按值捕获this  2.4  指定初始化  2.5  lambda表达式支持模板  2.6  从构造函数推导模板参数类型 ...  聚合初始化推导模板参数  2.28  隐式地返回本地变量转换为右值引用  2.29  允许default修饰运算符按值比较  2.30  非类型模板参数等效条件  3  宏  4  属性 ...#4 } 2.5  lambda表达式支持模板  从新版开始,lambda表达式支持模板编程,且支持自动推导。...  声明变量时进行初始化,如果能从构造函数中推导出变量类型,则该变量类型可以不用指定模板参数。 ...2.27  聚合初始化推导模板参数  通过聚合初始化中参数类型 来 推导出类模板参数类型  例子:  template struct S  {     T x;     T

1.9K50
领券