What's the meaning of "identity" in the definition of value categories in C++
Asked Answered
B

3

9

In short, you can just answer the part about identity, thanks. My main focus of this question is start from 2. about identity, I just tried to provide context/background of my current understanding so it may help you decide the depth when you're writing your answer.


I want to understand the big picture of type system and value categories in C++. I've searched/read many questions and resources online, but everyone has a distinct explanation, so I'm really confused. I'll list the part I can't grasp, if anyone could provide idea about

  1. On cppreference.com, first line:

    Objects, references, functions including function template specializations, and expressions have a property called type, which both restricts the operations that are permitted for those entities and provides semantic meaning to the otherwise generic sequences of bits.

    my question:

    • What does it mean an expression has a type? Is it the type of the final result after evaluation?
    • I don't want to learn template at current stage, would this hinder learning about the basic part (from you expert's perspective)? It took me some time to realize that forwarding reference and rvalue reference are different thing, which the former is for template.
  2. Value categories:

    I read this answer of - What are rvalues, lvalues, xvalues, glvalues, and prvalues?, the phrase bother me a lot is identity, which also appears on cppreference.com - Value categories (Line 5, glvalue).

    my question: can I say that identity == everything I can assign a new value on it?

    • I saw people using the word address/pointer for it, but is that has identity iff has address/pointer? I want the precise term.
    • I came across the idea of bit-field when reading cppreference.com, it seems like given a bit-field struct a, its bit field a.m has no address? Is this the reason the word identity is used instead of address/pointer?
    • I found a blog post explaining this, but it's lvalue definition is counter-intuitive: an lvalue denotes an object whose resource cannot be reused, why not?
Baltoslavic answered 23/11, 2018 at 8:43 Comment(0)
T
5

The identity is a philosophical concept. It's a property of a thing that makes it unique. No two "things" can have the same identity.

A something that has an identity is an entity.

[basic.lval]:

A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.

A name inside an expression can only designate one object. So a name inside an expression is an identity. It is defined as an lvalue (for example see expr.prim.id.unqual)

At a given address and at given time there can not be 2 objects of the same type (there can be object nested inside each other, ...). So dereferencing a pointer gives an lvalue.

A reference always designates an entity. So every function that returns a reference when called generates a glvalue.

...

An xvalue is a tag, that can only be generated by a cast (or a bound to a temporary materialization). It is a glvalue that denotes an object or bit-field whose resources can be reused basic.lval

The difference between an xvalue and an lvalue is used to produce efficient code. But xvalue as lvalue are glvalue: they bring the identity of an entity.

...

A prvalue is the result of an expression that is not associated to any object. That is the result of a call to a function that has a non reference return type or the result of some built-in operator calls. In c++ an expression is not an entity, so it has no identity.

prvalues may have a result object, which can be a temporary object. A temporary is an entity, it is materialized when needed (when one try to get a reference to it or when a prvalue is discarded).


The type of an expression is clearly defined in [expr.type]:

If an expression initially has the type “reference to T” ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression. [ Note: Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see [basic.life]). — end note  ]

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

An expression cannot have reference type.

Turfy answered 23/11, 2018 at 17:11 Comment(15)
Q1: A name inside an expression can only designate one object. I don't know what's A name? Is that a symbol that I can store (new) value into?Baltoslavic
Q2: For the [expr.prim.id.unqual], Example, Line 5: decltype((x)) y2 = y1;, I thought it's const float so I missed the &. Why & needed?Baltoslavic
Q3: So a name inside an expression is an identity. It is defined as an lvalue: So "expression has a name inside" is defined as an lvalue? Is the converse statement also true?Baltoslavic
@ptr_user7813604 A name is anything sequence of character "word" chacters and "::". No necessearily an object, it can be a function name for example.Turfy
@ptr_user7813604 You really ask tricky question. I am going to learn with you. An identifier is a concept related to the preprocessing phase. A key word is an identifier (A name is not), this concept vanish after the first phases of translation. This is defined here:eel.is/c++draft/lex.pptokenTurfy
@ptr_user7813604 For Q2 I am still on it! it is a tricky case related to lambda capture.Turfy
My original idea is to tell you anything I don't understand when reading your answer, as a feedback so your time answering me is worthy, you're not forced to answer all of them, for my Q2, I haven't learned about lambda expression. (but I just guess from x to (x) it becomes a lambda expression)Baltoslavic
For Q3 indeed the it is unclear. Inside "x+y", "x" is an expression id-expression this id-expression is an lvalue.Turfy
@ptr_user7813604 No a lambda expression is not that... You can keep it for latter.Turfy
OK, let me try again: Every name in a program is an lvalue? Or id-expression == sequence of characters == name is an lvalue.Baltoslavic
@ptr_user7813604 I am ok with question. The fact you are beginner make you ask question that I did not ask myself, I took it for acquired. This is in those "acquired" and "obvious" knowledge that lies the worst of the misconceptions. So I am happy to answer you. I am learning too.Turfy
@ptr_user7813604 Not every names: A name is a use of an identifier, operator-function-id, literal-operator-id, conversion-function-id, or template-id that denotes an entity or label ([stmt.goto], [stmt.label]) (eel.is/c++draft/basic#4)Turfy
@ptr_user7813604 in this last section are the base definitions.Turfy
@ptr_user7813604 As you can see a name can designate a type. But a name that appears as a primary expression cannot be a type.Turfy
Hi, did you remember me? I can fully understand your answer now.Baltoslavic
P
2
  1. The type of an expression is the type its result would have, if and when the expression were evaluated. An expression doesn't have to be evaluated, but all expressions have type. Type is a static property.
  2. There's no precise definition of identity, or an indication of which entities do or do not have identity. It's a muddy concept that is better left alone. Ignore it. Some people say that object identity is its address, but then this concept is useless. Why not just talk about its address then? And what about bit fields? They are objects without addresses, don't they have identity? Others say that lvalues have identity and rvalues don't, but then it's just as redundant.
Parra answered 23/11, 2018 at 9:49 Comment(3)
Why not just talk about its address then? this is what I want to know. So it's kind of a abstract term that beyond C++ itself right? Is that related to category theory?Baltoslavic
No, it doesn't relate to category theory. Not in any obvious way at any rate.Parra
@ptr_user7813604 a reasonable approximation is to imagine fractional addresses, that distinguish individual bits of a char.Dareen
M
1

First of all, if you really want to learn C++'s formalisms/details, you should refer to the standards (or drafts of them); instead of wiki pages (which may or may not be correct; although cppreference is usually quite good). See Where do I find the current C or C++ standard documents?.

Having said that, there is no need to study the C++ standard(s) to use the language. Actually, most developers don't, and for sure, they are not meant to learn C++. They are a formal document, not teaching/learning material. So, if you are just learning C++, buy a good book about it. See The Definitive C++ Book Guide and List instead.


What does it mean an expression has a type? Is it the type of the final result after evaluation?

No, it does not need to be evaluated (i.e. at runtime) to have a type. For instance, sizeof expr has type std::size_t, yet expr is not evaluated.

I don't want to learn template at current stage, would this hinder learning about the basic part (from you expert's perspective)? It took me some time to realize that forwarding reference and rvalue reference are different thing, which the former is for template.

Actually, it is the other way around, if you want to learn C++ for practical uses, you definitely need to learn at least the basics about templates (if only to use the standard library and not be completely lost).

However, you don't need to know, formally, everything about how they work about value types, rvalue references or templates themselves to be able to program.

the phrase bother me a lot is identity

There is no definition for "identity of" in the standard. In C++17, it is used in a few places, like when defining glvalue:

— A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.

But, indeed, you could say "having identity of" means "actually existing somewhere in memory (if requested)". The best you can do to understand this terminology is reading what Stroustrup wrote:

“has identity” – i.e. and address, a pointer, the user can determine whether two copies are identical, etc.

You can also think about it the opposite way: a glvalue (something that has identity) is any expression that is not a prvalue, if that helps.

Mister answered 23/11, 2018 at 9:34 Comment(6)
Telling OP to read the standard as a way to learn C++ is terrible advice. They will have barely any idea what it meansDareen
@Caleth: I have actually said the opposite of that. I can clarify it.Mister
A little question: i.e. and address means &-address?Baltoslavic
@ptr_user7813604 Yes, or better, in terms of std::addressof. You can read about the memory model for more details.Mister
@Acorn: Wow, thank you, I thought it's a typo of "an address" when I was reading the link provided in my post.Baltoslavic
@ptr_user7813604 Ah, I see what you mean. I think it is a typo indeed, Stroustrup seems to be referring to memory addresses in general.Mister

© 2022 - 2024 — McMap. All rights reserved.