所在的位置: C++ >> C++发展 >> c编程之路3Lamda捕获Mo

c编程之路3Lamda捕获Mo

前一篇文章c++编程之路(2)-Lamda的参数捕获方式中分享了如何Lamda如何通过传值和引用的方式捕获外部参数,但某些场景下,你需要把Move-only的对象放到Lamda闭包中,该怎么做呢?答案是C++没有提供这种功能,在C++14中才提供了这种能力,专业的术语叫InitCapture。

InitCapture

通过InitCapture用户可以指定Lamda表达式捕获的变量的名称和初始化表达式。如下所示,加粗的部分为InitCapture,等号左侧pw是Lamda闭包内使用的变量名称,等号右侧std::move(pw)是初始化表达式。可以看出C++14的InitCapture是对C++11Lamda表达式捕获能力的扩展,使其支持在捕获过程中用表达式赋值。

classWidget{public:...boolisValidated()const;boolisProcessed()const;boolisArchived()const;private:...};autopw=std::make_uniqueWidget();autofunc=[pw=std::move(pw)]{//initcapturereturnpw-isValidated()pw-isArchived();};

如何解决C++11中不支持InitCapture呢

Lamda表达式完成的功能只是声明一个类,然后声明它的一个匿名对象,所以我们可以手工写一个类,并实例化该类,来绕过Lamda表达式的限制。在C++11中Move-only的对象捕获功能可以如下实现:

classIsValAndArch{public:usingDataType=std::unique_ptrWidget;explicitIsValAndArch(DataTypeptr):pw(std::move(ptr)){}booloperator()()const{returnpw-isValidated()pw-isArchived();}private:DataTypepw;};autofunc=IsValAndArch(std::make_uniqueWidget());

另外一个在C++中实现Move-only对象捕获的方法是使用std::bind。std::bind的第一个参数是绑定的可调用执行的对象,第二个参数是传递给可调用对象的参数,std::bind生成的对象持有传递给绑定的Callable对象的所有参数,当bind对象被调用时,它所持有的参数都会传递给Callable对象。

std::vectordoubledata;autofunc=std::bind([](conststd::vectordoubledata){/*usesofdata*/},std::move(data));

最后再对比下采用std::bind方案与C++14方案的对比:

autofunc=[pw=std::make_uniqueWidget()]{returnpw-isValidated()pw-isArchived();};autofunc=std::bind([](conststd::unique_ptrWidgetpw){returnpw-isValidated()pw-isArchived();},std::make_uniqueWidget());

需要记住的:

C++14中用InitCapture捕获Move-only对象。

2.C++11中采用手工实现或者std::bind模拟捕获Move-only对象。




转载请注明:http://www.aierlanlan.com/tzrz/5214.html