首页 > 编程语言 >std::move 和 std::forward源码解析

std::move 和 std::forward源码解析

时间:2024-05-03 19:56:35浏览次数:25  
标签:std Widget reference 源码 && Arg forward

std::move和std::forward仅仅是执行转换(cast)的函数(事实上是函数模板)。std::move无条件的将它的实参转换为右值,而std::forward只在特定情况满足时下进行转换。

std::move

template <class _Ty>
constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept {
    return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}

std::move函数模板返回一个remove_reference_t<_Ty>&&,确保返回的一定是右值。

std::forward

template <class _Ty>
constexpr _Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept {
    return static_cast<_Ty&&>(_Arg);
}

template <class _Ty>
constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept {
    static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
    return static_cast<_Ty&&>(_Arg);
}

std::forward函数模板使用时显示指明模板参数类型,根据条件进行类型转换。

std::forward完美转发

void process(Widget& lval) {
    std::cout << "左值process" << std::endl;
}
void process(Widget&& lval) {
    std::cout << "右值process" << std::endl;
}
template<typename T>
void logAndProcess(T&& param) {
    process(temp::forward<T>(param));
}
Widget w;
logAndProcess(w);
logAndProcess(Widget());

logAndProcess模板函数,使用通用引用的形式进行模板类型推导,如果传入左值,TParam都会被推导为左值引用;如果传入右值,就正常推导,即T推导为Widget,param推导为Widget&&。

所以logAndProcess(w)函数体中,T为Widget&,param为Widget&,forward(param)会调用forward(remove_reference_t<_Ty>& _Arg)版本的重载函数,返回static_cast<_Ty&&>(_Arg),根据引用折叠的规则,注意这里的_Ty为Widget&,Widget& && 就是Widget&,返回左值引用。

logAndProcess(Widget())函数体中,T为Widget,param为Widget&&,forward(param)会调用forward(remove_reference_t<_Ty>&& _Arg)版本的重载函数,返回static_cast<_Ty&&>(_Arg),_Ty为Widget,所以返回Widget&&,即右值引用。

std::forward(w) 和 std:forward<Widget&>(w)

std::forward(w)返回右值,std:forward<Widget&>(w)返回左值,他们两个都会调用forward(remove_reference_t<_Ty>& Arg)版本的重载函数,因为_Ty类型的不同和引用折叠,一个返回右值,一个返回左值。

标签:std,Widget,reference,源码,&&,Arg,forward
From: https://www.cnblogs.com/sgsg-blogs/p/18171538

相关文章

  • Flink源码学习(6)StreamTask的初始化和执行
    Stream初始化taskExecutor执行一个Task当taskExecutor接受提交Task执行的请求,会调用:CompletableFuture<Acknowledge>submitTask(TaskDeploymentDescriptortdd,JobMasterIdjobMasterId,@RpcTimeoutTimetimeout);提交Task到TM提交Job过来的JobManager和......
  • 26-Spring源码分析(一)
    1.Spring架构设计Spring框架是一个分层架构,他包含一系列的功能要素,并被分为大约20个模块。1.1设计理念Spring是面向Bean的编程(BOP:BeanOrientedProgramming),Bean在Spring中才是真正的主角。Bean在Spring中作用就像Object对OOP的意义一样,没有对象的概念就像......
  • Spring6 当中的 Bean 循环依赖的详细处理方案+源码解析
    1.Spring6当中的Bean循环依赖的详细处理方案+源码解析@目录1.Spring6当中的Bean循环依赖的详细处理方案+源码解析每博一文案1.1Bean的循环依赖1.2singletion下的set注入下的Bean的循环依赖1.3prototype下的set注入下的Bean的循环依赖1.4singleton下的构造注......
  • 深入浅出Spring源码,终于把学Spring源码的技巧吃透了!
    前言本人从事Java架构十余年,也曾经在几家一线大厂任职多年,一直认为最难啃的当属Spring源码,为此我自己录制了一套Spring由浅入深的源码教程,根据自己多年来对于Spring源码整理的课纲一步步带你深入学习Spring源码,教程课件都打包好提供给你mian费学习!由于官方限制,对Spring源码感兴......
  • public void add(int index, E element)的方法源码分析
    publicclassArrayList<E>extendsAbstractList<E>implementsList<E>,RandomAccess,Cloneable,java.io.Serializable{publicvoidadd(intindex,Eelement){rangeCheckForAdd(index);//校验数组是否越界......
  • How to Jump Forward or Backward in VLC Media Player for 1 Second in Windows 10?
    https://www.youtube.com/watch?v=4LkEecm4UX8&ab_channel=TechMeSpot HowtoJumpForwardorBackwardinVLCMediaPlayerfor1SecondinWindows10?Step1:OpentheVideoinVLCMediaPlayer,andthenpausethevideo.Step2:Clickon'Tools'......
  • 稳扎稳打 部署丝滑 开源即时通讯(IM)项目OpenIM源码部署流程(linux windows mac)
    背景OpenIM包含多个关键组件,每个都是系统功能必不可少的一部分。具体来说,MongoDB用于持久化存储;Redis用作缓存;Kafka用于消息队列;Zookeeper用于服务发现;Minio用于对象存储。这些组件的众多可能会增加部署的复杂性。此外,系统包含多个微服务模块,这要求有效管理进程的启动、停止......
  • JDK源码分析-TreeSet
    概述TreeSet是Java集合框架中用于存储唯一元素的树形数据结构,它实现了NavigableSet接口,这意味着TreeSet中的元素不仅是有序的,还支持一系列的导航方法。TreeSet的内部实现主要依赖于TreeMap,通过TreeMap的键来维护元素的排序。 类图从以上类图可以看到,TreeSet实现了三个接口,......
  • Linux内核源码-存储驱动之 QSPI Flash
    传输方式DIO/QIO/DOUT/QPIQPI模式(QuadPeripheralInterface),所有阶段都通过4线传输。与之相对的是SPI。SPI模式:纯种SPI(MISO/MOSI两个数据线)DOUT全称DualI/O,命令字和地址字均为单线,仅在数据阶段为双线。QOUT全称QuadI/O,命令字和地址字均为单线,仅在数据阶段为双线......
  • delphi 2006中,使用stdcall调用约定时,压缩结构参数的bug分析
    问题今天遇到一个很奇怪的问题,有一个dephi2006写的dll,使用了stdcall的调用约定,参数传递了结构体,在函数中收到的结构体值和传入的不一致,最后一个boolean类型,应为False,收到的是True,如下图:代码//结构体定义RStruct=packedrecordi1:Integer;i2:Integer;i3:I......