8

次の C++11 プログラムと、GCC 4.7.2 での結果を考えてみましょう。

int main()
{
   constexpr int i = 0;
   int* p = i;
}

// g++ -g -ggdb -Wall -Wextra -pedantic -std=c++11 t.cpp
// t.cpp: In function 'int main()':
// t.cpp:4:13: error: invalid conversion from 'int' to 'int*' [-fpermissive]
// t.cpp:4:9: warning: unused variable 'p' [-Wunused-variable]

標準によると:

[C++11: 4.10/1]:null ポインター定数は、0 に評価される整数型の整数定数式 (5.19) prvalue です [..]

5.19 はめちゃくちゃで、完全に解析できませんでしたが、iこの基準を満たし、ヌル ポインター定数int*として機能することを期待しないので、初期化のために明示的な変換を必要としませんpか?

ではなくI s/constexpr/const/and でコンパイルすると、コンパイルは成功します。-ansi-std=c++11

4

1 に答える 1

8

[C++11: 5.19/3]:リテラル定数式は、リテラル型のprvalueコア定数式ですが、ポインター型ではありません。整数定数式は、整数型またはスコープなしの列挙型のリテラル定数式です。[..]

と:

[C++11: 3.9/10]: 次の場合、型はリテラル型です。

  • スカラー型; また
  • 参照型。また
  • 次のすべてのプロパティを持つクラスタイプ(第9節):[..]
  • リテラル型の配列。

この時点では、そのコードが非準拠である理由を見つけることができないため、GCCのバグが疑われます。

ただし、4.10から引用した箇所を変更することが提案されていることを考えると(アクティブな問題#903)、これは実際には非準拠のコードになるため、意図的なバグである可能性があります。


Iとではなくでs/constexpr/const/コンパイルすると、コンパイルは成功します。-ansi-std=c++11

積分定数式の定義により、C++03ではこのケースが明示的に許可されました。

[C++03: 5.19/1]:[..]積分定数式には、リテラル(2.13)、列挙子、定数式(8.5)で初期化された積分型または列挙型の定数変数または静的データ・メンバー、積分型または列挙型の非型テンプレート・パラメーター、およびsizeof式。[..]

于 2012-11-21T12:33:57.737 に答える