進捗置き場というわけでもない場所

プログラミングしてる中で見つけたこととか

singletonとfriendのお話

Twitterでちょっと話してたsingletonクラスとfriendのどっちを使うか的な話の自分的まとめ。

どういう話

ユーザー(≠ソフトウェアエンドユーザー)に複数作らせたくないリソースを、singletonパターンで管理するのと、メンバをstatic、関数をfriendに分けるのどっちを使おうか的な話です。
というわけでとりあえず双方の適当なコードを書いてみる。

singleton

class Singleton final {
public:
    static int getA() {
        return a;
    }
    static void setA(int a_) {
        a = a_;
    }

private:
    static int a;

}
int Singleton::a = 5;

int main() {
    Singleton::getA(); //呼び出し
}

friend混ぜ記法

class Hoge final {
public:
    friend int getA() {
        return a;
    }
    friend void setA(int a_) {
        a = a_;
    }

private:
    static int a;

}
int Hoge::a = 5;

int main() {
    getA(); //呼び出し
}

これを見てみると、classの定義では関数定義の最初にstaticがつくかfriendがつくか以外の違いがなさそう。
でもmain内を見てみると、その2つの性質の違いで関数の呼び出し方が変わってる。friendは「特定のclassのメンバを扱える外部関数」なので、呼び出しは普通の関数と同じようにできる。
この違いが意外と大きい。

僕も最初singleton使ってたんだけど、一番の悩みが「staticなメンバを参照したいだけなのに、必ずclassの中に入れる必要があること」だった。
実装の都合上そうなっているだけなのに、ユーザーが関数を呼び出すときにclass名を書く必要があるのってスマートじゃない感あるから的な考え。
そこで最近、実装をfriendにしてみたら、ユーザー側からは全く意識せず、グローバル空間も汚さないようにstaticな変数を参照できるようになった。
それまではfriendなんとなく毛嫌いしてたんだけど、こういう用途ならバンバン使って良さそう。

ただ、やたらめったらfriendを使うのも危ないし、staticメンバ関数はそれはそれで使うべき局面がある気がするのでその辺しっかり使い分けていきたい。終わり。