Created
July 14, 2014 08:45
-
-
Save remyroez/a13facc116345e9ed276 to your computer and use it in GitHub Desktop.
C++11 と unique_ptr でシングルトン ref: http://qiita.com/remyroez/items/fd35e6af8fbbdbdd73c4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main begin | |
1: device() | |
device foo! | |
2: device foo! | |
3: device foo! | |
~device() | |
4: invalid instance. | |
5: device() | |
6: device foo! | |
7: beacon() | |
8: gadget() | |
gadget baz! | |
9: beacon bar! | |
main end | |
~gadget() | |
~beacon() | |
~device() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "singleton.h" | |
#include <stdio.h> | |
// 適当シングルトンクラス1 | |
class device { | |
public: | |
DEFINE_SINGLETON(device); | |
void foo() { printf("device foo!\n"); } | |
~device() { printf("~device()\n"); } | |
private: | |
// コンストラクタは private に | |
device() { printf("device()\n"); } | |
// 一応 Non copyable | |
device(const device &) = delete; | |
device &operator =(const device &) = delete; | |
}; | |
// 適当シングルトンクラス2(名前と出力テキストが違うのみ) | |
class beacon { | |
public: | |
DEFINE_SINGLETON(beacon); | |
void foo() { printf("beacon bar!\n"); } | |
~beacon() { printf("~beacon()\n"); } | |
private: | |
beacon() { printf("beacon()\n"); } | |
beacon(const device &) = delete; | |
beacon &operator =(const device &) = delete; | |
}; | |
// 適当シングルトンクラス3(名前と出力テキストが違うのみ) | |
class gadget { | |
public: | |
DEFINE_SINGLETON(gadget); | |
void foo() { printf("gadget baz!\n"); } | |
~gadget() { printf("~gadget()\n"); } | |
private: | |
gadget() { printf("gadget()\n"); } | |
gadget(const device &) = delete; | |
gadget &operator =(const device &) = delete; | |
}; | |
int main() { | |
printf("main begin\n"); | |
// 初回のインスタンス取得時に、自動でインスタンス化する | |
printf("1: "); | |
device::instance()->foo(); | |
// 明示的に受け取り、所有判定も行う | |
printf("2: "); | |
if (device::singleton p = device::instance()) { | |
p->foo(); | |
} | |
// auto を使うときは明示的に参照にする | |
printf("3: "); | |
if (auto &p = device::instance()) { | |
p->foo(); | |
} | |
// インスタンスを明示的に解放 | |
device::destroy(); | |
// 2回目以降のインスタンス取得時は有効とは限らない | |
printf("4: "); | |
if (device::singleton p = device::instance()) { | |
p->foo(); | |
} else { | |
printf("invalid instance.\n"); | |
} | |
// インスタンスを明示的に作成 | |
printf("5: "); | |
device::create(); | |
// できれば所有判定は行ったほうがよい | |
printf("6: "); | |
if (device::singleton p = device::instance()) { | |
p->foo(); | |
} | |
// 二重に読んでも二重に作成されない | |
printf("7: "); | |
beacon::create(); | |
beacon::create(); | |
printf("8: "); | |
if (gadget::singleton p = gadget::instance()) { | |
p->foo(); | |
} | |
printf("9: "); | |
if (beacon::singleton p = beacon::instance()) { | |
p->foo(); | |
} | |
printf("main end\n"); | |
// 解放順は初回のインスタンス化を行った逆順 | |
// 途中で destroy して create しても変わらない | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// シングルトン定義マクロ | |
// マクロ使用後は public になるので注意 | |
#define DEFINE_SINGLETON(TYPE_)\ | |
private:\ | |
using self_type = TYPE_;\ | |
using unique_ptr = std::unique_ptr<self_type>;\ | |
public:\ | |
using singleton = const unique_ptr &;\ | |
static singleton instance() {\ | |
return ref();\ | |
}\ | |
static void create() {\ | |
if (!ref()) ref() = make_unique();\ | |
}\ | |
static void destroy() {\ | |
ref().reset();\ | |
}\ | |
private:\ | |
template <typename... Args>\ | |
static unique_ptr make_unique(Args&&... args) {\ | |
struct temp : self_type { temp() : self_type() {} };\ | |
return std::move(unique_ptr(new temp(std::forward<Args>(args)...)));\ | |
}\ | |
static unique_ptr &ref() {\ | |
static unique_ptr p = make_unique();\ | |
return p;\ | |
}\ | |
public: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment