So we declare a variable x: int x = 42; An expression x in this scope is now an lvalue (so also a glvalue). Follow. Lvaluesand Rvalues Lvalues and rvalues aren’t really language features. For non-class types you cannot assign to rvalues. Since you can call the function object std::bind gives you multiple times, it cannot “use up” the captured argument so it will be passed as an lvalue reference. You might consider A& f () & { to ensure the call is happening on an lvalue object if you need to do something like this. An example of an rvalue would be a literal constant – something like ’8′, or ’3. You will often find explanations that deal with the left and right side of an assignment. All you have to do here is make sure you get a pointer to an array, rather than a pointer to the first element of the array. Assume a variable name as a label attached to its location in memory. The pass-by-value version allows an lvalue argument and makes a copy of it. [3] Finally, this temporary variable is used as the value of the initializer. In int *p = &x;: x is an lvalue, referring to the variable of that name, &x is an rvalue, it's part of the initializer (specifically, an assignment-expression ), p is neither an rvalue nor an. 2 indicates the behavior of lvalues and rvalues in other significant contexts. in . How to cast/convert pointer to reference in C++. And there is no mandated lvalue-to-rvalue conversion. You could also pass it to a function accepting a const char*& (i. You have three choices: (1) assign to rvalue reference, (2) assign to const lvalue reference, (3) return by value but implement move semantics in your class. e. What you're referring to is the fact that if an expression. If an lvalue-to-rvalue conversion were performed on s, it would also call the copy constructor; [conv. This assignment uses the lvalueexpression nas an rvalue. call]/12, [expr. This is the place where compiler complains, because i as lvalue cannot be bound to rvalue reference. You are comparing two different things that are not really related. Rvalue references work in principle similarly to Lvalue references: We declare them by writing the data type of the rvalue followed by && and an identifier. Their very nature implies that the object is transient. You would need to provide const string& as template argument for T to make T&& also const string&. 2. Therefore it makes sense that they are mutable. If the operator accepts paramters by value, whenever you use an lvalue expression, there needs to be lvalue-to-rvalue conversion, which is copy initialising the parameter object from the argument. Let’s turn it around a bit. The actual problem is instantiating Parent with a reference type to begin with; in C++11 this is generally avoided via application of std::decay. e. const A& x = 1; //compile x = 2; //error! A&& xxx = 1; //compile A& xx = 1; //does not compile. Note: The ISO C standard does not require this, but it is required for POSIX conformance. This means the following is illegal: int main() { const int x { 5 }; int& ref { x }; return 0; } This is disallowed because it would allow us to modify a. I discovered that N3290 (identical to C++11 standard) contains non-normative example of binding double&& to rvalue generated from int lvalue, and the updated wording in §8. The reason why you need to const is to make x not a forwarding reference. h and move. Using our understanding of. 2) Lvalue of any type T may be converted to an lvalue or rvalue. first) as same as the implementation of std_pair. Let's look at the following snippet: So we have a reference being initialized by an xvalue of type const foo. Second (and you probably missed that), const char* is converted to a rvalue std::string via the const char* non-explicit constructor of std::string (# 5 in the link). Without this, the compiler will complain that you "cannot bind non-const lvalue reference of type 'std::string&' to an rvalue. cast (this is applicable from C++11 and later). Both of these options are user-defined conversion functions, so neither is better in terms of overload resolution, thus an ambiguity. This is its value category. The Parent class stores a pointer, but due to rvalue to lvalue conversion, the Parent ends up storing a reference to a pointer. Read 5. In that sense, rvalue references are a new language feature that adds a generic rvalue-to-lvalue. has an address). @YueZhou Function lvalues may be bound to rvalue references. 4. So sizeof (0, arr) = sizeof (arr) and which would be equal to 100* sizeof (char) and not = sizeof (char*). A nice feature of this heuristic is that it helps you remember that the type of an expression is independent of. HI Enlico, Thank's for the awesome answer, now I have a clearer idea of how to use RValue and LValue references. If you can't, it's usually an rvalue. It matches arguments of any value category, making t an lvalue reference if the supplied argument was an lvalue or an rvalue reference if the supplied argument was an rvalue. To set this compiler option in the Visual Studio development environment. The "my target must be copy-constructable" requirement of std::function is due to its own requirement of being copy-constructable. The word "rvalue" in the term "rvalue reference" describes the kind of reference: An rvalue reference is a reference that binds to rvalues, and an lvalue reference is a reference that binds to lvalues (mostly). 2), an xvalue if T is an rvalue reference to object type. i by itself is an lvalue. @user2308211: I think what I might have meant to say (back when I didn't know any C++!) was that vec4(). static_cast can do other things, as listed in 5. I would respect the first compiler more, it is at least honest with its inefficiency. You might want to use it more than once in your constructor, so it shouldn't be moved from on first use unless you explicitly want to. My guess is that this restriction has historical roots in the C++98 standard where rvalues were limited to temporaries, that were fully managed by the compiler. 1) If the reference is an lvalue reference. universal reference. std::forward is a conditional std::move. The usual arithmetic conversions required by many arithmetic operators do invoke an lvalue-to-rvalue conversion indirectly via the standard conversion used. The reason is simple; named rvalue reference is treated as lvalue (and implicit conversion from lvalue to rvalue reference is forbidden by standard). The expression ar is an lvalue. ) In very broad and simple terms, an lvalue refers to. Type conversions on references. 1 Answer. A simpler case: template <typename T> void foo(T&& ) { } foo(1); // T is int int x; foo(x); // T is int& When you specify float for x, you are specifying that that particular argument will have type float&&, and you cannot implicitly convert an lvalue float to an rvalue. You are returning a copy of A from test so *c triggers the construction of a copy of c. Conversion of a function pointer to void * shall not alter the representation. std::auto_ptr<Foo> foo(new Foo()); // auto_ptrs are deprecated btw bar(std::move(foo)); // changed ownership. And the lvalue-to-rvalue conversion always returns a prvalue value, not a (temporary) object. There is no implicit conversion as suggested in the title, the reference binds directly to the. lvalue references are marked with one ampersand (&). Whenever an lvalue is used in a position in which an rvalue is expected, the compiler performs an lvalue-to-rvalue conversion and then. is an rvalue reference to an object type, is an xvalue. But in this particular case, the rules. I think I'm missing something basic regarding the lvalue-to-rvalue standard conversion. void f1(int& namedValue){. std::forward<> will make sure to convert the "value category" x to match its type. Let's look at (T1&&)t2 first. That is the historical origin of the letters l. It seems like std::array can be converted to an std::span when it's an rvalue only on clang. So, the conversion from a A rvalue to something that P&& would accept in (1) calls the user defined conversion function operator P() &&. 8. lval), array-to-pointer (conv. A compiler can optimize the call to copy constructor and directly call the matching constructor. This article also mentioned that issue. It is really about rvalues vs. Refer to the Essential C++ blog for RAII. The fact that you pass bind itself an rvalue only means that there is. If this. However, it's type will be const std::string or std::string depending on the choice of const in the MyPair type. For example, this code will not compile. This is. The returned lvalue will contain exactly the result it is supposed to. C++0x, by contrast, introduces the following reference collapsing rules: The second rule is a special template argument deduction rule for function templates that take an argument by rvalue reference to a template argument: When foo is called on an lvalue of type A, then T resolves to A& and hence, by the reference collapsing rules above, the. It is used to convert an lvalue into an rvalue. 23. 255 How come a non-const reference cannot bind to a temporary object? 1 Why the code doesn't work on CodeBlocks,but on. 18. goo<int> is an lvalue of function type, but expressions of function type are. According to the rule of forwarding reference, when an lvalue is passed to add, the template type argument Element will be deduced as SomeClass&. To convert an lvalue to an rvalue, you can also use the std::move() function. Roughly, it’s an lvalue if you can “take its address”, and an rvalue otherwise. 1. The lvalue-to-rvalue conversion is covered in N3485 in section 4. C++98 assigning a value to a volatile variable might result in an unnecessary read due to the lvalue-to-rvalue conversion applied to the assignment result introduce discarded-value expressions and exclude this case from the list of cases that require the conversion CWG 1343: C++98 sequencing of destructor calls inExcept for an implicit object parameter, for which see 13. When you have a named value, as in . On the other hand lvalue references to const forbids any change to the object they reference and thus you may bind them to a rvalue. 12. The rvalue variant can already bind to this because you're already passing a temporary and the lvalue variant can bind to. 1: A glvalue of a non-function, non-array type T can be converted to a prvalue. e. OK. To set this compiler option in the Visual Studio development environment. It shouldn't. std::string hello = "hello"; std::string planet. A pointer is a type. However, note that when binding this to an rvalue reference, the value of this will be copied into a temporary object and the reference will instead be bound to that. And most implementations do that. We create two types of access: one const and one not const. The third constructor is called move constructor. return 17; //an lvalue reference to an rvalue} In C++03 copying the rvalue to an lvalue is the preferred choice (in some cases you can bind an lvalue reference to const to achieve a similar effect): r-value references are designed to be the subject of a move-constructor or move-assignment. std::function has a non-explicit constructor that accepts lambda closures, so there is implicit conversion. Consider this similar question: "Is an integer an lvalue or an rvalue". There is no lvalue-to-rvalue conversion in this scenario. It can appear only on the right-hand side of the assignment operator. lvalue simply means an object that has an identifiable location in memory (i. But in the circumstances of the linked question, the template instantiation of std::function cannot be inferred from the lambda type. The Rvalue refers to a value stored at an address in the memory. So in terms of the type analogy this means that cv T& and cv T&& are transformed to cv T if T is a class type and to T if T is a non-function non-array. The idea is that if you have a reference binding that could have been a direct binding if only the reference were of the appropriate kind (i. 98 * @param __t A thing of arbitrary type. I couldn't find an example of l2r applicable to class types myself; in all the seemingly applicable examples there's usually a function involved that takes lvalue-ref (like copy-ctor), for which l2r seems to be suppressed (see. Convert temporary to reference in C++. If we have a lvalue we can return it from a function, so we get a rvalue. In the previous question, I asked how this code should work: void f (const std::string &); //less efficient void f (std::string &&); //more efficient void g (const char * arg) { f (arg); } It seems that the move overload should probably be called because of the. > In general, if I need an rvalue and it's legal to convert the lvalue I have into an rvalue, the compiler should do it automatically. So, when you type const int& ref = 40. When you look at a parameter thing&& x its type is an rvalue reference, however, the variable named x also has a value category: it's an lvalue. In both cases, if the wrapper has been successfully constructed, we mark the status as value to indicate that we have a value. lvalues. Yes, if you pass an lvalue const char* to a function accepting a const char*, that'll work. So in your example, the expression to the right of the = is an expression that happens to be an lvalue. Put simply, an lvalue is an object reference and an rvalue is a value. Since int() isn't an lvalue, you can't assign to int(). 23. This example might clarify it:So we have a reference being initialized by an xvalue of type const foo. To mark the place(s) where you want to take advantage of the licence to ruthlessly plunder it, you have to convert it to an rvalue-reference on passing it on, for example with std::move or std::forward, the latter mostly for templates. And an rvalue reference is a reference that binds to an rvalue. 8. 10/2), Whenever a glvalue appears in a context where a prvalue is expected, the glvalue is converted to a prvalue. an lvalue reference). — even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter. lvalue:-. As shown in the code below, by using move()funciton, when I bound a converted lvalue to an rvalue reference, and then changed the value of the rvalue. 10) of a non-function, non-array type T can be converted to a prvalue. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. C++ type conversion from a variable to a reference. However, a (prvalue). )In the third line, they undergo an implicit lvalue-to-rvalue conversion. If the target type is an inaccessible or ambiguous base of the. 2, and 4. Here is a silly code that doesn't compile: int x; 1 = x; // error: expression must be a modifyable lvalue. C++ (as opposed to C) is a devoted lvalue-preserving language: it strives to painstakingly preserve the "lvalueness" of an expression whenever it is possible. If element at this position doesn't exist, function. "cannot bind non-const lvalue reference of type ‘M&’ to an rvalue of type. Would you ever mark a C++ RValue reference parameter as const. 1:. If you compile with /W4 then the compiler will warn you. You are returning a copy of A from test so *c triggers the construction of a copy of c. Both of g and h are legal and the reference binds directly. FWIW, the POSIX 2008 standard says (System Interfaces, §2. move simply returns an rvalue reference to its argument, equivalent to. I think it's reasonable to call print_stream like this:. A minimal example:This is because of copy elision in C++. The implementation of the language level is based on IBM's interpretation of the standard. The second one constructs the object with an lvalue reference which reads the argument, t. 6) An lvalue (until C++11) glvalue (since C++11) expression of type T1 can be converted to reference to another type T2. 2k 9 128 212 asked Jan 14, 2016 at 8:26 Simon X. References. 5. Convert any type to void, evaluating and discarding the value. I could have used std::move to convert the lvalue to rvalue reference and the call would be successful. But you might just let regular deduction occurs. Cast to reference type. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories: xvalue, and lvalue . b is just an alternative name to the memory assigned to the variable a. Because a non-const reference is always a lvalue, so the code works and result in a lvalue (i. 3 Viable functions (4). Each expression in C (an operator with its arguments, a function call, a constant, a variable name, etc) is characterized by two independent properties: a type and a value category . Whether it’s heap or stack, and it’s addressable. using g++. Safe downcast may be done with dynamic_cast. Yes, rvalues are moved, lvalues are copied. The first are categories for the type of a variable/member. Both lvalue references and rvalue references are a compound type. Share. thus, this is legal: string&& s = foo (); // extends lifetime as before s += "bar"; baz (std::move (s)); // move the temporary into the baz function. Except for an implicit object parameter, for which see 13. thus, this is legal: string&& s = foo (); // extends lifetime as before s += "bar"; baz (std::move (s)); // move the temporary into the baz function. [dcl. Note that the lvalue-to-rvalue conversion is not the only conversion that converts an lvalue to a prvalue: There's also the array-to-pointer conversion and the function-to-pointer conversion. e. 2), an xvalue if T is an rvalue reference to object type, and a prvalue otherwise. std::apply perfect-forwards the tuple to std::get to access elements of the tuple. Therefore, I thought of providing some macro/function that wraps a parameter so it can be passed whether it's an l/rvalue - in this case get_addr. (Lvalue-to-rvalue conversions on class types are rare, but do occur in some places in the language, e. It would capitalize std::strings, and display each parameter after they are capitalized. Read 5. e. The value category of a compound literal is lvalue (its address can be taken). Otherwise your compiler will throw an error: obj & a1 = bar (); invalid initialization of non-const reference of type ‘obj&’ from an rvalue of type ‘obj’. It is illegal in C++ to attach non-const references to rvalues. an rvalue reference). As an example, the operand of unary & must be a function designator, the result of [], the result of unary *, or an lvalue (C 2018 6. In k++, the expression k is an l-value (roughly speaking, it has a name), which is its value-category. Using it only makes sense inside of a template, where you choose whether to move or not depending on a template argument. (prvalue) The output of this example is: produces an answer of type int because both are integers. 2 1). 6 — Pass by const lvalue reference. Therefore, if we make a reference parameter const, then it will be able to bind to any type of argument:According to the rvalue reference proposal, a named rvalue is no different from an lvalue, except for decltype. 1 Answer. If t returns by lvalue reference, the code does not compile because a rvalue reference cannot bind to it. Set the Enforce type conversion rules property to /Zc:rvalueCast or. 20 and lower) & R-value, higher the number the better (R-5 and higher). 4. 2), then: the value contained in the referenced. rvalue references are marked with two ampersands (&&). 6. One can calculate it from the equation for C-value in Equation 1 above: Equation 3: R-value = thickness / K-value. I can't speak for the motivation behind having it work this way despite the tuple explicitly holding an. And so on. Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4. Regarding the second question. Alex November 11, 2023. Category 4 used to be a bit different in C++11, but I believe this wording is correct for C++14. The expression *this is an lvalue; A {} is an rvalue (prvalue) even though they designate the same temporary object. Both of these options are user-defined conversion functions, so neither is better in terms of overload resolution, thus an ambiguity. 1 Answer. However, you don't have double && in your code, you have U && for a deduced U. The result is that of *reinterpret_cast<T2*>(p), where p is a pointer of type “pointer to T1 ” to the object designated by expression. If you had. Similarly, rhs in Gadget. (since C++11)20. Done. There is a very important distinction to be made between expressions which are rvalues and expressions whose type is an rvalue reference. In such cases: [1] First, implicit type conversion to T is applied if necessary. Or the compiler could convert said references to pointers, push a pointer on the stack, pop the identical pointer off, and call it std::move. 1 Answer. Naming expressions are always lvlaues. The C++ Standard does use the term rvalue, defining it indirectly with this sentence: "Every expression is either an lvalue or an rvalue. According to the C++ specifications, it takes two rvalues as arguments and returns an rvalue. In the previous question, I asked how this code should work: void f (const std::string &); //less efficient void f (std::string &&); //more efficient void g (const char * arg) { f (arg); } It seems that the move overload should probably be called because of the. Arrays are lvalues. m, static_cast<A&&> (a), and a + a are xvalues. This approach is hard to generalize to more input arguments. First the compiler performs an implicit array-to-pointer conversion for "abc", so the type of "abc" becomes const char*. The address-of operator can only be used on lvalues. In C++, the cast result belongs to one of the following value categories:. – super. For example, assume you pass an rvalue reference to an object of type X to a function template that takes type T&& as its parameter. If t returns by lvalue reference, the code does not compile because a rvalue reference cannot bind to it. (If you insist to know, the result of subscripting into an rvalue array used to be an lvalue in C++11, but is an xvalue in C++14 - issue 1213 . baz(1) by itself is not UB, but it would be UB to dereference the resulting pointer after the end of the full-expression containing baz(1). 4. If t returns a local variable, then you get a dangling reference, since that variable is gone after the call. Every lvalue is, in turn, either modifiable or non-modifiable. If an lvalue-to-rvalue conversion were performed on s, it would also call the copy constructor; [conv. 3=i; is illegal. In C++ class and array prvalues can have cv-qualified types. Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i. 1, 4. Lvalue to rvalue conversion changes the value category of an expression, without changing its type. For details, see Set C++ compiler and build properties in Visual Studio. Ternary conditional operator will yield an lvalue, if the type of its second and third operands is an lvalue. It is VC++'s evil extension. why std::forward converts both as rvalue reference. C. 14′. “If T1 is reference-related to T2 and the reference is an rvalue reference, the initializer expression shall not be an lvalue. 1. 1) does not accept such code (makes perfect sense). , values that can be assigned: namespaces, for instance, are not assignable; thanks to @Maggyero for the edit suggestion). In the next example, we first use the addition operator + (→//3) to add two Lvalues and then the assignment operator = to assign the result to another Lvalue. In (static_cast<int&&> (3))++, the expression static. The purpose of r-value reference parameters is to detect specifically when an object is an r-value. I expect that when using a temporary instance of a Wraper object, the conversion operator defined for rvalue will always be used. But then i got following error:. Rvalue references are types, types are not expressions and so cannot be "considered lvalue". The following diagram illustrates the relationships between the. e. , with extensions: pointer or reference to a is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is (that is, this cast ignores the private inheritance specifier). If you wanted to move an lvalue, you would likely have to use an RAII container that does this for you. C++ does not allow you to get an r-value reference to a variable without an explicit conversion. Oct 31, 2016 at 20:29. Whenever a glvalue expression. Applying the lvalue-to-rvalue conversion to x reads the value of the mutable global variable globx, which makes it not a constant expression as the value of globx is subject to change (and, even if it were const, there would be the issue of its value not being known at compile time). Now an lvalue reference is a reference that binds to an lvalue. If you can, it typically is. 53 If T is an incomplete type, a program that necessitates this conversion is ill-formed. 1 is rvalue, it doesn't point anywhere, and it's contained within lvalue x. G. For example, if you’ve declared a variable int x;, then x is an lvalue, but 253 and x + 6 are rvalues. Then I use rvalue reference of class B's this pointer to pass it to A's constructor. rvalue/lvalue tells you the value category. You should provide an overload taking rvalue references when you want to move the passed argument. There are no references of references in C++. 3) If new_type is an rvalue reference type, static_cast converts the value of expression to xvalue. You can disable this behaviour with the /Za (disable language extensions) compiler switch under. 3. Among. Thus, this syntax is now legal: T&& r = T(); rvalue references primarily provide for the following: Move semantics. The reason why you need to const is to make x not a forwarding reference. const A& x = 1; //compile x = 2; //error! A&& xxx = 1; //compile A& xx = 1; //does not compile. The question related to this one. void f2(int&& namedValue){. Each expression has some non-reference type, and each expression belongs to exactly. That's an exception to the general rule that it is impossible for lvalues to be bound to rvalue. Forwarding references are very greedy, and if you don't pass in the exact same type (including. 10. With string as template argument you get string&& in the function parameter, which is a rvalue reference that doesn't accept lvalues. Say we want to steal from an lvalue: int main() { Holder h1(1000); // h1 is an lvalue Holder h2(h1); // copy-constructor invoked (because of lvalue in input) } This will not work: since h2 receives an lvalue in input, the copy constructor is being triggered. func () indeed returns a prvalue and from the C++ Standard par. 9. int a = 1, b; a + 1 = b; int *p, *q; cppreference wrote:; An xvalue is an expression that identifies an "eXpiring" object, that is, the object that may be moved from. Lvalues and rvalues are fundamental to C++ expressions. Non-const rvalue references always refer to a type. The Microsoft documentation is wrong. c++ base constructor lvalue to parameter. The expression x is an lvalue, so it is converted. a glvalue (“generalized” lvalue) is an expression whose. template <typename T> StreamWriter& StreamWriter::operator<< (const T& source) { Write (&source); return *this; } Share. The name “lvalue” comes from the assignment expression E1 = E2 in which the. init. Allowing both rvalues and lvalues to be bound to an lvalue reference makes that impossible. lvalue cannot be a function, expression (like a+b) or a constant (like 3 , 4 , etc. 0. The value of x is 1. lval]/3. Open the project's Property Pages dialog box. 1 Lvalue-to-rvalue conversion paragraph 1 and says (emphasis mine going forward): A glvalue (3. Using lvalue references where rvalue references are required is an error: int& func2(){//compilation error: cannot bind. In C++, it is illegal to implicitly convert an rvalue to an lvalue reference. 3. int&& x = 3; x is now an lvalue. If you pass an prvalue, it isn't converted, the temporary is materialised into the parameter object. It cannot convert from an rvalue to an lvalue reference, even a const one. e. The reference declared in the above code is lvalue. 16. Values return by functions/methods and expression are temporary values, so you do have to use std::move to move them (C++ standard to convert to rvalue) when you pass them to functions/methods. While the type of _x is 'r-value reference to std::vector<int>', it is still an l-value as it has a name. The "l" and "r" in "lvalue reference" and "rvalue reference" refers to the categories of values to which the reference can bind, not to the category of the id-expression naming a variable of this reference type. 20 hours ago · String Templates (a preview feature introduced in Java 21) greatly improves how we create strings in Java by merging constant strings with variable values. –std::forward is usually the way to 'convert' value category. Sorted by: 7. I guess you are reading the Rvalue References: C++0x Features in VC10, Part 2. Expressions Each expression in C (an operator with its arguments, a function call, a constant, a variable name, etc) is characterized by two independent. This is what std::move is for. 10): An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. I recently filed a bug against MSVC which relates to this, where the non-standard behavior caused standard-compliant code to fail to compile and/or compile with a deviant behavior. Value categories. It shouldn't. std::move is there to allow for the casting. You must explicitly use std::move (or a cast) to convert an lvalue into an rvalue reference, and an rvalue reference will never bind to an lvalue on its own. call]/12, [expr. The difference is that &i is OK but &5 is not. You can use str as a variable, which also implies that it is an lvalue, not a temporary rvalue. You need to pass in an rvalue, and for that you need to use std::move: I can see why this is counter-intuitive! x is lvalue (as we know it). 1 Can't make a function accept both rvalue and lvalue references. Radius: 2 2 4. It is a forwarding reference. This is apprently gcc's interpretation, and since arr is not an rvalue (it is an lvalue), this tiebreaker is skipped and no subsequent tiebreakers apply. 4/1: The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue. Unscopedenumeration values implicitly convert to integer. References in C++ are nothing but the alternative to the already existing variable. You can convert an lvalue to an rvalue by casting it to an xvalue; this is conveniently encapsulated into the type-deducing cast. Each C++ expression (an operator with its operands, a literal, a variable name, etc. e. Therefore it makes sense that they are mutable. static_cast<typename remove_reference<T>::type&&> (t) The result of the function call is an rvalue (specifically, an xvalue ), so it can be bound to an rvalue reference where the function argument couldn't. For the second overload, it would call operator const P&() const&. The output is: Copy constructor with lvalue reference. lval] 1. But it is still a reference, which is a lvalue.