考虑一个函数
template <typename T>
const T&& foo();
当我尝试测试它时,我发现了我不明白的结果。输出为 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;
}
decltype 不应该保留 const 限定符吗?在我看来,它应该像
T-> C&&
,所以通过引用折叠规则返回类型是const C&&
,结果的decltype是const C&&
另外,这条线
std::cout << std::is_same_v<decltype(foo<int>()), const int&&> << '\n';
按预期打印 1.
有人能帮我找出正确的工作逻辑吗?
我发现当 decltype 应用于非类纯右值时,cv 限定符被丢弃。但事实并非如此,因为
foo<int&&>()
的值类别是xvalue,这也不适用于类类型C
。
不应该 decltype 保留 const 限定符?
是的,这里也是。
foo<C&&>()
的返回类型确实是 C&&
,而不是 const C&&
。
在我看来应该是T->C&&,所以通过引用折叠规则返回类型是const C&&,结果的decltype是const C&&
不,您首先将
const
应用于 T
,然后是 &&
。
const T&&
的意思是“rvalue reference to (const T
)”。它并不意味着“const
(对T
的右值引用)”。
const
应用在顶层 到T
。这意味着如果 T
是 C&&
,您正在尝试对引用进行 const
限定,但在 C++ 中没有 const
限定的引用。所以语言规则说 const
在尝试通过这样的构造 const
-限定引用时被忽略。
std::cout << std::is_same_v
<< '\n';
在这里,您将
const
应用到 int
上,从而得到 const int
,然后在顶部添加 &&
。所以你得到const int&&
.
我发现当 decltype 应用于非类纯右值时,cv 限定符被丢弃。
它们在非类类型纯右值表达式上被丢弃,但在函数本身的返回类型上不被丢弃。如果一个函数被声明为返回
const T
并且您用 int
代替 T
,那么该函数的返回类型为 const int
,但是对该函数的调用是一个类型为 int
. 的纯右值表达式
但事实并非如此,因为 foo
() 的值类别是 xvalue,这也不适用于类类型 C。
对,没错。这条特殊规则在这里无关紧要。
decltype
确实忠实地再现了声明的返回类型。