看来C++ 11和C++ 14对prvalue的cv限定的处理不同。
C++ 11坚持使用自C++ 98以来一直存在的“经典”方法:根据3.10/4,“非类prvalue始终具有cv不合格的类型”。
C++ 14在3.10/4中包含类似的措词,但作为注释出现:“[注:类和数组prvalue可以具有cv限定的类型;其他prvalue始终具有cv不限定的类型。请参见第5章。尾注]”
在第5条中说:
5/6条目是C++ 14中的新增功能。现在,它使用对引用类型的结果始终使用的相同方法来处理prvalue的cv限定词(请参阅5/5)。
发生这种变化的原因可能是什么? C++ 11及之前拒绝非类prvalues拥有任何cv资格的权利。 C++ 14表示,非类,非数组prvalue可以具有cv限定,但是在进行任何进一步分析之前,这些cv限定将被丢弃。
我的猜测是,有一些新的(对于C++ 14)语言功能,可以在适当的情况下(在进行上述调整之前)以某种方式“查看” prvalue的cv限定词。它们存在吗?如果是的话,这些功能是什么?2
这个问题源自以下上下文:假设一个编译器内部将this
类的隐藏参数X
实现为X *const
类型的变量。由于要求编译器将this
公开为prvalue,因此该const
不会在C++ 11(或更早版本)中导致任何问题,在C++ 11中,标量prvalue永远都不是cv限定的。但是C++ 14呢?如果完全相同的编译器将该this
公开为X *const
类型的prvalue,可能会导致问题吗?
1 5/6与C++ 14中3.10/4中的注释之间似乎存在矛盾,但是注释仍然不是规范性的。我正在使用文本的草稿版本。
2我最初的猜测是decltype
。我什至以为我在尝试时找到了答案
std::cout << std::is_same<decltype((const int) 0), const int>::value << std::endl;
在GCC中,输出
1
。但是,看到Clang和VC++输出0
(并且decltype
的规范似乎不支持此行为),我倾向于认为这只是GCC中的错误(从6.1开始) 最佳答案
根据commit on github,这样做是为了解决CWG1261: Explicit handling of cv-qualification with non-class prvalues
根据对该问题的评论,看来this
(通常是 prvalue )的类型类别中存在令人惊讶的变化空间,并且gcc formerly和MSVC当前使用了 const lvalue 。
该措辞使这个漏洞更加明确,例如,即使this
通过某种编译器内部魔术方法是X* const
类型的prvalue,在进行任何进一步分析之前,它都已调整为X*
。
同样,您给出的示例确实看起来像是gcc错误。可能decltype
在应用c样式强制转换之前没有查看值类型。
现在在[basic.lval]/4中成为注释的原因是,它现在是[expr]/6中新文本的结果,而不是在[basic.lval]/4中指定规则。
完全感谢T.C.在问题注释中基本回答了此问题,包括对gcc错误修复的引用,以及先前对于cv限定的非类非数组prvalue行为未指定的其他各种示例。