Consider a function
template <typename T>
const T&& foo();
When i had tried to tested it,i founded result that I didn't understand. Output is 0.
#include <iostream>
class C{};
template <typename T>
const T&& foo();
int main() {
std::cout << std::is_same_v<decltype(foo<C&&>()), const C&&>;
return 0;
}
Shouldn't decltype preserve const qualifiers? In my opinion, it should be like T-> C&&
, so return type is const C&&
via reference collapsing rules, and decltype of result is const C&&
Also, this line
std::cout << std::is_same_v<decltype(foo<int>()), const int&&> << '\n';
Prints 1 as expected.
Can somebody help me to figure out correct logic of working?
I found that when decltype applied on non-class prvalue, cv qualifiers are discarded. But this is not the case, because value category of foo<int&&>()
is xvalue, and this also doesn't works with class type C
.
Shouldn't decltype preserve const qualifiers?
Yes, and it does here as well. The return type of foo<C&&>()
really is C&&
, not const C&&
.
In my opinion, it should be like T-> C&&, so return type is const C&& via reference collapsing rules, and decltype of result is const C&&
No, you are applying const
to T
first, then &&
afterwards.
const T&&
means "rvalue reference to (const T
)". It doesn't mean "const
(rvalue reference to T
)".
The const
is applied at top-level to T
. That means if T
is C&&
you are trying to const
-qualify a reference, but there are no const
-qualified references in C++. So the language rules say that const
is ignored when trying to const
-qualify a reference through such a construction.
std::cout << std::is_same_v<decltype(foo()), const int&&> << '\n';
Here you are applying const
to int
giving you const int
and then you add &&
on top. So you get const int&&
.
I found that when decltype applied on non-class prvalue, cv qualifiers are discarded.
They are discarded on the non-class type prvalue expression, but not on the return type of the function itself. If a function is declared to return const T
and you substitute int
for T
, then the function has return type const int
, but a call to the function is a prvalue expression of type int
.
But this is not the case, because value category of foo<int&&>() is xvalue, and this also doesn't works with class type C.
Yes, correct. This special rule doesn't matter here. decltype
does faithfully reproduce the declared return type.