17

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_FLAG1または5でない限り無視されるコードのブロックが導入され、6より大きい場合は診断が行われます。

#if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ]

この構成は、C++11の新機能です。

4

2 に答える 2

6

意図はこれが機能することであり、左辺値から右辺値への変換が有効である場合を示す段落は、文字列リテラルのサブオブジェクトを参照する左辺値が定数式で初期化された定数整数オブジェクトであるという注記で修正されます(これは、C ++ 11以降のドラフトで許可されているケースの1つとして説明されています)。

プリプロセッサ内での使用についてのあなたのコメントは興味深いように見えますが、それが機能することを意図しているかどうかはわかりません。これについては初めて聞いた。

于 2011-09-15T19:24:45.477 に答える
1

についての質問に関して#ifは、プリプロセッサで使用できる式のセットを増やすことは標準化委員会の意図ではなく、現在の表現は欠陥であると見なされます。これは、KonaWG21以降の郵送でコアイシュー1436としてリストされます。これを私たちの注意を引いてくれてありがとう!

于 2012-02-17T00:07:28.807 に答える