constexpr
式は「constexprで定義された不揮発性オブジェクトを参照する、またはそのようなオブジェクトのサブオブジェクトを参照するリテラル型のglvalue」(§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文字列リテラルは、ナロー文字列リテラルとも呼ばれます。狭い文字列リテラルの型は「arrayofnconst char」です。ここで、nは以下に定義する文字列のサイズであり、静的な保存期間があります。
このタイプのオブジェクトは、一時的なものであり、静的な保存期間(5.19 / 2、上記のスニペットの直後)ではない場合にのみ、インデックスを作成できるように思われます。
[
constexpr
左辺値から右辺値への変換を許可]…定数式で初期化された、存続期間が終了していない不揮発性一時オブジェクトを参照するリテラル型の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は、その価値については受け入れますが、「'._0'の値は定数式では使用できない」ためget_1( "hello" )
拒否します…それでも、ケースラベルまたは配列バインドとして受け入れられます。"hello"[1]
"hello"[1]
ここでいくつかの標準的なヘアを分割しています…分析は正しいですか、そしてこの機能の設計意図はありましたか?
編集:ああ…これにはいくつかの動機があります。この種の式は、プリプロセッサでルックアップテーブルを使用する唯一の方法のようです。たとえば、これにより、SOME_INTEGER_FLAG
1または5でない限り無視されるコードのブロックが導入され、6より大きい場合は診断が行われます。
#if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ]
この構成は、C++11の新機能です。