首页 > 编程语言 >C++ 模板实参推断和引用折叠

C++ 模板实参推断和引用折叠

时间:2024-11-08 17:29:53浏览次数:3  
标签:右值 左值 C++ 引用 && 类型 实参 模板

两个例外规则

假定 i是一个 int 对象,我们可能认为像 £3(i)这样的调用是不合法的。毕竟,i是一个左值,而通常我们不能将一个右值引用绑定到一个左值上。但是,C++语言在正常绑定规则之外定义了两个例外规则,允许这种绑定。这两个例外规则是move 这种标准库设施正确工作的基础。

第一个例外规则影响右值引用参数的推断如何进行。当我们将一个左值(如i)传递给函数的右值引用参数,且此右值引用指向模板类型参数(如T&&)时,编译器推断模板类型参数为实参的左值引用类型。因此,当我们调用f3(i)时,编译器推断T的类型为int&,而非int。

T被推断为int&看起来好像意味着f3的函数参数应该是一个类型int&的右值引用。通常,我们不能(直接)定义一个引用的引用(参见2.3.1节,第46页)。但是,通过类型别名(参见2.5.1节,第60页)或通过模板类型参数间接定义是可以的。

在这种情况下,我们可以使用第二个例外绑定规则:如果我们间接创建一个引用的引用,则这些引用形成了“折叠”。在所有情况下(除了一个例外),引用会折叠成一个普通的左值引用类型。在新标准中,折叠规则扩展到右值引用。只在一种特殊情况下引用会折叠成右值引用:右值引用的右值引用。即,对于一个给定类型 X:

  • X& &X& &&X&& &都折叠成类型X&
  • 类型X&& &&折叠成X&&

Note:
引用折叠只能应用于间接创建的引用的引用,如类型别名或模板参数。

两个重要结果

  • 如果一个函数参数是一个指向模板类型参数的右值引用(如,T&&),则它可以被绑定到一个左值;且
  • 如果实参是一个左值,则推断出的模板实参类型将是一个左值引用,且函数参数将被实例化为一个(普通)左值引用参数(T&)

这两个规则暗示,我们可以将任意类型的实参传递给T&&类型的函数参数。

Note:
如果一个函数参数是指向模板参数类型的右值引用(如,T&&),则可以传递给它任意类型的实参。如果将一个左值传递给这样的参数,则函数参数被实例化为一个普通的左值引用(T&)。

std::move

从一个左值 static_cast 到一个右值引用是允许的

通常情况下,static_cast 只能用于其他合法的类型转换(参见 4.11.3 节,第 145页)。但是,这里又有一条针对右值引用特许规则:虽然不能 隐式地将一个左值转换为右值引用,但我们可以用static_cast显式地将一个左值转换为一个右值引用

std::forward 转发

类似move,forward定义在头文件utility中。与move不同,forward必须通过显式模板实参来调用(参见16.2.2节,第603页)。forward返回该显式实参类型的右值引用。即,forward<T>的返回类型是T&&




源自:《C++ Primer》 P608

标签:右值,左值,C++,引用,&&,类型,实参,模板
From: https://www.cnblogs.com/huvjie/p/18535530

相关文章

  • 07C++选择结构(1)
    一、基础知识1、关系运算符因为我们要对条件进行判断,必然会用到关系运算符:名称大于大于等于小于小于等于等于不等于符号>>=<<===!=关系表达式的值是一个逻辑值,即“真”(True)或“假”(False)。如果条件成立,其值为“真”;如果条件不成立,其值为“假”。2、逻......
  • 【C++进阶】智能指针的使用及原理(1)
    1.智能指针的使用场景分析下面程序中我们可以看到,new了以后,我们也delete了,但是因为抛异常导,后面的delete没有得到执行,所以就内存泄漏了,所以我们需要new以后捕获异常,捕获到异常后delete内存,再把异常抛出,但是因为new本身也可能抛异常,连续的两个new和下面的Divide都可能会抛异......
  • c++执行shell操作
     message("----->>>>>shelldemo/CMakeLists.txt")#收集当前目录下所有的.cpp文件aux_source_directory(.DIR_SRCS)#添加可执行文件add_executable(shelldemo${DIR_SRCS})#链接需要的库target_link_libraries(shelldemo${LIB_LIB})/shelldemo/CMakeList......
  • 【C++篇】无序中的法则:探索 STL之unordered_map 与 unordered_set容器的哈希美学
    文章目录C++`unordered_map`和`unordered_set`容器详解前言第一章:`unordered_map`和`unordered_set`的概念1.1`unordered_map`和`unordered_set`的定义1.2与`map`、`set`的区别第二章:`unordered_map`和`unordered_set`的构造方法2.1`unordered_map`......
  • Chromium 进程降权和提权模拟示例c++
     一、背景知识概念参考微软链接:强制完整性控制-Win32应用程序|Microsoft学习授权)(模拟级别-Win32apps|MicrosoftLearnDuplicateTokenEx函数(securitybaseapi.h)-Win32apps|MicrosoftLearn本文主要演示 low,medium,high,andsystem四种权限创建......
  • C++之OpenCV入门到提高004:Mat 对象的使用
    一、介绍今天是这个系列《C++之Opencv入门到提高》得第四篇文章。这篇文章很简单,介绍如何使用Mat对象来实例化图像实例,了解它的构造函数和常用的方法,这是基础,为以后的学习做好铺垫。虽然操作很简单,但是背后有很多东西需要我们深究,才能做到知其然知其所以然。OpenCV具......
  • C++ 模板参数的两种类型转换
    与非模板函数一样,我们在一次调用中传递给函数模板的实参被用来初始化函数的形参。如果一个函数形参的类型使用了模板类型参数,那么它采用特殊的初始化规则。只有很有限的几种类型转换会自动地应用于这些实参。编译器通常不是对实参进行类型转换,而是生成一个新的模板实例。与往常一......
  • C++ 模板显式实例化
    //template.hpptemplate<typenameT>classDylan{public:Dylan(Tt);Tm_data;};//template.cpp#include"template.hpp"template<typenameT>Dylan<T>::Dylan(Tt){m_data=t;}templateclassDylan<int&g......
  • C++关于DLL导出模板类和模板函数
    这两天写了个Dll,要导出普通类中的模板函数,稍微查了一下,没查到具体资料。自己根据C++模板的编译原理,推断出应该要源码放在头文件中直接导出,查了下接触的OpenSource项目,确实如此。这里记录一下,方便下次查阅。1、宏定义说明:#ifdefDLL_PROJECT#defineTEMPLATE_IM_EXPORT__decl......
  • c++多态学习:多态含义与使用
    目录 多态的概念多态的定义多态的实现注意事项 多态的概念多态是面向对象编程中的一个重要概念,它指的是同一个行为具有多个不同表现形式或形态的能力。在C++中,多态主要通过虚函数来实现,允许将子类类型的指针赋值给父类类型的指针,并在运行时根据实际对象类型调用相......