繁体   English   中英

为什么将表达式转换为rvalue对函数的引用是lvalue?

[英]Why cast expression to rvalue reference to function is lvalue?

在这里, cppreference-lvalue ,我发现了

将表达式转换为对函数的rvalue引用是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;
}

这样的事实。

为什么将表达式转换为rvalue对函数的引用是lvalue? 是因为函数类型不需要移动语义或其他东西吗? 或者我理解这个词错了。

将表达式转换为对函数的rvalue引用是lvalue

它遵循C ++ 11 3.10 / 1中的值类别的定义(强调我的):

  • 左值 (...)表示函数或对象。 ...

  • xvalue (“eXpiring”值)也指对象,......

  • rvalue (...)是xvalue,临时对象(12.2)或其子对象,或者与对象无关的值。

  • prvalue (“纯”rvalue)是一个不是xvalue的rvalue。 ...

请注意,只有左值类别可以是一个函数,所有其他类别只是值或对象。

它也在5.2.9 / 1中得到回应:

表达式static_cast<T>(v)的结果是将表达式v转换为类型T 如果T左值引用类型或函数类型的右值引用,则结果为左值 ; 如果T是对象类型的右值引用,则结果为xvalue; 否则,结果是prvalue。 ...

至于它的原因,我当然只能猜测(不是标准化委员会的一部分)。 但我的猜测是,拥有函数类型的rvalues是没有意义的 - 函数永远不会是临时函数,它永远不会处于或接近其生命周期的末尾。

非常感谢TC提供的信息( N3055 ,他的评论链接),以便快速概述答案,并引用与此问题相关的一些段落。 这个答案告诉我们原因

rvalue引用(如传统的左值引用)可以绑定到函数。 然而,将rvalue参考返回值作为rvalue处理,将函数rvalue的新概念引入到语言中。 之前没有这样的想法 - 在右值上下文中使用的函数左值变为指向函数的rvalue,而不是函数rvalue - 因此当前的标准草案没有描述如何处理这样的右值。 特别是,函数调用和函数指针的转换是根据函数左 值来 指定的, 因此对函数的右值引用的最合理使用在当前的措辞中是未定义的。

这些问题的一种可能的解决方案是保持当前的方法将右值参考返回值视为右值,但是为rvalues的规范添加各种警告,以便来自右值参考的那些具有特殊特征。 这可以称为“有趣的左值”方法。 然而,进一步检查标准草案的当前措辞表明,上面列出的问题可能只是冰山一角:许多规范应适用于右值引用所引用的对象,例如对象生存期,别名规则等等,用左值表示, 因此右值警告列表可能会很长

这表明了一种替代方法:rvalue引用返回值实际上应该被视为左值,除了一些例外,允许在预期的情况下将它们视为rvalues,即在引用绑定,重载决策和模板参数中扣除。 这个被称为“有趣的左值”方法的想法体现在本文的早期版本中。经过匹兹堡核心工作组(2010年3月8日至13日)的广泛讨论 ,......

另外,As 5.2.2函数调用[expr.call]说:

对于非成员函数或静态成员函数的调用,后缀表达式应该是引用函数的左值 (在这种情况下,后缀表达式上的函数到指针标准转换(4.3)被抑制),或者它应具有指向函数类型的指针。

现在static_cast<void(&&)(int)>(test)是一个左值。

所以static_cast<void(&&)(int)>(test)(555); 没关系

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM