为什么将表达式强制转换为对函数的右值引用是左值
Why cast expression to rvalue reference to function is lvalue?
在这里,cppreference lvalue,我发现
将表达式强制转换为右值,对函数的引用为左值。
我很好奇,所以我进行了以下实验:
#include <iostream>
using namespace std;
typedef void (&&funr) (int);
typedef void (&funl) (int);
void test(int num){
cout<<num<<endl;//output:20
}
void foo(funr fun){
fun(10);
}
void foo(funl fun){
fun(20);//call this
}
template <typename T> void foo(T&& fun){
cout<<is_same<T,void(&)(int)>::value<<endl;//true, it is lvalue.
cout<<is_same<T,void(int)>::value<<endl;//false, it isn't rvalue.
}
int main()
{
foo(static_cast<void(&&)(int)>(test));
return 0;
}
事实上是这样。
为什么将表达式强制转换为对函数的右值引用是左值?是因为函数类型不需要移动语义还是其他什么?或者我把这个词理解错了。
将表达式强制转换为函数的右值引用为左值
它源于C++11 3.10/1(emphasis mine)中值类别的定义:
左值(…)指定函数或对象。。。
xvalue("eXpiring"值)也指对象。。。
右值(…)是一个xvalue、一个临时对象(12.2)或其子对象,或者是一个与对象无关的值。
prvalue("纯"右值)是一个不是xvalue的右值。。。
请注意,只有左值类别可以是函数,其他所有类别都只能是值或对象。
它也在5.2.9/1:中得到了回应
表达式
static_cast<T>(v)
的结果是将表达式v
转换为类型T
的结果如果T
是左值引用类型或函数类型的右值引用,则结果为左值;如果T
是右值引用对象类型,结果是一个xvalue;否则,结果为prvalue。。。
至于原因,我当然只能猜测(不是标准化委员会的成员)。但我的猜测是,拥有函数类型的右值是没有意义的;函数永远不可能是临时的,它永远不可能处于或接近其生命周期的尽头。
非常感谢T.C.提供的信息(N3055,其评论处的链接),以便快速概述答案,我引用了与此问题相关的一些段落这个答案告诉我们为什么
右值引用(像传统的左值引用)可以绑定到功能将右值参考返回值视为右值,然而,在语言以前没有这样的想法——使用了一个函数lvalue在右值上下文中,它变为指向函数右值的指针,而不是函数值–因此当前的标准草案没有描述如何这样的右耳值将被处理特别是函数调用和函数指针的转换是根据函数指定的左值,所以对函数的右值引用的最合理的用法是当前措辞中未定义
一个可能的解决方案问题是要保持目前治疗右值引用返回值作为右值,但要添加各种注意事项对右耳值的规范,使那些来自右耳值参考文献将具有特殊的特征。这可以称为"滑稽的右耳值"方法。然而,对标准草案目前的措辞表明上面列出的可能只是冰山一角:应应用于右值所指向的对象的规范引用引用,如对象生存期、别名规则等,是用左值表示,因此右值警告列表可以得到相当长。
这提出了另一种方法:重新值引用返回值实际上应该被视为lvalues,只有少数例外允许它们被视为右价预期,即参考绑定、过载解决,以及模板参数推导。这个想法被称为"有趣的左值"方法,体现在本文的早期版本中。在匹兹堡(2010年3月8日至13日)会议上核心工作组进行了广泛讨论之后,……
此外,正如5.2.2函数调用[expr.call]所说:
对于对非成员函数或静态成员函数的调用,后缀表达式应为引用函数(在这种情况下,函数到指针的标准转换(4.3)在后缀表达式上被抑制),或者它应该具有指向函数类型的指针。
现在static_cast<void(&&)(int)>(test)
是一个左值。
所以static_cast<void(&&)(int)>(test)(555);
是可以的。
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 无法将右值引用函数与 GCC 匹配
- C ++引用函数参数似乎包含原始对象的副本,而不是充当"real reference"
- 通过引用函数传递指针参数是什么意思?
- 常量引用函数参数的地址何时唯一?
- 我想了解为什么在这个例子中使用引用函数?或者引用在c++函数中的重要性
- C++ 通过引用函数传递数组,但内容保持不变
- 用数组或指针引用函数?
- 引用函数如何"int &foo();"工作?
- 常量引用函数参数:是否可以禁止临时对象?
- 计算在代码中引用函数的次数
- <initializer_list> 引用函数
- 字符串引用(函数)的差异
- 在类中引用函数时的"No Matching Function for Call"
- 无法通过引用函数"calcValues"中"firstNum"和"secondNum"变量来更改值
- 尝试引用已删除的函数(不引用函数)
- 引用函数指针
- 引用函数按值和自动返回
- 为什么我们可以取消引用函数指针
- 通过引用函数传递值的目的是什么