![](/img/trans.png)
[英]What's the official name of '.' and '->' operators in C and C++?
[英]What's the standard/official name for universal references?
我知道如果一个变量或参数被声明为某个推导类型T
类型为T&&
,那么该变量或参数被广泛称为通用引用 。
Scott Meyers在其最初的演讲“C ++ 11中的通用参考”中引入了通用参考这一术语。 但是,我想知道普遍参考的官方/标准术语是什么。
众所周知,从C ++ 11开始, T&&
类型的参数称为右值参考 [ ISO / IEC 14882:2011§8.3.2/ p2 References [dcl.ref] ]。 也就是说,除非T
是模板参数类型或auto
或某个左值引用类型的typedef
。
例子:
template<typename T> void foo(T&& p) { // -> T is a template parameter ... } auto &&p = expression;
虽然上面的例子中技术上T&&
仍然是右值参考,但它的行为与常规参数有很大不同。
当然,你会问“为什么这个特殊情况没有特殊的语法”。 答案是C ++委员会为这个特殊的构造故意重载了&&
语法。 然而,他们错过了这个特例的名称。
由于这个特定结构没有明确的名称, Scott Meyers创造了广为人知的术语/名称通用参考文献 。
但委员会认为,由于多种原因,这个名称并不合适。 因此, Herb Sutter , Bjarne Stroustrup和Gabriel Dos Reis提出的N4164提议将名称改为Forwarding References 。
转发参考文献的名称在委员会成员之间的非正式讨论中得到了最多的支持,包括前面提到的提案的作者。 有趣的是,Scott Meyers本人在他最初的“Universal References”演讲中引入了这个词。 然而,后来他决定继续使用名称通用引用 。 因为这个决定扮演了一个角色,当时他并不认为转发引用一词也包括auto&&
案例。
根据该提议,术语“ 通用引用”虽然是一个具有明显含义的合理名称,但它在几个方面恰好是错误的。
通用引用必须表示以下内容:
显然情况并非如此,也不适合使用这种结构。 此外,这个名称会鼓励许多人认为具有这种名称的东西意味着“普遍”使用。 委员会认为这是件坏事。
此外,“通用引用”本身甚至不是真正的引用,而是一组规则,用于在特定上下文中以特定方式使用引用,并为该用途提供某些语言支持,并且该用法是转发 。
auto&&
也被认为是一个转发案例 auto&&
也被视为前瞻性案例,因为它遵循参考折叠规则 。 例如:
[](auto&& x){ … }
for
-ranged循环的形式, for(auto &&i : v) { ... }
auto&&
局部变量用于转发。 术语转发参考在以下地方的标准草案N4527中提到:
§14.8.2.1/从函数调用中减去模板参数[temp.deduct.call] (Emphasis Mine) :
如果P是cv限定类型,则类型推导将忽略P类型的顶级cv限定符。 如果P是引用类型,则P引用的类型用于类型推导。 转发引用是对cv-unqualified模板参数的rvalue引用。 如果P是转发引用且参数是左值,则使用类型“对A的左值引用”代替A来进行类型推导。 [例如:
template <class T> int f(T&& heisenreference); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which // would bind an rvalue reference to an lvalue
- 结束例子]
§14.8.2.5/ p10从类型[temp.deduct.type]中推导出模板参数:
类似地,如果P具有包含(T)的形式,则将P的各个参数类型列表的每个参数类型Pi与相应的参数类型列表A的相应参数类型Ai进行比较。如果P和A是当获取函数模板的地址(14.8.2.2)或从函数声明(14.8.2.6)中推导出模板参数时,源自演绎的函数类型以及Pi和Ai是顶级参数类型列表的参数如果它是转发参考 (14.8.2.1)并且Ai是左值参考,则P和A分别被调整,在这种情况下,Pi的类型被改变为模板参数类型(即,T &&被简单地改变为T)。 [注意:结果,当Pi为
T&&
且Ai为X&
,调整后的Pi将为T,导致T被推导为X&
。 - 尾注] [示例:template <class T> void f(T&&); template <> void f(int&) { } // #1 template <> void f(int&&) { } // #2 void g(int i) { f(i); // calls f<int&>(int&), ie, #1 f(0); // calls f<int>(int&&), ie, #2 }
- 结束示例]如果对应于Pi的参数声明是函数参数包,则将其declaratorid的类型与A的参数类型列表中的每个剩余参数类型进行比较。每个比较推导出后续位置的模板参数。由函数参数包扩展的模板参数包。 在部分排序(14.8.2.4)期间,如果Ai最初是一个函数参数包:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.