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.