Boost logo

Boost Users :

Subject: [Boost-users] [type traits][enable_if] how do I resolve ambiguous class template instantiation?
From: Steve Lorimer (steve.lorimer_at_[hidden])
Date: 2010-07-28 11:39:17


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



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net