这是有效的,因为允许constexpr
表达式取值为“文字类型的glvalue,引用constexpr定义的非易失性对象,或引用此类的子对象一个对象“(§5.19/ 2):
constexpr char str[] = "hello, world";
constexpr char e = str[1];
但是,似乎字符串文字不符合此描述:
constexpr char e = "hello, world"[1]; // error: literal is not constexpr
2.14.5 / 8描述了字符串文字的类型:
普通字符串文字和UTF-8字符串文字也称为窄字符串文字。窄字符串文字的类型为“n const char数组”,其中n是下面定义的字符串大小,并且具有静态存储持续时间。
似乎这种类型的对象可以被索引,只要它是临时的而不是静态存储持续时间(5.19 / 2,就在上面的代码片段之后):
[
constexpr
允许lvalue-to-rvalue转换] ...一个文字类型的glvalue,引用一个非易失性临时对象,其生命周期尚未结束,用常量表达式初始化
这一点特别奇怪,因为取一个临时物体的左值通常是“作弊”。我想这个规则适用于引用类型的函数参数,例如
constexpr char get_1( char const (&str)[ 6 ] )
{ return str[ 1 ]; }
constexpr char i = get_1( { 'y', 'i', 'k', 'e', 's', '\0' } ); // OK
constexpr char e = get_1( "hello" ); // error: string literal not temporary
对于它的价值,GCC 4.7接受get_1( "hello" )
,但拒绝"hello"[1]
,因为“._0'的值在常量表达式中不可用”...... "hello"[1]
可以作为案例标签或数组绑定。
我在这里拆分一些Standardese头发......分析是否正确,是否有一些设计意图?
编辑:哦......这有一些动力。似乎这种表达式是在预处理器中使用查找表的唯一方法。例如,这会引入一个代码块,除非SOME_INTEGER_FLAG
为1或5,否则将被忽略,如果大于6,则会导致诊断:
#if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ]
这个结构对C ++ 11来说是新的。
答案 0 :(得分:6)
意图是,这是有效的,并且当左值转换的左值有效时的段落将be amended with a note表明引用字符串文字的子对象的左值是一个用a初始化的常量整数对象在后C ++ 11草案中的常量表达式(被描述为允许的情况之一)。
您对预处理器中的使用的评论看起来很有趣,但我不确定这是否有效。我第一次听到这个消息。
答案 1 :(得分:1)
关于#if
的问题,标准委员会并不打算增加可用于预处理器的表达式集,而且当前的措辞被认为是一个缺陷。这将在后科纳WG21邮件中列为核心问题1436。感谢您引起我们的注意!