C ++ 17に移行しようとすると、奇妙な問題が発生しました。問題は、C ++ 17で何か(そして何がわからないか)が変更され、デフォルトのコンストラクターの場合にリストの初期化の動作が異なることです。https://en.cppreference.com/w/cpp/language/list_initializationで詳細を検索しようとしましたが、関連性のあるものは見つかりませんでした。
以下のコードがC ++ 14でコンパイルされるが、B{}
代わりに呼び出すときにC ++ 17でコンパイルされない理由を誰かが知っていますかB()
?(gcc8.2と7.3およびicc19の両方で試しました)
struct A{
protected:
A() {}
};
struct B : public A {};
B f(){
return B(); //compilation OK
//return B{}; //compilation error
}
集合体は、ユーザー提供のコンストラクター([class.ctor])、プライベートまたは保護された非静的データメンバー(Clause [class.access])、基本クラス(Clause [class.access])を含まない配列またはクラス(Clause [class])です。句[class。派生])、および仮想関数なし([class.virtual])。
したがって、B
は集合体ではありません。その結果、B{}
確実に集約初期設定ではなく、B{}
とB()
同じことを意味してしまいます。どちらも、B
のデフォルトコンストラクタを呼び出すだけです。
ただし、C ++ 17では、集計の定義が次のように変更されました。
骨材は、アレイまたはクラスであります
- ユーザー提供、明示的、または継承されたコンストラクター([class.ctor])はありません。
- プライベートまたは保護された非静的データメンバーがない([class.access]節)、
- 仮想関数なし、および
- 仮想、プライベート、または保護された基本クラス([class.mi])はありません。
[注:集計の初期化では、保護されたプライベート基本クラスのメンバーまたはコンストラクターにアクセスできません。 —エンドノート]
制限はもはやオンになっていない任意のちょうど仮想/プライベート/保護されたもので、基底クラス。しかしB
、パブリックベースクラスがあります。集合体になりました!また、C ++ 17集約初期化では、基本クラスのサブオブジェクトを初期化できます。
特に、B{}
サブオブジェクトの初期化子を提供しない集約初期化です。しかし、最初の(そして唯一の)サブオブジェクトは、A
初期化しようとしているからです{}
(集計の初期化中に、明示的な初期化子のないサブオブジェクトはからコピー初期化されます{}
)。これは、A
コンストラクターが保護されているため実行できません。私たちは友達ではありません(引用されたメモも参照してください)。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加