通用引用的标准/官方名称是什么? [英] What's the standard/official name for universal references?

查看:108
本文介绍了通用引用的标准/官方名称是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如果一个变量或参数声明为 T&&& 类型 T

通用引用是由Scott引入的,迈尔斯在他原来的演讲中通用参考在C ++ 11。但是,我不知道通用引用的官方/标准术语是什么。

解决方案

概述



已知从C ++ 11起,类型 T&& 的参数被称为参考 [ ISO / IEC 14882:2011§8.3.2/ p2参考文献[dcl.ref] ]。也就是说,除非 T 是模板参数类型或 auto typedef








$ b p> template< typename T>
void foo(T& p){// - > T是模板参数
...
}

auto&& p = expression;


虽然技术上 T&& / code>在上面的例子中仍然是一个右值引用,它的行为显着不同于一个正常的。



当然,你会问为什么这个特殊情况没有特殊语法。答案是C ++委员会为这个特殊结构有意重载&&& 语法。然而,他们错过了命名这种特殊情况。



如果这个特定结构没有明确的名称, Scott Meyers 创造了广为人知的术语/名称 通用参考



然而委员会认为这个名称由于多种原因而不合适。因此, N4164 Herb Sutter Bjarne Stroustrup Gabriel Dos Reis 建议将名称更改为转发参考



名称转发参考在委员会成员之间的非正式讨论中获得最多的支持,包括前面提到的提案的作者。有趣的是,斯科特·迈尔斯自己在他原来的通用参考谈话中引入了这个词。然而,后来他决定采用名称​​通用引用。对于这个决定起到了这样的作用,当时他并不认为转发引用包括 auto&& 情况。



为什么不提供通用参考? >通用引用虽然是一个具有明显意义的合理名称,但在几个方面却是错误的。



>必须表示以下内容:




  • 可以随处使用的引用;或

  • 可用于一切的参考;或

  • 类似的东西。



显然这不是这种情况,这个结构。此外,这个名称将鼓励许多人认为具有这样的名称的东西意在被普遍地使用。委员会认为这是一件坏事。



此外,通用引用甚至不是真正的
引用本身,而是一组在特定方式中以特定方式使用引用的规则



为什么 auto&&&< / b> code>也被视为转发案例



auto&&& 它遵循参考折叠规则。例如:




  • 形式为 [](auto&& x){...}的通用lambdas $

  • 代表 & i:v){...}

  • 最后,一般来说, auto&& $ c>局部变量用于转发。



转发引用的标准字样



草稿中提及了转发参考一词标准N4527 在以下位置:



§14.8.2.1/从函数调用中取消模板参数[temp.deduct.call] em> (Emphasis Mine)


如果P是cv限定类型,类型
的限定符被忽略类型扣除。如果P是引用类型,则由P引用的类型
用于类型推导。 转发
引用
是cv未限定模板
参数的值。如果P是转发引用并且参数是
左值,则对于
类型扣除使用类型对A的左值引用来代替A. [示例:

 模板< class T& int f(T& heisenreference); 
template< class T> int g(const T&&;);
int i
int n1 = f(i); // call f< int&>(int&)
int n2 = f(0); // call f< int>(int&&)
int n3 = g(i); // error:will call g< int>(const int&&),其中
//将绑定一个右值引用

- end example]


§14.8.2.5/ p10类似地,如果P具有包含(T)的形式的参数,则来自类型[temp.deduct.type]的参数:



,则将P的相应参数类型列表的每个参数类型
Pi与A的相应
参数类型列表的
对应参数类型Ai进行比较。如果P和A是
起源于取得函数
模板(14.8.2.2)的地址或从
函数声明(14.8.2.6)中推导出模板参数时的推导的函数类型,Pi和Ai如果是转发引用(14.8.2.1),Ai被分别调整
的参数,并且Ai是一个左值
引用,在这种情况下,Pi的类型被改变为模板
参数类型(即,T&简单地变为T)。 [注:作为
结果,当Pi T&& 且Ai为 X& 调整的Pi将是T,
,使得T被推导为 X& 。 - end note] [示例:

 模板< class T& void f(T&&;); 
模板<> void f(int&){} //#1
template<> void f(int&&){} //#2
void g(int i){
f(i); //调用f< int&>(int&),即#1
f(0); // call f< int>(int&&),ie#2
}

- end example]如果对应于Pi的参数声明是一个
函数参数包,那么它的declaratorid的类型与A的parameter-type-list中的每个剩余参数类型比较

