LoginSignup
0
1

privateコンストラクタをmake_sharedする

Posted at

そのままではprivateなコンストラクタをmake_sharedで利用できないので内部クラスを利用する。

#include <memory>

class Hoge {
 public:
  static std::shared_ptr<Hoge> Create() {
    return std::make_shared<CreateHelper>(1, 2);
  }
  static std::shared_ptr<Hoge> Create(int x, int y) {
    return std::make_shared<CreateHelper>(x, y);
  }

 private:
  // privateコンストラクタを呼び出すためのヘルパクラスとそのエイリアス
  template<class T>
  struct Impl : T {
    template<class... ARGS>
    explicit Impl(ARGS&&... args)
        : T(std::forward<ARGS>(args)...) { /* ignore */ }
  };
  using CreateHelper = Impl<Hoge>;
  
  int x_, y_;
  Hoge(int x, int y) : x_(x), y_(y) { /* ignore */ }
}

説明

まず

  • std::make_sharedprivate内部クラスを構築可能
  • 内部クラス(子クラス)は親クラスのprivateメンバにアクセス可能

そこで

  1. コンストラクタを呼び出すために親クラスを継承したprivate内部クラスを作成
  2. privateエイリアスを作成
  3. std::make_sharedで利用
  4. 暗黙的アップキャストによって親クラスのポインタとして使用

という流れ。

1.について、内部クラスの継承先をテンプレートにすることで、親クラスHogeの継承を可能にしている。また、コンストラクタの引数をテンプレートにすることで、定義の手間を省いている。

2.について、直接内部クラスを呼び出すと、std::make_shared<CreateHelper<Hoge>>となり、複数の関数から呼び出すという状況では保守性やコードの移植性が問題になるのでusingを使ってstd::make_shared<CreateHelper>の形式で呼び出せるようにしている。

参考記事

https://gintenlabo.hatenablog.com/entry/20131211/1386771626
https://qiita.com/ToshiManaPlus1/items/b98e50fa3af771fd0d60

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1