Decltype of function call discards const qualifiers

105 Views Asked by At

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.

1

There are 1 best solutions below

1
user17732522 On BEST ANSWER

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.