C++ decltype(“Hello”)的结果是什么?
我在所有编译器上都得到了意想不到的结果,我在这些编译器上尝试了以下操作(GCC 4.7.2、GCC 4.8.0测试版、ICC 13.0.1、Clang 3.2、VC10):C++ decltype(“Hello”)的结果是什么?,c++,c++11,string-literals,decltype,C++,C++11,String Literals,Decltype,我在所有编译器上都得到了意想不到的结果,我在这些编译器上尝试了以下操作(GCC 4.7.2、GCC 4.8.0测试版、ICC 13.0.1、Clang 3.2、VC10): #包括 int main() { //这会开火 静态断言( std::值是否相同, “错误!” ); } 我本以为上面的编译时断言不会触发,但它确实触发了。毕竟,这一条没有(如预期的那样): #包括 int main() { char const hello[6]=“hello”; //这不会开火 静态断言( std::值
#包括
int main()
{
//这会开火
静态断言(
std::值是否相同,
“错误!”
);
}
我本以为上面的编译时断言不会触发,但它确实触发了。毕竟,这一条没有(如预期的那样):
#包括
int main()
{
char const hello[6]=“hello”;
//这不会开火
静态断言(
std::值是否相同,
“错误!”
);
}
那么,根据C++11标准(非常感谢参考资料),decltype(“Hello”)的结果是什么呢?我应该将其与什么进行比较,以使上面的编译时断言不会触发?[注意:最初,这不是一个自我回答的问题;我只是在描述我的调查尝试时碰巧找到了答案,我认为分享它会很好。]
根据C++11标准附录C(2.14.5):
字符串文字的类型从“字符数组”更改为“常量字符数组”“[…]
此外,第7.1.6.2/4段规定(关于decltype
的结果):
decltype(e)
表示的类型定义如下:
-如果e
是未加密的id表达式或未加密的类成员访问(5.2.5),decltype(e)
是由e
命名的实体的类型。如果没有这样的实体,或者如果e
命名了一组重载函数,则程序的格式不正确
-否则,如果e
是一个x值,decltype(e)
是T&
,其中T
是e
的类型
-否则,如果e
是左值,decltype(e)
是T&
,其中T
是e
的类型
-否则,decltype(e)
是e
的类型
由于,根据上述段落和附件C中的段落,decltype(“Hello”)
的结果是对大小为6的恒定窄字符数组的左值引用:
#include <type_traits>
int main()
{
// This will NOT fire
static_assert(
std::is_same<decltype("Hello"), char const (&)[6]>::value,
"Error!"
);
}
#包括
int main()
{
//这不会开火
静态断言(
std::值是否相同,
“错误!”
);
}
最后,即使
hello
变量也是一个左值,问题文本中的第二个编译时断言也不会触发,因为hello
是一个未加密的id表达式,这使得它属于上述第7.1.6.2/4段列表的第一项。因此,decltype(hello)
的结果是由hello
命名的实体的类型,即char const[6]
当您考虑编写decltype(expr)&
@KerrekSB:Yes时,这些规则是有意义的。我只是觉得很奇怪,因为我习惯于用“字符串文字具有类型const char[]
,decltype(x)
返回类型x
,所以decltype(“hello”)
应该返回const char[6]
”,忘记了细节。吸取的教训(希望)+1对问题和答案都适用。我保证我不再接触C++编译器。@ AndyProwl,你说你和你列出的各种编译器有不同的结果。如果您能提供您测试的编译器所做的一切,那就太好了。@Valloric:我从所有编译器得到的结果都是相同的,而且都是正确的:断言触发。我只是有一个错误的期望,因为我期望断言不会被触发。这就是我所说的“意外结果”。答案应该是清楚的。
#include <type_traits>
int main()
{
char const hello[6] = "Hello";
// This will not fire
static_assert(
std::is_same<decltype(hello), char const[6]>::value,
"Error!"
);
}
#include <type_traits>
int main()
{
// This will NOT fire
static_assert(
std::is_same<decltype("Hello"), char const (&)[6]>::value,
"Error!"
);
}