[type traits][enable_if] how do I resolve ambiguous class template instantiation?

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; }

On Wed, 28 Jul 2010, Steve Lorimer wrote:
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?
Does this require enable_if? Unless you have objects that inherit from intrusive_ptr or shared_ptr that you want to catch, something like: template <typename T> struct alloc { /* stack */ }; template <typename T> struct alloc<T*> { /* raw pointer */ }; template <typename T> struct alloc<shared_ptr<T> > { /* shared_ptr */ }; template <typename T> struct alloc<intrusive_ptr<T> > { /* intrusive_ptr */ }; is likely to be enough. Or are you going to expand to more cases later than cannot be handled by simple specializations? -- Jeremiah Willcock
participants (2)
-
Jeremiah Willcock
-
Steve Lorimer