Skip to content

Instantly share code, notes, and snippets.

@remyroez
Created July 18, 2014 09:25
Show Gist options
  • Save remyroez/82be4884022a6458ae14 to your computer and use it in GitHub Desktop.
Save remyroez/82be4884022a6458ae14 to your computer and use it in GitHub Desktop.
C++11 の make_shared を拡張する ref: http://qiita.com/remyroez/items/04968f3a2b09f4888f11
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()
#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;
}
#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