我从以下所有编译器中得到了意想不到的结果(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!"
);
}
那么根据C ++ 11标准decltype("Hello")
的结果是什么(参考文献受到高度赞赏)?我应该将它与什么进行比较,以便上面的编译时断言不会触发?
答案 0 :(得分:30)
[注意:最初,这并不是一个自我回答的问题;我正好在描述我的调查尝试时碰巧找到了答案,我认为分享它会很好。]
根据C ++ 11标准的附录C(2.14.5):
字符串文字的类型从“char of char”更改为“ const char数组。”[....]
此外,第7.1.6.2/4段规定了(关于decltype
的结果):
decltype(e)
表示的类型定义如下:- 如果
e
是未加密码的id-expression或未加密码的类成员访问(5.2.5),则decltype(e)
是e
命名的实体的类型。如果没有这样的实体,或者e
命名了一组重载函数,那么该程序就是格式不正确的;- 否则,如果
e
是xvalue,则decltype(e)
为T&&
,T
的类型为e
;- 否则,如果
e
是左值,则decltype(e)
为T&
,T
类型为e
;- 否则,
decltype(e)
是e
的类型。
由于 string literals are lvalues ,根据上述段落和附件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
是 notarenthesized id-expression ,这使它落入第7.1.6.2/4段中上述列表的第一项。因此,decltype(hello)
的结果是hello
命名的实体的类型,即char const[6]
。