简体   繁体   English

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

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

At here, cppreference-lvalue ,I found that 在这里, cppreference-lvalue ,我发现了

Cast expression to rvalue reference to function is lvalue. 将表达式转换为对函数的rvalue引用是lvalue。

I was curious, so I carried out the following experiment: 我很好奇,所以我进行了以下实验:

#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;
}

the fact that so. 这样的事实。

Why cast expression to rvalue reference to function is lvalue? 为什么将表达式转换为rvalue对函数的引用是lvalue? Is it because a function type is no need to move semantics or something else? 是因为函数类型不需要移动语义或其他东西吗? Or I understand this word wrong. 或者我理解这个词错了。

Cast expression to rvalue reference to function is lvalue 将表达式转换为对函数的rvalue引用是lvalue

It follows from the definition of value categories in C++11 3.10/1 (emphasis mine): 它遵循C ++ 11 3.10 / 1中的值类别的定义(强调我的):

  • An lvalue (...) designates a function or an object. 左值 (...)表示函数或对象。 ... ...

  • An xvalue (an “eXpiring” value) also refers to an object, ... xvalue (“eXpiring”值)也指对象,......

  • An rvalue (...) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object. rvalue (...)是xvalue,临时对象(12.2)或其子对象,或者与对象无关的值。

  • A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. prvalue (“纯”rvalue)是一个不是xvalue的rvalue。 ... ...

Notice that only the lvalue category can be a function, all the others are values or objects only. 请注意,只有左值类别可以是一个函数,所有其他类别只是值或对象。

It's also echoed in 5.2.9/1: 它也在5.2.9 / 1中得到回应:

The result of the expression static_cast<T>(v) is the result of converting the expression v to type T . 表达式static_cast<T>(v)的结果是将表达式v转换为类型T If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue ; 如果T左值引用类型或函数类型的右值引用,则结果为左值 ; if T is an rvalue reference to object type, the result is an xvalue; 如果T是对象类型的右值引用,则结果为xvalue; otherwise, the result is a prvalue. 否则,结果是prvalue。 ... ...

As for the why of it, I can of course only guess (not being part of the standardisation committee). 至于它的原因,我当然只能猜测(不是标准化委员会的一部分)。 But my guess is that it would make no sense to have rvalues of function type—a function can never be a temporary, it can never be at or near the end of its lifetime. 但我的猜测是,拥有函数类型的rvalues是没有意义的 - 函数永远不会是临时函数,它永远不会处于或接近其生命周期的末尾。

Very grateful to the information( N3055 ,link at his comment) provided by TC , in order to facilitate a quick overview of the answers, and I quote some paragraphs related to this issue. 非常感谢TC提供的信息( N3055 ,他的评论链接),以便快速概述答案,并引用与此问题相关的一些段落。 This answer tells us why 这个答案告诉我们原因

rvalue references (like traditional lvalue references) can be bound to functions. rvalue引用(如传统的左值引用)可以绑定到函数。 Treating an rvalue reference return value as an rvalue, however, introduces the novel concept of a function rvalue into the language. 然而,将rvalue参考返回值作为rvalue处理,将函数rvalue的新概念引入到语言中。 There was previously no such idea – a function lvalue used in an rvalue context becomes a pointer-to-function rvalue, not a function rvalue – so the current draft Standard does not describe how such rvalues are to be treated. 之前没有这样的想法 - 在右值上下文中使用的函数左值变为指向函数的rvalue,而不是函数rvalue - 因此当前的标准草案没有描述如何处理这样的右值。 In particular, function calls and conversions to function pointers are specified in terms of function lvalues, so most plausible uses of rvalue references to functions are undefined in the current wording. 特别是,函数调用和函数指针的转换是根据函数左 值来 指定的, 因此对函数的右值引用的最合理使用在当前的措辞中是未定义的。

One possible resolution for these problems would be to maintain the current approach of treating an rvalue reference return value as an rvalue but to add various caveats to the specification of rvalues so that those coming from rvalue references would have special characteristics. 这些问题的一种可能的解决方案是保持当前的方法将右值参考返回值视为右值,但是为rvalues的规范添加各种警告,以便来自右值参考的那些具有特殊特征。 This could be called the “funny rvalue” approach. 这可以称为“有趣的左值”方法。 However, further examination of the current wording of the draft Standard indicates that the problems listed above are probably only the tip of the iceberg: many of the specifications that should apply to the objects to which rvalue references refer, such as object lifetime, aliasing rules, etc., are phrased in terms of lvalues, so the list of rvalue caveats could get quite long . 然而,进一步检查标准草案的当前措辞表明,上面列出的问题可能只是冰山一角:许多规范应适用于右值引用所引用的对象,例如对象生存期,别名规则等等,用左值表示, 因此右值警告列表可能会很长

This suggests an alternative approach: that rvalue reference return values should actually be seen as lvalues, with a few exceptions to allow them to be treated as rvalues in the cases where that is intended, ie, in reference binding, overload resolution, and template argument deduction. 这表明了一种替代方法:rvalue引用返回值实际上应该被视为左值,除了一些例外,允许在预期的情况下将它们视为rvalues,即在引用绑定,重载决策和模板参数中扣除。 This idea, dubbed the “funny lvalue” approach, is embodied in earlier versions of this paper.After extensive discussions in the Core Working Group at the Pittsburgh (March 8-13, 2010) meeting, ...... 这个被称为“有趣的左值”方法的想法体现在本文的早期版本中。经过匹兹堡核心工作组(2010年3月8日至13日)的广泛讨论 ,......

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

For a call to a non-member function or to a static member function, the postfix expression shall be either an lvalue that refers to a function (in which case the function-to-pointer standard conversion (4.3) is suppressed on the postfix expression), or it shall have pointer to function type. 对于非成员函数或静态成员函数的调用,后缀表达式应该是引用函数的左值 (在这种情况下,后缀表达式上的函数到指针标准转换(4.3)被抑制),或者它应具有指向函数类型的指针。

Now static_cast<void(&&)(int)>(test) is an lvalue. 现在static_cast<void(&&)(int)>(test)是一个左值。

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

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

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