36

我从所有尝试过以下操作的编译器(GCC 4.7.2、GCC 4.8.0 beta、ICC 13.0.1、Clang 3.2、VC10)中得到了意想不到的结果:

#include <type_traits>

int main()
{
    // This will fire
    static_assert(
        std::is_same<decltype("Hello"), char const[6]>::value, 
        "Error!"
        );
}

我本来希望上面的编译时断言不会触发,但确实如此。毕竟,这个没有(如预期的那样):

#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!"
        );
}

那么decltype("Hello")根据 C++11 标准的结果是什么(高度赞赏参考)?我应该将它与什么进行比较,以使上面的编译时断言不会触发?

4

1 回答 1

30

[注意:最初,这不是一个自我回答的问题;当我描述我的调查尝试时,我碰巧自己找到了答案,我认为分享它会很好。]

根据 C++11 标准的附件 C (2.14.5):

字符串文字的类型从“char数组”更改为“<strong>const char数组”。[……]

此外,第 7.1.6.2/4 段规定(关于 的结果decltype):

表示的类型decltype(e)定义如下:

— 如果e是无括号的 id 表达式或无括号的类成员访问 (5.2.5),decltype(e)是由 命名的实体的类型e。如果没有这样的实体,或者如果e命名了一组重载函数,则程序是非良构的;

— 否则,如果e是 xvalue,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!"
        );
}

最后,即使hello变量也是左值,问题文本中的第二个编译时断言也不会触发,因为hello它是一个未加括号的 id-expression,这使其属于第 7.1.6.2 段中上述列表的第一项/4。因此, 的结果decltype(hello)就是以 命名的实体的类型hello,即char const[6]

于 2013-02-24T00:17:48.703 回答