C++ decltype(“Hello”)的结果是什么?

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::值

我在所有编译器上都得到了意想不到的结果,我在这些编译器上尝试了以下操作(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::值是否相同,
“错误!”
);
}
那么,根据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!"
        );
}