[解決済み] 非静的データメンバのクラス内初期化とネストしたクラスコンストラクタの使用時のエラー
質問
以下のコードは非常に些細なもので、うまくコンパイルできるものと思っていました。
struct A
{
struct B
{
int i = 0;
};
B b;
A(const B& _b = B())
: b(_b)
{}
};
このコードをg++のバージョン4.7.2, 4.8.1, clang++ 3.2, 3.3を使ってテストしてみました。g++ 4.7.2がこのコードでセグメンテーションを行うという事実を除けば ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770 ) を除いて、他のテストされたコンパイラーはあまり説明のないエラーメッセージを出します。
g++ 4.8.1:
test.cpp: In constructor ‘constexpr A::B::B()’:
test.cpp:3:12: error: constructor required before non-static data member for ‘A::B::i’ has been parsed
struct B
^
test.cpp: At global scope:
test.cpp:11:23: note: synthesized method ‘constexpr A::B::B()’ first required here
A(const B& _b = B())
^
clang++ 3.2および3.3。
test.cpp:11:21: error: defaulted default constructor of 'B' cannot be used by non-static data member initializer which appears before end of class definition
A(const B& _b = B())
^
このコードをコンパイル可能にすることは可能で、何の違いもないように思われます。2つのオプションがあります。
struct B
{
int i = 0;
B(){} // using B()=default; works only for clang++
};
または
struct B
{
int i;
B() : i(0) {} // classic c++98 initialization
};
このコードは本当に間違っているのでしょうか、それともコンパイラが間違っているのでしょうか?
どのように解決するのですか?
このコードは本当に間違っているのでしょうか、それともコンパイラが間違っているのでしょうか?
まあ、どちらでもありません。この規格には欠陥があります。
A
のイニシャライザーをパースしている間は、完全であると見なされます。
B::i
のイニシャライザーをパースしている間は完了とみなされ、その
B::B()
(のイニシャライザを使用する)。
B::i
のイニシャライザーを使用します) は
A
. これは明らかに循環的です。これを考えてみましょう。
struct A {
struct B {
int i = (A(), 0);
};
A() noexcept(!noexcept(B()));
};
これには矛盾があります。
B::B()
は暗黙のうちに
noexcept
とすれば
A()
は投げない、そして
A()
は投げません。
B::B()
は
ではない
noexcept
. この他にも様々なサイクルや矛盾があります。
これは、コア・イシューによって追跡されます 1360 および 1397 . 特に core issue 1397 のこのメモに注意してください。
おそらく、これに対処する最も良い方法は、非静的データメンバーイニシャライザーがそのクラスのデフォルトのコンストラクタを使用することを不正にすることでしょう。
これは、私がこの問題を解決するためにClangに実装したルールの特殊なケースです。Clang のルールは、クラスのデフォルトのコンストラクタは、そのクラスの非静的データ メンバ イニシャライザが解析される前に使用することはできない、というものです。したがって、Clang はここで診断を発行します。
A(const B& _b = B())
^
... なぜなら Clang はデフォルトの初期化子を解析する前にデフォルトの引数を解析し、このデフォルトの引数には
B
のデフォルト初期化子がすでにパースされている必要があるからです(暗黙のうちに
B::B()
).
関連
-
[解決済み] エラー: '...'のメンバー '...'が非クラス型である場合のリクエスト
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】静的定数文字列(クラスメンバ)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】Enterキーを押して続行する
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる