C++ もっとシンプルに使えるシングルトンクラス

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
inemaru
記事: 108
登録日時: 3年前

C++ もっとシンプルに使えるシングルトンクラス

#1

投稿記事 by inemaru » 2年前

お世話になります。

デザインパターンのシングルトンをC++で実装/使用する際
friendが出てくるのが少し煩わしいと感じて、質問することにしました。

シングルトンパターンの実装として、下記サイトのコードを使用しています。
これでほぼ完璧! C++シングルトン基底クラスの決定版!

サイトの方法では、シングルトンクラスを継承してクラスを定義する際
定義するクラス内でfriendを指定する必要がありますが、
friendを書かずに実現する方法は、ないでしょうか?

書き忘れた場合でも、コンパイル時に気が付けますが
書かなくても実現できるのであれば、書かない方法を使いたいです。

宜しくお願い致します。

アバター
usao
記事: 1541
登録日時: 6年前

Re: C++ もっとシンプルに使えるシングルトンクラス

#2

投稿記事 by usao » 2年前

オフトピック
素人の私には
Singleton<T>に書いている事柄を Hoge にダイレクトに書けばいいだけの話に見える…
この話に継承を用いる利点わからないです.

inemaru
記事: 108
登録日時: 3年前

Re: C++ もっとシンプルに使えるシングルトンクラス

#3

投稿記事 by inemaru » 2年前

継承を使用しているのは、
シングルトンの機能を再利用するためです。

プロジェクト内で、複数のクラスに対して
個別にシングルトンを実装していく手間を省きたい意図です。

結城紬
記事: 42
登録日時: 2年前

Re: C++ もっとシンプルに使えるシングルトンクラス

#4

投稿記事 by 結城紬 » 2年前

解決方法ではないのですが、
そもそもそのサイトのコードで、 friend を書くというのは、コンストラクタを private 指定することと1セットにして初めて意味があることです。
派生クラスのコンストラクタを private にする事を強制する方法が存在しないのであれば、(基底クラスを指定するだけ、という方法で)これ以上シンプルにするのは難しいのではないかなと思いますが、どうでしょうか。

結城紬
記事: 42
登録日時: 2年前

Re: C++ もっとシンプルに使えるシングルトンクラス

#5

投稿記事 by 結城紬 » 2年前

シンプルにする別の方向性として、CRTP を使わない(Singleton を基底にしない)のであれば書き忘れは防げるのではないかと思いました。
friend は残りますが、 Hoge がシングルトンであることは1回しか書かなくて済みます。
これだと、 createInstance がカスタムできない弱点がありますが…。

コード:

#include <memory>

class StaticOnly {
  StaticOnly() = delete;
  StaticOnly(const StaticOnly &) = delete;
  StaticOnly &operator=(const StaticOnly &) = delete;
  StaticOnly(StaticOnly &&) = delete;
  StaticOnly &operator=(StaticOnly &&) = delete;
};
template <class T> using singleton_pointer_type = std::unique_ptr<T>;
template <class T> T &singleton();
template <class T> class SingletonSpy : public StaticOnly {
  friend T &singleton<T>();
  static T *createInstance() { return new T(); }
  static T &getReference(const singleton_pointer_type<T> &ptr) { return *ptr; }
};
template <class T> T &singleton() {
  static singleton_pointer_type<T> s(SingletonSpy<T>::createInstance());
  return SingletonSpy<T>::getReference(s);
}

class Hoge {
  friend SingletonSpy<Hoge>;
  Hoge() {}

public:
  void func() { puts("hoge"); }
};

int main() {
  auto &hoge = singleton<Hoge>();
  hoge.func();
  //Hoge a; // compile error
  //SingletonSpy<Hoge> b; // compile error
  return 0;
}

inemaru
記事: 108
登録日時: 3年前

Re: C++ もっとシンプルに使えるシングルトンクラス

#6

投稿記事 by inemaru » 2年前

結城紬さん、回答ありがとうございます!

実装例まで、あげていただき非常にわかりやすかったです。
使用側でシングルトンの記述を最小限に抑えたかったので、
ご提示いただいた方法で、十分でした。

おかげさまで、かなりシンプルに書けるようになりました。
ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る