-1

Consider following code:

using flref = int(&)(double);
using frref = int(&&)(double);
int foo(double){ return 32; }
int main(){
    flref l = foo;  // Function lvalue references are bound to the function name
    frref r = foo;  // Function rvalue references are bound to the function name
    return 0;
}

Why can both the lvalue reference and the rvalue reference bind to the function in this case? Both GCC, Clang, and MSVC compile this code without errors.

Is a function name an lvalue or an rvalue when used as an expression?

In the flref l = foo; sentence, is the rhs of = an expression?

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
Yue Zhou
  • 47
  • 3
  • 2
    [if it has a name, then it is an lvalue](https://stackoverflow.com/questions/27554296/on-how-to-recognize-rvalue-or-lvalue-reference-and-if-it-has-a-name-rule) – Jason Apr 17 '23 at 03:31
  • @Jason So you think `foo` is a lvalue? So why can an rvalue reference be bound to this lvalue? `int x = 10; int&& rref = x; // error` – Yue Zhou Apr 17 '23 at 03:39
  • @NateEldredge So you think `foo` is an rvalue? So why can a lvalue reference be bound to this rvalue? `int& ref = 10; // error` – Yue Zhou Apr 17 '23 at 03:40
  • 2
    Calling a "_lvalue reference_" a "_left reference_" and a "rvalue reference" a "_right reference_" is very misleading. The pre-C++ origin of the terms "_lvalue_" and "_rvalue_" might be related to "_left_" and "_right_" side of assignment, but that meaning is only applicable in a small subset of the C++ language. – user17732522 Apr 17 '23 at 03:49
  • 1
    @YueZhou Function lvalues may be bound to rvalue references. That's an exception to the general rule that it is impossible for lvalues to be bound to rvalue references. This choice is just more convenient, since there are no rvalues of function type. See the "_or function lvalue_" in https://eel.is/c++draft/dcl.init.ref#5.3.1. – user17732522 Apr 17 '23 at 03:51
  • Relevant question: [Can an rvalue reference bind to a function?](https://stackoverflow.com/q/15589842/580083) – Daniel Langr Apr 17 '23 at 06:51

1 Answers1

4

Whether the function name is a lvalue or an rvalue when used as an expression?

An id-expression naming a function is an lvalue expression of the function's type. There are no rvalue expressions with function type.

Why can both function left and right references be bound to function names?

Because lvalue expressions of function type are specifically exempt from the requirement that a rvalue reference must be initialized, after potential temporary materialization, by an rvalue (specifically xvalue) expression. See "or function" in [dcl.init.ref]/5.3.1.

This was probably chosen to be specified this way since it is the most convenient choice. The alternatives would be either to disallow rvalue references to functions completely, which would make generic code unnecessarily more difficult to write or to introduce a notion of function rvalues, which would just force everyone to write std::move around function names all the time.

flref l = foo; In this sentence, is the right side of the equal sign an expression?

It is called a statement, not a sentence. The right-hand side of the equals sign in a variable initializer must always be either a braced-init-list (i.e. = { /*...*/ }) or an expression. If there are no braces, then it can't be anything but an expression.


As an aside: Calling a "lvalue reference" a "left reference" and a "rvalue reference" a "right reference" is very misleading. The pre-C++ origin of the terms "lvalue" and "rvalue" might be related to "left" and "right" side of assignment, but that meaning is only applicable in a small subset of the C++ language.

user17732522
  • 53,019
  • 2
  • 56
  • 105