I'm trying to use template specialization and enable_if / type_traits to correctly allocate memory for different types, where the template parameter will be one of:
1. boost::intrusive_ptr<U> // create U on the heap, return intrusive_ptr
2. boost::shared_ptr<U> // create U on the heap, return shared_ptr
3. U* // create U on the heap, return raw pointer
4. U // create U on the stack
I'm pretty sure I'm just doing something stupid, but I'm getting ambiguous conflicts between my template for types of U and the smart pointer types.
Please can you comment on how to fix the code below?
TIA
Steve
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
template<typename U, class Enable = void>
struct alloc;
template<typename U>
struct alloc<U, typename boost::disable_if< boost::is_pointer<U> >::type >
{
U operator()()
{
std::cout << __LINE__ << std::endl;
return U();
}
};
//-----------------------------------------------------
template<typename U>
struct alloc<U, typename boost::enable_if< boost::is_pointer<U> >::type >
{
U operator()()
{
std::cout << __LINE__ << std::endl;
return new U;
}
};
//-----------------------------------------------------
template< typename U >
struct alloc< boost::intrusive_ptr<U> >
{
boost::intrusive_ptr<U> operator()()
{
std::cout << __LINE__ << std::endl;
return boost::intrusive_ptr<U>(new U);
}
};
//-----------------------------------------------------
template<typename U >
struct alloc< boost::shared_ptr<U> >
{
boost::shared_ptr<U> operator()()
{
std::cout << __LINE__ << std::endl;
return boost::shared_ptr<U>(new U);
}
};
//-----------------------------------------------------
template<typename T>
struct test
{
alloc<T> create;
T fun() { return create(); }
};
struct foo
{
uint32_t refs;
foo() : refs() { std::cout << "foo" << std::endl; }
};
inline void intrusive_ptr_add_ref(foo* p) { ++p->refs; }
inline void intrusive_ptr_release(foo* p) { if (!--p->refs) delete p; }
int main()
{
test<int*> a;
int* p = a.fun();
*p = 5;
test<int> b;
int d = b.fun();
d = 5;
test< boost::intrusive_ptr<foo> > c;
boost::intrusive_ptr<foo> z = c.fun();
z.get();
test< boost::shared_ptr<int> > gd;
boost::shared_ptr<int> x = gd.fun();
x.get();
return 0;
}