9
votes
typedef void(&&RF)(void* p);

RF rf()
{
    return f;
}

int ay[10] = { 0 };

typedef int(&&RA)[10];

RA ra()
{
    return ay; // error
}

cout << is_lvalue_reference<decltype(rf())>::value << endl; // 1

The C++ reference says "rvalue references to functions are treated as lvalues whether named or not".

But I can not understand what the considerations for this are? I guess that perhaps the name of function is always a lvalue. So it must keep its attribute of an lvalue and ensure passing the function name to anywhere it can be invoked, like rf()(NULL). Then the array name came unbidden to my mind. I think it is always a lvalue too, so I wrote the code above to test this and got a error.

Who can point out the real reason behind all of this?

1
Any named rvalue reference is, itself, an lvalue.chris
Well that's interesting. There's a language rule that says that a function call expression is an lvalue (even) if the function returns an rvalue reference to a function type. But this is only an exception for function types, not for any other type.dyp
@chris A named rvalue reference is an xvalue.KeyC0de

1 Answers

10
votes

In N3055 the issue of rvalue references to functions is briefly discussed:

In addition, rvalue references (like traditional lvalue references) can be bound to functions. Treating an rvalue reference return value as an rvalue, however, introduces the novel concept of a function rvalue into the language. 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. 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.

Functions don't have lifetime or storage duration, so the lvalue/rvalue distinction doesn't make sense for them. On the other hand, if you allow function rvalues to exist, you have to resolve the issues discussed in the quoted paragraph. In light of this, forcing all function values to be lvalues seems to me to have been a reasonable solution.

Another solution, I suppose, would have been to ban function rvalues altogether, so any attempt to create an rvalue reference to function type would result in an ill-formed program. I don't know whether this approach was considered, but my guess is that it would cause inconveniences with generic programming.

On the other hand, for any object type, including array types, there is a meaningful distinction between lvalues and rvalues. So the language forbids you from binding an rvalue reference to object type to an lvalue of object type. I'm not sure why you're surprised that your code doesn't compile.