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.
Yes, and it does here as well. The return type of
foo<C&&>()really isC&&, notconst C&&.No, you are applying
consttoTfirst, then&&afterwards.const T&&means "rvalue reference to (const T)". It doesn't mean "const(rvalue reference toT)".The
constis applied at top-level toT. That means ifTisC&&you are trying toconst-qualify a reference, but there are noconst-qualified references in C++. So the language rules say thatconstis ignored when trying toconst-qualify a reference through such a construction.Here you are applying
consttointgiving youconst intand then you add&&on top. So you getconst int&&.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 Tand you substituteintforT, then the function has return typeconst int, but a call to the function is a prvalue expression of typeint.Yes, correct. This special rule doesn't matter here.
decltypedoes faithfully reproduce the declared return type.