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