Namespaces
Variants
Views
Actions

Talk:cpp/language/value category

From cppreference.com

Contents

[edit] lvalue

I added that any reference to a function is an lvalue. Someone removed that. It is true that any reference to a function is an lvalue so that statement covers all cases. The following box on C++11 is misleading. Fraser R (talk) 00:37, 4 May 2023 (PDT)

Hopefully my edit clarifies the lvalue reference to function case --Ybab321 (talk) 04:05, 4 May 2023 (PDT)

[edit] Category of a.m for prvalues

I think that the a.m example for prvalues is very misleading in its wording; a.m is never a prvalue, since it's named, and is either an lvalue or an xvalue, as noted here:

http://eel.is/c++draft/expr.ref#4.2

It makes sense, to me, that the prvalue bit should be removed entirely. The xvalue case of a.m is correct in that, if a is an rvalue, m is an xvalue.

38.99.42.242 17:22, 22 December 2016 (PST)

That link is to the current C++17 draft, while the part about member of rvalue being an rvalue is from before C++11. It was made confusing by a "since c++17" that snuck in - updated. --Cubbi (talk) 18:20, 22 December 2016 (PST)

(Begemot (talk) 02:32, 26 August 2015 (PDT))

Hi everyone! I think I found mistakes

Hey there, so I've been digging into this to give a seminar on R and L values, and agree that the way it is written now is a bit misleading. I've seen somewhere this called a "bug," however I was just reading the C++14 standard (https://timsong-cpp.github.io/cppwp/n4140/draft.pdf), and on page 87 (101 of the pdf) it states: "An expression is an xvalue if... a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue." I can confirm this is the behavior I get using gcc. I'm pretty scared to touch the actual reference, since I'm no expert, but this seems to be pretty solid...

where is the "bug"? Member of xvalue is xvalue. that's what this page says ("a.m, [...] where a is an rvalue"), as does the current standard (#4.2.sentence-2) as did C++14. --Cubbi (talk) 06:04, 31 October 2018 (PDT)
Let me clarify, I'm not calling it a bug, I've just seen it called that elsewhere. To be more clear, I've posted a question on stackoverflow: https://stackoverflow.com/questions/53160833/should-the-member-access-operator-of-an-rvalue-be-an-xvalue.

This did indeed change in C++14 from C++11, I've edited the main page. I saw this in ISO/IEC 14882:2011 5.2.5p(4.2), and it is also present in https://wg21.link/N3337 (https://timsong-cpp.github.io/cppwp/n3337/expr.ref#4.2): If a is a prvalue, a.m is a prvalue in C++11. 131.111.243.142 02:56, 25 February 2022 (PST)

[edit] lvalue

  • "the name of a variable or function in scope, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;"

But if variable's type is rvalue reference, then value can be moved from, this means that it is an xvalue, rather than lvalue. Am i right?

  • "...member access (except for non-static non-reference members of rvalues, member enumerators, and non-static member functions)."

I think that using rvalues here is wrong, since rvalue means prvalue or xvalue, but member cannot be prvalue, since it always has an identity, so xvalue is more precise.

  • "...subscript (except on an array rvalue)..."

I can't imagine an rvalue array. I think here means an array of xvalues.


Any thoughts?

all three are correct as described on this page. Named rvalue references cannot be moved from (look at any move constructor). Member of rvalue is already correctly described as xvalue. Rvalue arrays are described at cpp/language/array#Array_rvalues --Cubbi (talk) 03:04, 26 August 2015 (PDT)

[edit] lvalue

hi, I do not think the description below about lvalue expression is correct:

  a string literal, such as "Hello, world!";

a string literal should be an pvalue. Kreats (talk) 01:12, 25 December 2015 (PST)

It is correct as written. T. Canens (talk) 01:25, 25 December 2015 (PST)

[edit] rvalue array subscription produces an lvalue, not an xvalue

Sorry, but I just can't find any way that the following is an xvalue:

  a[n], the built-in subscript expression, where a is an array rvalue;

Take a look at this:

#include <utility>
#include <iostream>
 
void bind(int(& arg)[3]) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
 
void bind(int(&& arg)[3]) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
 
void bind(int& arg) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
 
void bind(int&& arg) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
 
template<typename T> using identity = T;
 
int main() {
    int array[3] = {0,0,0};
    using arr = int[3];
 
    // A prvalue array binds to rvalue reference
    bind(identity<int[]>{0,0,0});
 
    // A prvalue array binds to rvalue reference
    bind(arr{});
 
    // An xvalue array binds to rvalue reference
    bind(std::move(array));
 
    // prvalue array subscription binds to lvalue reference
    bind(identity<int[3]>{0,0,0}[0]);
 
    // prvalue array subscription binds to lvalue reference
    bind(arr{}[0]);
 
    // xvalue array subscription binds to lvalue reference
    bind(std::move(array)[0]);
}

Output:

void bind(int (&&)[3])
void bind(int (&&)[3])
void bind(int (&&)[3])
void bind(int &)
void bind(int &)
void bind(int &)

Subscripting an array xvalue and prvalue both bind to the lvalue reference overload!

What am I missing? Perhaps my attempts to produce an array prvalue actually have just created xvalues, and xvalue array subscription is an lvalue expression? If so, I am stumped for more ways to create an array prvalue.

I also found no reference in the C++11 standard that states rvalue array subscription is an xvalue expression. Perhaps whoever explains this to me could point me to the paragraph that defines this behaviour.

Thanks :D Jsj (talk) 21:20, 24 February 2016 (PST)

For clang, there seems to be an open bug report regarding subscripts in rvalue arrays --Cubbi (talk) 02:59, 25 February 2016 (PST)

[edit] Expressions can have reference type

The statement "Each expression has some non-reference type" is not true as is. Scott Meyers has a blog post dedicated to this. Stefan Arnold (talk) 09:08, 3 March 2016 (PST)

He seems to like making C++ more complicated than it is. Expressions with reference type do not exist. If you attempt to form one, that's not what you get. This (and other type adjustments prior to any analysis) might matter if you're writing a C++ parser, but it's unobservable semantically. --Cubbi (talk) 10:23, 3 March 2016 (PST)
Actually it's not Scott who makes things complicated, but the standard. Indeed, there are some paragraphs in the standard concerning reference-typed expressions (i.e., before type adjustment drops off the reference from the type), so people might get confused when switching between cppreference.com and the standard. But OK, it's probably in the spirit of cppreference.com to ignore such seemingly unnecessary complications! Stefan Arnold (talk) 01:39, 4 March 2016 (PST)

[edit] Ternary conditional

In all three categories (lvalue, prvalue, xvalue) there is an identical "ternary conditional" bullet that says "a ? b : c, the ternary conditional expression for some a, b, and c", without actually qualifying the a, b, or c. Does anyone know the technical restrictions applied to them? Wyverald (talk) 19:54, 16 October 2016 (PDT)

Yes, it's an extremely complicated mess. You can click on the description for that operator for the gory details. T. Canens (talk) 00:50, 17 October 2016 (PDT)

[edit] C++17 rewrite

I think Cubbi's rewrite makes this page much harder to understand. While it may be true that "rvalue" no longer maps directly to "moveable", I think the taxonomy as a whole is much more comprehensible when initially presented as Stroustrup's orthogonal axes.

For now I've just added a table to the intro that shows the axes. I think there's room for more improvement by rewording or expanding the intro text, but I didn't want to get too far ahead of myself. Guildd (talk) 13:47, 9 January 2017 (PST)

I don't think the table that was added demonstrates the axes mentioned in Stroustrup's design (those axes were "has identity" in one dimension and "can be moved" in the other). I loved that classification too, but it no longer applies except to the C++11 History section. --Cubbi (talk) 20:41, 9 January 2017 (PST)


[edit] A diagram

When I first learned about the value categories in C++, a diagram somewhere online helped me a lot to understand them. I thought it would be nice to add something like that to this page and so recreated a similar one here: https://gist.github.com/vojtechkral/699fc20e7df671c13d0cd257680aff5b but I don't seem to have the permission to upload here. Any help? Thanks! Vojtechkral (talk) 04:49, 18 December 2017 (PST)

[edit] Temporaries in C++17

The intro says:

  • a prvalue (“pure” rvalue) is an expression whose evaluation either
    • computes the value of the operand of an operator (such prvalue has no result object), or
    • initializes an object or a bit-field (such prvalue is said to have a result object). All class and array prvalues have a result object even if it is discarded. In certain contexts, temporary materialization occurs to create a temporary as the result object;

But later it is said that "any expression that designates a temporary object, after temporary materialization" is an xvalue.

IMHO the intro should be reworked to clarify the differences between pre-C++17 and C++17 standards. Is it even possible, in C++17, to have a prvalue with a result object? If yes, when?

-- 147.32.8.170 02:03, 10 October 2019 (PDT)

Since C++17 (I don't really understand the related specification until C++17), a prvalue may have a result object but never designates it. The result object is always designated by a glvalue. --Fruderica (talk) 03:31, 10 October 2019 (PDT)
How do you define having a result object and designating a result object? Can you show an example of a (prvalue) expression which has a result object, but does not designate it? -- 147.32.8.170 05:34, 10 October 2019 (PDT)
Temporary materialization is a conversion from prvalue to xvalue. Maybe "any expression that designates a temporary object, after temporary materialization" under xvalue is a bit ambiguous? --D41D8CD98F (talk) 04:05, 10 October 2019 (PDT)
re "IMHO the intro should be reworked to clarify the differences between pre-C++17 and C++17" -- pre-C++17 part is in the History section. There were far too many changes through the years to make anything legible that attempts to describe both the past and the present (we tried).
re "Can you show an example of a (prvalue) expression which has a result object, but does not designate it?" as the intro currently says, prvalue has a result object when it "initializes an object or a bit-field". int x = 1; the prvalue 1 has the result object x. The expression 1 does not designate any object: it has no address. --Cubbi (talk) 05:43, 10 October 2019 (PDT)
re "pre-C++17 part is in the History section" -- in that case I suggest to mark the whole intro as "since C++17". Otherwise it is not easy to realize this, for example I assumed that the intro holds "since C++11". -- 147.32.8.170 06:05, 10 October 2019 (PDT)

[edit] Bit-fields

Contrary to this page, bit-fields are not mentioned in the value categories specified in the standard (https://eel.is/c++draft/expr.prop#basic.lval-1).

Compare

  • A glvalue is an expression whose evaluation determines the identity of an object or function.
  • A prvalue is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, or an expression that has type cv void.
  • An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).

to

  • a glvalue (“generalized” lvalue) is an expression whose evaluation determines the identity of an object, bit-field, or function;
  • a prvalue (“pure” rvalue) is an expression whose evaluation either computes the value of an operand of a built-in operator or has type void (such prvalue has no result object), or initializes an object or a bit-field (such prvalue is said to have a result object).
  • an xvalue (an “eXpiring” value) is a glvalue that denotes an object or bit-field whose resources can be reused;

Who is right?

Maggyero (talk) 03:33, 8 September 2021 (PDT)

"object, bit-field, or function" is correct although incomplete; there are other entities lvalues can refer to that aren't objects or functions (or bit-fields). However, this is just the intro, and needs to bring up only the core points that distinguish the categories: since we have a separate section for bit fields under (cpp/language/value_category#Special_categories), I wouldn't mind shortening that to just "object or function". --Cubbi (talk) 07:29, 8 September 2021 (PDT)
Alright, I thought that the standard was exhaustive i.e. that value categories only applied to expressions denoting or computing objects and functions. If the standard itself is incomplete, I agree that we should not try to complete it here.
Maggyero (talk) 11:12, 8 September 2021 (PDT)

[edit] How about retroactively applying the C++11 taxonomy to C++98 among the cppreference?

I suppose that the C++17 change (P0135R1) actually deserves rev-boxes as it introduced some behavior changes, but not the C++11 taxonomy change (N3055). --Fruderica (talk) 00:14, 30 June 2022 (PDT)