Created
July 18, 2014 09:25
-
-
Save remyroez/82be4884022a6458ae14 to your computer and use it in GitHub Desktop.
C++11 の make_shared を拡張する ref: http://qiita.com/remyroez/items/04968f3a2b09f4888f11
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
0: foo() shared f() ~foo() | |
1: foo(1234) shared f() ~foo() | |
2: foo(456) shared custom_deleter f() ~foo() | |
3: foo(789) shared custom_full f() ~foo() | |
4: foo() unique f() ~foo() | |
5: foo(bar) unique f() ~foo() | |
6: *** error *** | |
7: foo(42) unique custom_deleter f() ~foo() |
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 <stdio.h> | |
#include <string> | |
#include "sub_memory.hpp" | |
// ctor が公開されていない適当なクラス | |
class foo { | |
public: | |
~foo() { printf("~foo()\n"); } | |
void f() { printf("f() "); } | |
protected: | |
foo() { printf("foo() "); } | |
foo(int i) { printf("foo(%d) ", i); } | |
foo(std::string &str) { | |
printf("foo(%s) ", str.empty() ? "*empty*" : str.c_str()); | |
} | |
}; | |
int main() { | |
// ctor が公開されていないので直接インスタンス化はできない | |
#if 0 | |
foo a; | |
foo *p = new foo(); | |
#endif | |
// make_shared + 引数なし | |
printf("0: "); | |
if (auto it = sub::make_shared<foo>()) { | |
printf("shared "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_shared + 引数あり | |
printf("1: "); | |
if (auto it = sub::make_shared<foo>(1234)) { | |
printf("shared "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_shared + 引数あり + カスタムデリータ | |
printf("2: "); | |
if (auto it = sub::make_shared<foo>(sub::custom_deleter(), std::default_delete<foo>(), 456)) { | |
printf("shared custom_deleter "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_shared + 引数あり + カスタムデリータ + カスタムアロケータ | |
printf("3: "); | |
if (auto it = sub::make_shared<foo>(sub::custom_full(), std::default_delete<foo>(), std::allocator<void>(), 789)) { | |
printf("shared custom_full "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_unique + 引数なし | |
printf("4: "); | |
if (auto it = sub::make_unique<foo>()) { | |
printf("unique "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_unique + 引数あり(参照) | |
printf("5: "); | |
std::string str("bar"); | |
if (auto it = sub::make_unique<foo>(str)) { | |
printf("unique "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_unique + 引数あり(コピー) | |
printf("6: "); | |
#if 0 | |
// コピー渡し ctor が用意されていないのでコンパイルエラー | |
if (auto it = sub::make_unique<foo>(std::string("baz"))) { | |
printf("unique "); | |
it->f(); | |
#else | |
if (false) { | |
#endif | |
} else { | |
printf("*** error ***\n"); | |
} | |
// make_unique + 引数あり + カスタムデリータ | |
printf("7: "); | |
if (auto it = sub::make_unique<foo>(sub::custom_deleter(), std::default_delete<foo>(), 42)) { | |
printf("unique custom_deleter "); | |
it->f(); | |
} else { | |
printf("*** error ***\n"); | |
} | |
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
#ifndef SUB_MEMORY_HPP_ | |
#define SUB_MEOMRY_HPP_ | |
#include <memory> | |
namespace sub { | |
namespace { | |
// ctor を public にするためだけの継承クラス | |
template <class T> | |
struct _derived : public T { | |
template <typename... Args> | |
_derived(Args&&... args) : T(std::forward<Args>(args)...) {} | |
}; | |
} // namespace | |
// カスタムデリータ使用タグ | |
struct custom_deleter {}; | |
// カスタムデリータ、アロケータ使用タグ | |
struct custom_full {}; | |
// make_shared 拡張版 カスタムデリータ指定 | |
template <class T, class Deleter, typename... Args> | |
std::shared_ptr<T> make_shared(custom_deleter, Deleter d, Args&&... args) { | |
return std::move(std::shared_ptr<T>(new _derived<T>(std::forward<Args>(args)...), d)); | |
} | |
// make_shared 拡張版 カスタムデリータ、アロケータ指定 | |
template <class T, class Deleter, class Alloc, typename... Args> | |
std::shared_ptr<T> make_shared(custom_full, Deleter d, Alloc a, Args&&... args) { | |
return std::move(std::shared_ptr<T>(new _derived<T>(std::forward<Args>(args)...), d, a)); | |
} | |
// make_shared 拡張版 | |
template <class T, typename... Args> | |
std::shared_ptr<T> make_shared(Args&&... args) { | |
return std::move(std::make_shared<_derived<T>>(std::forward<Args>(args)...)); | |
} | |
// make_unique(C++14) 拡張版 カスタム | |
template <class T, class Deleter, typename... Args> | |
std::unique_ptr<T> make_unique(custom_deleter, Deleter d, Args&&... args) { | |
return std::move(std::unique_ptr<T>(new _derived<T>(std::forward<Args>(args)...), d)); | |
} | |
// make_unique(C++14) 拡張版 | |
template <class T, typename... Args> | |
std::unique_ptr<T> make_unique(Args&&... args) { | |
return std::move(std::unique_ptr<T>(new _derived<T>(std::forward<Args>(args)...))); | |
} | |
} // namespace sub | |
#endif // SUB_MEMORY_HPP_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment