Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is a variable that is about to go out of scope an lvalue or an xvalue? #4882

Closed
geryogam opened this issue Sep 8, 2021 · 6 comments
Closed

Comments

@geryogam
Copy link
Contributor

geryogam commented Sep 8, 2021

When a variable that is about to go out of scope is returned or thrown, its resources can be reused i.e. it can be moved from, as the following C++ program shows:

struct X {
    X() {
        std::cout << "X()\n";
    }
    
    X(X&&) {
        std::cout << "X(X&&)\n";
    }
    
    ~X() {
        std::cout << "~X()\n";
    }
};

X f() {
    X x;
    std::cout << "return\n";
    return x;
}

int main() {
    try {
        X x = f();
        std::cout << "throw\n";
        throw x;
    } catch (...) {
        std::cout << "catch\n";
    }
    return 0;
}

Compilation (we turn off copy/move elision with the flag -fno-elide-constructors), linkage, and execution:

clang++ -std=c++17 -O2 -Wall -pedantic -pthread -fno-elide-constructors\
main.cpp && ./a.out

Output:

X()
return
X(X&&)
~X()
throw
X(X&&)
~X()
catch
~X()

x in the above statements return x; and throw x; denotes an object whose resources can be reused.

In the Working Draft, Standard for Programming Language C++, [basic.lval-1], we have the following definitions for value categories:

  • A glvalue is an expression whose evaluation determines the identity of an object or function.
  • An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).
  • An lvalue is a glvalue that is not an xvalue.

So is x an lvalue or an xvalue?

@tkoeppe
Copy link
Contributor

tkoeppe commented Sep 8, 2021

I'm sorry, but this is not the right venue for the discussion of how C++ works. This issues list is for editorial issues only: https://github.com/cplusplus/draft/wiki/How-to-tell-if-an-issue-is-editorial

@tkoeppe tkoeppe closed this as completed Sep 8, 2021
@jwakely
Copy link
Member

jwakely commented Sep 8, 2021

Stack Overflow would be more appropriate for this question.

@geryogam
Copy link
Contributor Author

geryogam commented Sep 8, 2021

I did actually post the question on Stack Overflow. I eventually posted here because I suspect a conflict in the current C++ standard for the value category of returned or thrown named variables, between:

  • the current definition of xvalues which classifies them as xvalues in [basic.lval/1.3]:

    An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).

  • the current definition of unqualified id-expressions which classifies them as lvalues in [expr.prim.id.unqual/3]:

    The expression is an lvalue if the entity is a function, variable, structured binding, data member, or template parameter object and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.

By the definition of lvalues in [basic.lval/1.4], this is impossible:

An lvalue is a glvalue that is not an xvalue.

@jwakely
Copy link
Member

jwakely commented Sep 9, 2021

[class.copy.elision] allows copy/move elision for lvalues, but it doesn't mean that an eligible lvalue expression is an xvalue. It's still an lvalue, it does not change its value category.

The definition of xvalue does seem unclear though. The ever-growing scope of [class.copy.elision] means that there are more and more lvalues "whose resources can be reused".

@geryogam
Copy link
Contributor Author

geryogam commented Sep 9, 2021

The definition of xvalue does seem unclear though. The ever-growing scope of [class.copy.elision] means that there are more and more lvalues "whose resources can be reused".

Yes that is my point. With the current definitions of value categories, the name of an object can be an lvalue expression (its resources cannot be reused) at some point in the program, and an xvalue expression (its resources can be reused) at some other point. So the value category of a name changes. Is it something that we want? @zygoloid?

@jensmaurer
Copy link
Member

I think the interpretation that a name (i.e. an identifier) somehow changes its value category when looked at it from different angles is wrong. [class.copy.elision] simply wants to say "apply static_cast<T&&>(x) on whatever thing you got for x"; that doesn't mean "x" itself somehow changes its value category.

The problem is that the definition of "xvalue" in [basic.lval] is not really needed for the standard to work; we just need a term of art to refer to certain kinds of expressions. If there is a suggestion for a more hazy definition of "xvalue" in [basic.lval], I'm all ears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants