decltype 错误 C2440:无法将 'int *' 转换为 'int *&'。

5
以下是一个人为编造的实际代码示例:
int** Ptr = 0;
decltype(Ptr[0]) Test = (int*)0;

我遇到了以下错误:

错误 C2440:'initializing': 无法从'int *'转换为'int *&'

我不确定为什么会出现这个错误,因为根据我对 decltype 的理解(如果我理解有误,请纠正),它只是接受任何你给予的表达式并将其解析为实际类型。在这种情况下,Ptr[0] 是一个 int*,所以我期望得到:int* Test = (int*)0;

我错过了什么?为什么会出现那个错误?


也许 Ptr[0] 的类型是左值引用,因此尝试用 prvalue 初始化它会失败。 - Weak to Enuma Elish
Ptr[0] 转换为 *(Ptr + 0),并且在上面链接中解释了 *Ptrdecltype - fghj
2个回答

7
如果我们查看草案C++标准的章节7.1.6.2简单类型说明符[dcl.type.simple],并查看其中的情况,对于decltype,它开始说:
对于表达式e,由decltype(e)表示的类型定义如下:
我们可以看到,在这种情况下,表达式不是id-expression也不是类成员访问,这将得到您所期望的结果(强调我的):
如果e是未括号化的id-expression或未括号化的类成员访问(5.2.5),decltype(e)是由e命名的实体的类型。如果没有这样的实体,或者e命名了一组重载函数,则程序是非法的;
但结果是一个左值:
否则,如果e是一个左值,则decltype(e)是T&,其中T是e的类型
这将导致一个引用。

正如M.M所指出的那样,std::remove_reference可以用来获取您想要的结果:

std::remove_reference<decltype(Ptr[0])>::type Test = (int*)0;

正如 T.C. 指出的那样,std::decay 也是一种选择,而且更短:

std::decay<decltype(Ptr[0])>::type Test = (int*)0;

感谢您的回答。我不确定他们实现这种方式的原因,对我来说没有意义。是否有办法(强制转换或其他C++技巧)使decltype(Ptr [0])产生一个int *?(去掉& - vexe
1
@vexe 你可以使用 std::remove_reference - M.M
auto 更短 :) - Barry
decay会去除const限定符,而remove_reference则不会。 - CashCow

3
除了其他答案之外,您也可以使用以下方法:
int ** ptr = 0;
decltype(+ptr[0]) test = (int*)0;
// (+*p) is now an r-value expression of type int, rather than int&

这里使用的一些规则包括:

  • 如果表达式的值类别是lvalue,则decltype产生T&;
  • 如果表达式的值类别是prvalue,则decltype产生T。

还要注意,如果对象的名称被括在圆括号中,则它被视为普通的lvalue表达式,因此decltype(x)和decltype((x))通常是不同的类型。[摘自https://en.cppreference.com/w/cpp/language/decltype]

参见http://www.cplusplus.com/forum/beginner/149331/
更多关于decltype的信息请点击 :https://en.cppreference.com/w/cpp/language/decltype


如果您能解释一下一元运算符 + 如何在 +ptr[0] 中起作用,那么您的答案将会更好。 - Adrian Mole
1
@AdrianMole 好的,已更新。谢谢。希望现在的解释可以了。 - Alex Vask

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接