Thus we can bind a non-const lvalue reference to a function marked with std::move() because a function marked with std::move() is still an lvalue.
Reference:
Special Rule for Casting to Rvalue References to Functions:
The C++ standard has a specific rule regarding the value category of a cast expression when the target type is an rvalue reference to a function type. According to the standard, a cast expression to an lvalue reference type or an rvalue reference to a function type results in an lvalue.
This is a key exception to the general rule that casting to an rvalue reference to an object type yields an xvalue.
Why this special rule?
The concept of "moving" is primarily applicable to objects that own resources (like dynamic memory). Moving an object involves transferring ownership of these resources from one object to another, often leaving the source object in a valid but empty or default state. This is a meaningful operation for objects where copying is expensive.
Functions, on the other hand, do not own such resources that can be transferred in this manner. A function's identity is its entry point in memory, which is fixed. There's no state within a function itself that can be "moved" to another location or entity in the way an object's data members might be.
Therefore, casting a function to an rvalue reference to a function doesn't enable any form of resource transfer or change the fundamental lvalue nature of the function itself. The C++ standard reflects this by specifying that such a cast still results in an lvalue. The expression still refers to the same identifiable function entity.
void f(int) {}
void(&fref1)(int) = f; // fref1 is an lvalue
void(&&fref2)(int) = f; // fref2 is also an lvalue
auto& ar = std::move(f); // OK: ar is lvalue of type void(&)(int)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.