1. ホーム
  2. c++

[解決済み] プライベートコンストラクタはいつプライベートコンストラクタでなくなるのか?

2023-01-27 16:28:07

質問

ある型があり、その型のデフォルトコンストラクタをprivateにしたいとします。次のように書きます。

class C {
    C() = default;
};

int main() {
    C c;           // error: C::C() is private within this context (g++)
                   // error: calling a private constructor of class 'C' (clang++)
                   // error C2248: 'C::C' cannot access private member declared in class 'C' (MSVC)
    auto c2 = C(); // error: as above
}

素晴らしい

しかし、その後、コンストラクタは私が思っていたほどプライベートでないことが判明しました。

class C {
    C() = default;
};

int main() {
    C c{};         // OK on all compilers
    auto c2 = C{}; // OK on all compilers
}    

これは非常に驚くべき、予期しない、そして明らかに望ましくない動作であると私には思えます。なぜこれがOKなのでしょうか?

どのように解決するのですか?

C++14 8.4.2/5 [dcl.fct.def.default] にトリックがあります。

... ある関数は ユーザが提供する であり、最初の宣言で明示的にデフォルト化または削除されていない場合は 削除されていない場合は ...

ということは C のデフォルトコンストラクタは実際には ではなく ユーザーによって提供されたものではありません。そのため C はユーザ提供のコンストラクタを持たないため、8.5.1 [dcl.init.aggr]に従い集約されます。

このような場合 アグリゲート は,ユーザが提供するコンストラクタ(12.1),プライベート又はプロテクトされた非静的データメンバ(11)をもたない配列又はクラス(9項)である。 protected non-static data members (第11項)、基底クラス (第10項)、及び仮想関数 (第10.3項) をもたない配列又はクラスです。