字符串文字可以在常量表达式中下标吗?

时间:2011-09-15 00:40:24

标签: c++ c++11 string-literals constexpr

这是有效的,因为允许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来说是新的。

2 个答案:

答案 0 :(得分:6)

意图是,这是有效的,并且当左值转换的左值有效时的段落将be amended with a note表明引用字符串文字的子对象的左值是一个用a初始化的常量整数对象在后C ++ 11草案中的常量表达式(被描述为允许的情况之一)。

您对预处理器中的使用的评论看起来很有趣,但我不确定这是否有效。我第一次听到这个消息。

答案 1 :(得分:1)

关于#if的问题,标准委员会并不打算增加可用于预处理器的表达式集,而且当前的措辞被认为是一个缺陷。这将在后科纳WG21邮件中列为核心问题1436。感谢您引起我们的注意!