Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++, what categories (lvalue, rvalue, xvalue, etc.) can expressions that produce temporaries of class type fall into?

Here is some example code:

#include <iostream>

class Foo
{
public:
  explicit Foo(int x) : data(x) {};

  Foo& operator++()
  {
    data += 1;
    return *this;
  }

  void *get_addr()
  {
    return (void*)this;
  }

  friend Foo operator + (const Foo& lhs, const Foo& rhs);
  friend std::ostream& operator << (std::ostream& os, const Foo& f);

private:
  int data;
};

std::ostream& operator << (std::ostream& os, const Foo& f)
{
  return (os << f.data);
}

Foo operator + (const Foo& lhs, const Foo& rhs)
{
  return Foo(lhs.data + rhs.data);
}

void bar(Foo& f)
{
  std::cout << "bar(l-value ref)" << std::endl;
}

void bar(const Foo& f)
{
  std::cout << "bar(const l-value ref)" << std::endl;
}

void bar(Foo&& f)
{
  std::cout << "bar(r-value ref)" << std::endl;
}

int main()
{
  // getting the identity of the object
  std::cout << Foo(5).get_addr() << std::endl;  // Can write &Foo(5)
                                                // by overloading &
  // overload resolution
  bar(Foo(5));                                       // prints r-value ref

  // default copy assignment
  std::cout << (Foo(78) = Foo(86)) << std::endl;     // prints 86

  // mutating operations
  std::cout << (++Foo(5)) << std::endl;              // prints 6

  // more mutating operations
  std::cout << (++(Foo(78) + Foo(86))) << std::endl; // prints 165
  // overload resolution
  bar((Foo(78) + Foo(86)));                          // prints r-value ref
}

Are expressions like Foo(5) prvalues or general rvalues? Does the fact that I can call get_addr() on these expressions mean that they have identity? Or does the fact that I cannot apply the default &-operator (I mean non-overloaded) mean that they do not have identity and are therefore prvalues?

Is it also fair to say that mutability of the produced value via the expression that produced it is orthogonal to this value-classification?

like image 879
CppNoob Avatar asked Dec 21 '13 08:12

CppNoob


People also ask

What is lvalue and rvalue in C?

An lvalue (locator value) represents an object that occupies some identifiable location in memory (i.e. has an address). rvalues are defined by exclusion. Every expression is either an lvalue or an rvalue, so, an rvalue is an expression that does not represent an object occupying some identifiable location in memory.

What is Xvalue?

An xvalue is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime). Example: Certain kinds of expressions involving rvalue references (8.3.

What is lvalue and rvalue reference?

“l-value” refers to a memory location that identifies an object. “r-value” refers to the data value that is stored at some address in memory. References in C++ are nothing but the alternative to the already existing variable.

Which of the following are correct value categories that a C++ expression can have?

Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories: prvalue, xvalue, and lvalue.


1 Answers

Any expression in C++ is either an lvalue or an rvalue. Hence, you're asking for the classifications that are rvalues. For that, inspect the figure showing the tree of classifications, in the C++11 standard §3.10/1.

Expression category taxonomy


For more info (without delving into the standard) see What are rvalues, lvalues, ....


Regarding

“Are expressions like Foo(5) rvalues or prvalue”

a prvalue is necessary an rvalue – for it couldn't very well be an lvalue.

A prvalue “(“pure” rvalue) is an rvalue that is not an xvalue”, and an xvalue is “the result of certain kinds of expressions involving rvalue references” A constructor call does not produce an rvalue reference, hence it's not an xvalue. So the rvalue is a prvalue, a pure rvalue.

like image 119
Cheers and hth. - Alf Avatar answered Oct 21 '22 12:10

Cheers and hth. - Alf