考虑一个函数
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
。
1条答案
按热度按时间zpf6vheq1#
decltype不应该保留const限定符吗?
foo<C&&>()
的返回类型实际上是C&&
,而不是const C&&
。在我看来,它应该像T-〉C&&,所以通过引用折叠规则返回类型是const C&&,结果的decltype是const C&&
不,您首先将
const
应用到T
,然后再应用&&
。const T&&
的意思是“rvalue reference to(const T
)",而不是“*const
(rvalue reference toT
)*"。const
在顶层 * 应用于T
。这意味着如果T
是C&&
,则尝试const
-限定引用,但是在C++中没有const
-限定的引用。所以语言规则说当尝试const
-时,const
被忽略。通过这样的结构限定一个参考。std::cout〈〈std::is_same_v〈decltype(foo()),const int&&〉〈〈'\n';
在这里,你将
const
应用到int
上,得到const int
,然后在上面加上&&
,得到const int&&
。我发现当decltype应用于非类纯右值时,cv限定符被丢弃。
如果一个函数声明返回
const T
,而你用int
替换T
,那么这个函数的返回类型是const int
,但是对这个函数的调用是一个int
类型的纯右值表达式。但事实并非如此,因为foo〈int&&〉()的值类别是xvalue,这也不适用于类类型C。
是的,正确。这个特殊的规则在这里并不重要。
decltype
确实忠实地复制了声明的返回类型。