2017-02-17 5 views
0

次の宣言は、3.8.1では失敗しましたが、テストされた他のコンパイラ(例えば、gcc 6.1、MSVC 2015、clang 3.9.1)ではエラーなくコンパイルされているようです。constexprインスタンス(例: `std :: integral_constant`)の初期化は` = {} `を必要としますか?

constexpr std::integral_constant<int,0> myConstant; 

打ち鳴らす3.8.1が得られます。以下は、試験したすべてのコンパイラで正しくコンパイル

error: default initialization of an object of const type 'const std::integral_constant<int, 0>' without a user-provided default constructor constexpr std::integral_constant<int,0> myConstant;

に対し:ここで何が起こっているか

constexpr std::integral_constant<int,0> myConstant = {}; 

自分のタイプを定義した場合、ユーザーが入力できるようにユーザ提供のデフォルトのctorを書く必要がありますか?={}

答えて

1

constexpr変数を初期化する必要があります。 Typename variablename;という形式の宣言は、variablenameのデフォルト初期化を実行します。

デフォルトのコンストラクタを持たない型は、デフォルトの初期化で未初期化になります。通常それは問題ありません。

ただし、constexpr変数は初期化を許可されていません。したがって、単純なデフォルトのコンストラクタを持つ型の場合は、それらを目に見える形で初期化する必要があります。変数に= {}を実行すると、値が初期化され、オブジェクトがゼロになります。

これは問題とはみなされません。通常= {}の場合でも、constexpr変数を視覚的に初期化する必要があります。そうすれば、あなたがしていることは誰にでも明らかです。

また、デフォルトのコンストラクタを型に追加するだけで、人々が視覚的に初期化することなくその変数を作成できるようにする必要があります。タイプがの場合は、ユーザーが指定したデフォルトのコンストラクターをタイプに追加するだけで、ジョブを実行するにはが必要です。


コンパイラの動作については、それがあります。 3.8.1でのClangの動作は仕様に関して正しいので、他は正しくありません。

+0

'std :: integral_constant'には値の表現がありません(空の構造体です)。あなたの "あなたは常に目に見える形で初期化すべきです"というルールがまだ適用されていますか? –

+0

@RossBencina: "* std :: integral_constantには値の表現がありません*"標準では、すべての 'constexpr'変数は初期化されるはずです。それが価値表現を持っているかどうかは、標準が気にするものではありません。これは 'constexpr'関数で宣言された変数にも当てはまります。 –

+0

この回答は現在、私の質問に「ここでは何が起こっていますか? - 異なるコンパイラ間で動作が異なるのはなぜですか?コンパイラは正しいですか? –

0

https://stackoverflow.com/a/28338265/2013747によると、={}が必要かどうかは、clangとgccが元々異なって実装することを選択した未解決の問題です。 ={}を省略することはCWGが推奨する方向であるように見え、それを反映するようにclang 3.9ポリシーを変更しました。 CWGアクティブ問題#253引用

253はなぜ空にしなければならないか、完全に初期化さconstのオブジェクトが初期化されますか?

[] 8.6の

段落9は[dcl.init]言う:

ないイニシャライザをオブジェクトに指定されていない、オブジェクトが(おそらく> CV修飾)である場合、また、非PODクラス型(またはその配列)の場合、オブジェクトは>デフォルトで初期化されます。オブジェクトがconst修飾型である場合、基本となる> class型は、ユーザーが宣言した既定のコンストラクタを持ちます。それ以外の場合、オブジェクトに>初期化子が指定されていない場合、オブジェクトとそのサブオブジェクト(存在する場合)は不確定な初期値を持ちます。オブジェクトまたはそのサブオブジェクトのいずれかがconst修飾された型のものである場合、プログラムは不正です。

const PODオブジェクトに非静的データメンバーがない場合はどうなりますか? この文言は、[...]

をそのような場合空の初期化を必要とする(強調を加える。)ここでの結論は、古いコンパイラとの互換性、および標準を厳守するために、={}がない限り、使用しなければならないということですユーザーが宣言したデフォルトのctorがあります。

古いclangの動作は、言語仕様の上記の保守的な解釈 に起因します。 CWG 2011年8月の会議決議:8月から

ノート、2011年会議:

暗黙のデフォルトコンストラクタは、すべてのサブオブジェクトを初期化する場合は、初期化子が必要とされるべきでありません。

出典:http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253

私の知る限りでは、この変更はまだC++標準のすべてのバージョンに組み込まれていません。したがって、={}を省略することはおそらくコンパイルを続行し、今後この規格で正式にサポートされる可能性がありますが、現在は公式のISO標準の一部ではありません。

関連する問題