Skip to content

Instantly share code, notes, and snippets.

@ignisan
Last active August 29, 2015 13:55
Show Gist options
  • Save ignisan/8710717 to your computer and use it in GitHub Desktop.
Save ignisan/8710717 to your computer and use it in GitHub Desktop.
cocos2d::Objectを継承しているとintrusive_ptrになる。そうでない場合はshared_ptrになる。
#pragma once
#include<memory>
#include<type_traits>
#include"cocos2d.h"
#include"IsBaseOf.hpp"
static void intrusive_ptr_add_ref(cocos2d::Object* p) {
p->retain();
// std::cout << "retain:" << p << "," << p->getReferenceCount() << std::endl;
}
static void intrusive_ptr_release(cocos2d::Object* p) {
p->release();
// std::cout << "release:" << p << "," << p->getReferenceCount() << std::endl;
}
#include<boost/intrusive_ptr.hpp>
namespace ignis {
namespace detail {
template<typename T,bool>
struct cocosptr {
typedef boost::intrusive_ptr<T> type;
} ;
template<typename T>
struct cocosptr<T,false> {
typedef std::shared_ptr<T> type;
};
template<typename T, typename... Types>
typename cocosptr<T,true>::type
make_cocosptr(std::true_type, Types... args) {
return typename cocosptr<T,true>::type(new T(args...), false);
}
template<typename T, typename... Types>
typename cocosptr<T,false>::type
make_cocosptr(std::false_type, Types... args) {
return std::make_shared<T>(args...);
}
}
template<typename T>
using cocosptr = typename detail::cocosptr<T,IsBaseOf<cocos2d::Object,T>::value>::type;
template<typename T, typename... Types>
cocosptr<T> make_cocosptr(Types... args) {
using integral_type = typename IsBaseOf<cocos2d::Object,T>::type;
return detail::make_cocosptr<T>(integral_type(),args...);
}
namespace detail {
template<typename T>
typename cocosptr<T,true>::type // intrusive_ptr
convert_from(std::true_type, T* ptr) {
if(cocos2d::PoolManager::getInstance()->getCurrentPool()->contains(ptr)) {
return typename cocosptr<T,true>::type(ptr, true);
}
else {
return typename cocosptr<T,true>::type(ptr, true);
}
}
template<typename T>
typename cocosptr<T,false>::type // shared_ptr
convert_from(std::false_type, T* ptr) {
return typename cocosptr<T,false>::type(ptr);
}
}
template<typename T>
cocosptr<T> convert_from(T* ptr) {
using integral_type = typename IsBaseOf<cocos2d::Object,T>::type;
return detail::convert_from(integral_type(), ptr);
}
template<typename T, typename... Types>
cocosptr<T> create(Types... args) {
return convert_from(T::create(args...));
}
}
/*
class CocosClass : public cocos2d::Object {
public:
ignis::cocosptr<CocosClass> func()
{
auto p = ignis::cocosptr<CocosClass>(new CocosClass,false);
return p;
}
CocosClass()
{
CCLOG("new CocosClass, %d",getReferenceCount());
}
~CocosClass()
{
CCLOG("delete CocosClass, %d",getReferenceCount());
}
};
class SomeClass {
public:
SomeClass() {
CCLOG("new SomeClass");
}
~SomeClass() {
CCLOG("delete SomeClass");
}
};
void func() {
auto p = ignis::cocosptr<SomeClass>(new SomeClass);
p = ignis::make_cocosptr<SomeClass>();
auto cocos_p = ignis::cocosptr<CocosClass>(new CocosClass,false);
cocos_p = ignis::make_cocosptr<CocosClass>();
}
*/
#pragma once
#include<type_traits>
namespace ignis {
namespace detail {
// ref) http://stackoverflow.com/questions/2910979/how-is-base-of-works
template<typename Base, typename Derived>
struct is_base_of_helper {
operator Base*() const;
operator Derived*();
};
template<typename Base, typename Derived>
struct is_base_of_check {
private:
typedef char (&yes)[1];
typedef char (&no)[2];
template<typename T>
static yes check(Derived*, T);
static no check(Base*, int);
public:
static const bool value =
sizeof(check(is_base_of_helper<Base,Derived>(), int()))==sizeof(yes);
};
template<typename Type>
struct is_base_of_check<Type,Type> {
static const bool value = true;
};
} // detail namespace
template<typename Base,typename Derived>
struct IsBaseOf :
std::integral_constant<bool,
detail::is_base_of_check<
typename std::remove_cv<Base>::type,
typename std::remove_cv<Derived>::type>::value>
{ };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment