Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does `const &&` bind to all prvalues (and xvalues)?

The C++ standard defines the following functions deleted;

template <class T>
void ref(const T&&) = delete;

template <class T>
void cref(const T&&) = delete;

This is to aid in ensuring that the functions are not misused by disallowing them from binding to temporary values (rvalues).

  • Does const && bind to all rvalues, specifically prvalues?
  • Would const && bind to all "moved objects" (xvalues; basically something returned from std::move or similar)?

I can reason that it should, but I don't have any "proof" for this.

  • Or conversely, are there cases where an rvalue (prvalue or xvalue) will not bind to const &&?
    • If so, how so?

Note: some clarity from the comments, this question is heavily swayed to classic rvalues, the prvalue value category.

like image 276
Niall Avatar asked Jul 24 '14 20:07

Niall


People also ask

Does const mean constant?

What is const (constant)? Const (constant) in programming is a keyword that defines a variable or pointer as unchangeable. A const may be applied in an object declaration to indicate that the object, unlike a standard variable, does not change.

What does const {} mean in Javascript?

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable—just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.

What does const mean?

1. fixed and invariable; unchanging. 2. continual or continuous; incessant.

What does the const do?

The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it. In C, constant values default to external linkage, so they can appear only in source files.


2 Answers

T const&& can bind to rvalues of type T or const T.

From 8.5.3 [dcl.init.ref] paragraph 5:

5 - A reference to type "cv1 T1" is initialized by an expression of type "cv2 T2" as follows: [...]
— Otherwise, [...] the reference shall be an rvalue reference. [...]
— If the initializer expression
— is an xvalue, class prvalue, array prvalue or function lvalue and "cv1 T1" is reference-compatible with "cv2 T2" [...] then the reference is bound to the value of the initializer expression [...]

If the initializer expression is a prvalue of non-class type, then a temporary copy is created for reference binding (ibid).

Reference-compatibility is defined in 8.5.3p4; it requires a same-or-base-class relationship and same-or-greater cv qualification.

So for an rvalue to bind to T const&&, its cv-qualification must be no greater than const.

like image 126
ecatmur Avatar answered Sep 20 '22 12:09

ecatmur


I want to add some empirical evidence here supporting the answer.

template <class T>
void ref(T&) {}

template <class T>
void ref(volatile T&) {}

template <class T>
void ref(volatile const T&) {}

template <class T>
void ref(const T&) {}

template <class T>
void ref(const T&&) = delete;

// xvalues
int&& ax();
const int&& bx();
volatile int&& cx();
volatile const int&& dx();

// prvalues
int ap();
const int bp();
volatile int cp();
volatile const int dp();

void test()
{
    ref(ax());
    ref(bx());
    ref(cx());
    ref(dx());

    ref(ap());
    ref(bp());
    ref(cp());
    ref(dp());
}

All the calls to ref in this case fail to compile, both xvalues and prvalues with the cv-qualified variations; msvc, gcc and clang all fail the compilation with the appropriate "attempting to reference a deleted function" error.

like image 21
Niall Avatar answered Sep 19 '22 12:09

Niall