Jun 28, 2024 at 10:46am UTC
1 2 3 4 5 6 7 8
|
template <typename T>
const T&& Test(T&& t) {
return t;
}
......
int i = 0;
int&& irr = std::move(i);
decltype(Test(irr)) t = i;
|
Since there is a `const` in the return type of function `Test`, I think the type of the function call expression `Test(irr)` should also contain a `const`. Concretely, I think `decltype(Test(irr))` should have deduced type `const int &`. But there is no `const`; the type of `t` is just `int&`. Why is `const` gone?
PS, I used
std::is_const<std::remove_reference<decltype(Test(irr))>::type>::value
to check that the return type of `Test(irr)` is not a reference to const.
PS2, I'm using C++17.
Last edited on Jun 28, 2024 at 10:47am UTC
Jun 28, 2024 at 2:21pm UTC
T is
int&.
Question is, what is
const T&& in that case according to the
reference collapsing rules?
I find it difficult to find information about this exact case but the standard has the following example:
1 2 3
|
int i;
typedef int& LRI;
const LRI&& r3 = i; // r3 has the type int&
|
See
https://eel.is/c++draft/dcl.ref#7 for full example and more details.
So I guess this is consistent with
Test(irr) returning
int& but I cannot explain
why the rules are this way.
Last edited on Jun 28, 2024 at 2:56pm UTC
Jun 28, 2024 at 3:13pm UTC
A function that returns an rvalue-reference provides access for moving which means that the caller can take the contents of the referred object and move it to a different object.
Why would you want to return a const rvalue-reference?
Jun 29, 2024 at 6:46am UTC
T is
int& and the function's return type is
T const&&. Substitution produces the type
int& const&&, which is collapsed into
int&. (Be careful not to make the incorrect derivation
const T&& →
const int& && →
const int&.)
We're observing that cv-qualifiers are ignored when applied to a reference type. This happens even when reference collapsing
isn't involved:
1 2 3 4
|
using T = int&;
int x = 0;
T const rx = x; // int& const → int&
rx++; // okay: the declared type of rx is int&
|
The key is that the
const applies to the reference itself and not to the type being referred to.
I believe that if
R is a reference type, it doesn't make sense to distinguish between
R const and
R for two main reasons:
1. References are usually indistinguishable from the thing they refer to. (Reference transparency [expr.type]/1).
2. References are not objects ([basic.types.general]) and can never be modified ("reseated") to refer to something else.
Last edited on Jun 29, 2024 at 6:52am UTC
Jun 29, 2024 at 3:12pm UTC
@Peter87: Thank you for referring me to the relevant Standard. I think this is because reference has no top-level const, so const qualified to reference does not take effect, thus being dropped. Only const qualified to the actual object (say, typedef const int& LRI;) will be preserved. Thank you again for your reply.