每次比较都会推断出模板参数包在模块参数包中扩展的函数参数包的
中后续位置的模板参数。
在部分顺序(14.8.2.4)中,如果Ai最初是一个函数
参数包:



I know that if a variable or parameter is declared to have type T&& for some deduced type T, that variable or parameter is widely called a universal reference.

The term universal reference was introduced by Scott Meyers in his original talk "Universal References in C++11". However, I wonder what's the official/standard term for universal references.

解决方案

Overview

It is known that since C++11, a parameter of type T&& is called an rvalue reference [ISO/IEC 14882:2011 §8.3.2/p2 References [dcl.ref] ]. That is, unless T is a template parameter type or auto or a typedef for some lvalue reference type.

examples:

template<typename T>
void foo(T&& p) { // -> T is a template parameter
  ...
}

auto &&p = expression;

Although technically T&& in the examples above is still an rvalue reference, its behaviour differs significantly from a regular one.

Naturally, you would ask "why this special case doesn't have a special syntax". The answer is that the && syntax was intentionally overloaded for this special construct by the C++ committee. However, they missed to name this special case.

In the absence of a distinct name for this particular construct, Scott Meyers coined the widely known term/name universal references.

The committee however, decided that this name is not proper for a number of reasons. As such, the proposal N4164 made by Herb Sutter, Bjarne Stroustrup and Gabriel Dos Reis proposed to change the name to Forwarding References.

The name Forwarding References had the most support in informal discussions among committee members, including the authors of the proposal mentioned earlier. Interestingly enough, it was Scott Meyers himself that introduced that term in his original "Universal References" talk. However, later he decided to go along with the name universal references. For this decision played role the fact that at the time he didn't think that the term forwarding references included also the auto&& case.

Why not universal references?

According to the proposal the term Universal references although is a reasonable name with an obvious meaning, it happens to be wrong in several aspects.

A universal reference must mean the following:

  • A reference that can be used everywhere; or
  • A reference that can be used for everything; or
  • something similar.

Obviously this is not the case nor is the appropriate use of this construct. Furthermore, this name would encourage many people to consider that something having such a name is meant to be used "universally". Something that the committee considered it a bad thing.

Moreover, "universal references" aren’t even really references per se, but rather a set of rules for using references in a particular way in a particular context with some language support for that use, and that use is forwarding.

Why auto&& is Also Considered a Forwarding case

auto&& is also considered a forward case since it follows the reference collapsing rules. For example in:

  • Generic lambdas of the form, [](auto&& x){ … }
  • for-ranged loop of the form, for(auto &&i : v) { ... }
  • Finally, in general is true that auto&& local variables are for forwarding.

Standard Wordings for Forwarding References

The term forwarding references is mentioned in the draft standard N4527 in the following places:

§14.8.2.1/ Deducing template arguments from a function call [temp.deduct.call] (Emphasis Mine):

If P is a cv-qualified type, the top level cv-qualifiers of P’s type are ignored for type deduction. If P is a reference type, the type referred to by P is used for type deduction. A forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type "lvalue reference to A" is used in place of A for type deduction. [ Example:

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

— end example ]

§14.8.2.5/p10 Deducing template arguments from a type [temp.deduct.type]:

Similarly, if P has a form that contains (T), then each parameter type Pi of the respective parameter-typelist of P is compared with the corresponding parameter type Ai of the corresponding parameter-type-list of A. If P and A are function types that originated from deduction when taking the address of a function template (14.8.2.2) or when deducing template arguments from a function declaration (14.8.2.6) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is a forwarding reference (14.8.2.1) and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T). [ Note: As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be deduced as X&. — end note ] [Example:

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&), i.e., #1
f(0); // calls f<int>(int&&), i.e., #2
}

— end example ] If the parameter-declaration corresponding to Pi is a function parameter pack, then the type of its declaratorid is compared with each remaining parameter type in the parameter-type-list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. During partial ordering (14.8.2.4), if Ai was originally a function parameter pack:

这篇关于通用引用的标准/官方名称是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