views:

269

answers:

1

The offending code:

template<typename T>
class SharedObject {
 public:
  typedef boost::intrusive_ptr<T> Pointer;
  typedef boost::intrusive_ptr<T const> ConstPointer;
  inline Pointer GetPointer() {
    return Pointer(this); //Ambiguous call here
  }
  inline ConstPointer GetPointer() const {
    return ConstPointer(this);
  }
  ...

and used like this:

template <typename T>
class SomeClass: public SharedObject<SomeClass<T> > {
 public:
  static inline boost::intrusive_ptr<SomeClass<T> > Create() {
    return (new SomeClass)->GetPointer();
  }
};

int main()
{
  auto v = SomeClass<int>::Create();
}

GCC (4.4.1) with boost 1.41 gives this error upon instatiating the first (non-const) version of GetPointer():

error: call of overloaded ‘intrusive_ptr SharedObject<SomeClass<int> >* const)’ is ambiguous
boost/smart_ptr/intrusive_ptr.hpp:118: note: candidates are: boost::intrusive_ptr<T>::intrusive_ptr(boost::intrusive_ptr<T>&&) [with T = SomeClass<int>] <near match>
boost/smart_ptr/intrusive_ptr.hpp:94:  note:                 boost::intrusive_ptr<T>::intrusive_ptr(const boost::intrusive_ptr<T>&) [with T = SomeClass<int>] <near match>
boost/smart_ptr/intrusive_ptr.hpp:70:  note:                 boost::intrusive_ptr<T>::intrusive_ptr(T*, bool) [with T = SomeClass<int>] <near match>

To my less than arcane skills in C++, I can't see why there is any ambiguity at all. The two canditates at lines 188 and 94 takes an existing intrusive_ptr rvalue reference, which SharedObject::this certainly is not. The final candidate however is a perfect match (the bool argument is optional).

Anyone care to enlighten me as to what the problem is?

EDIT+answer: I finally realized that in

  inline Pointer GetPointer() {
    return Pointer(this); //Ambiguous call here
  }

this refers to SharedObject while the Pointer typedef is SomeClass. (Which is pretty much what Butterworth pointed out right away).

  inline Pointer GetPointer() {
    return Pointer(static_cast<C*>(this));
  }

Since I know this to really be SomeClass, inheriting from SharedObject, a static_cast makes the template class go 'round.

+2  A: 

When you say:

typedef boost::intrusive_ptr<T> Pointer;

you are declaring a type which is an intrusive pointer to an int (because T is an int at that point), when the template is instantiated in your code. Your SharedObject class is not an int, so you can't instantiate such an intrusive pointer using this.

Edit: OK, I misunderstood your code, I'll try again. At:

return Pointer(this); //Ambiguous call here

this is a SharedObject , as per the error messages, however the pointer is typedefed to a SomeClass I think.

Your code is incredibly hard to understand - whatever it is you are trying to do, there must be a simpler way. And you seem to be missing a virtual destructor (and maybe a virtual function) in the base class.

anon
Well read. I hadn't seen it. :)
Benoît
I'm not sure I understand your answer. I added a more specific example in the original question. As far as I can see, ShareObject is instantiated with `SomeClass<T>` passed as T, which as far as I understand makes `typedef boost::intrusive_ptr<T> Pointer;` work as intended? Do I fail to understand your answer, or was my initial example too vague?
Thanks for your help. It helped me figure things out.<br><br>And as for my goal, it's actually not as complicated as it looks. I put the full class at http://paste.ubuntu.com/360614/ for reference. (I'm not missing a virtual destructor afaik).
(make that http://paste.ubuntu.com/360622/)