views:

161

answers:

4

hello.
I implemented reference counting pointers (called SP in the example) and im having problems with polymorphism which i think i shouldn't have. In the following code:

    SP<BaseClass> foo()
    {   
        // Some logic...
        SP<DerivedClass> retPtr = new DerivedClass();
        return retPtr;
    }

DerivedClass inherits from BaseClass. With normal pointers this should have worked, but with the smart pointers it says "cannot convert from 'SP<T>' to 'const SP<T>&" and i think it refers to the copy constructor of the smart pointer.
How to i allow this kind of polymorphism with reference counting pointer?
I'd appreciate code samples cause obviously im doing something wrong here if im having this problem.

Thanks! :)

[PS Please don't tell me to use standard library with smart pointers because that's impossible at this moment.]

+4  A: 

Fairly obvious:

SP<DerivedClass> retPtr = new DerivedClass();

should be:

SP<BaseClass> retPtr = new DerivedClass();
anon
Converting SP<DerivedClass> into SP<BaseClass> should be no problem with a good smart pointer implementation.
Danvil
This fixes the specific problem in `foo()`, but it does not make for a natural syntax in other places where the conversion may be needed.
Gorpik
@Danvil: Converting isn't the issue, you can't change the return type in an overloaded function except in limited cases (covariant references and pointers) so it's pointless to even create an `SP` of the wrong type. This answer is the simplest: create an object of the type actually being returned.
Charles Bailey
A: 

Why not add a template assignment operator:

template <class Base>
class SP
{
    ...

    template<class Derived>
    operator = (SP<Derived>& rhs)
    {
        ...

(and maybe copy constructor, too)?

Vlad
+4  A: 

You should add implicit converting constructor for SP<T>:

template<class T>
struct SP {
   /// ......
   template<class Y>
   SP( SP <Y> const & r )
    : px( r.px ) // ...
    {
    }

   //....
private:
   T * px;
}
Alexey Malistov
A template constructor is never a copy constructor. A copy constructor isn't going to help; this is a non-explicit converting constructor.
Charles Bailey
@Charles. Right. No matter.
Alexey Malistov
A: 

In addition to the copy constructor:

SP(const SP<T>& ref);

you need a conversion constructor:

template<typename T2>
SP(const SP<T2>& ref);

Otherwise, the compiler will not know how to construct SP<BaseClass> from a SP<DerivedClass>; for him, they are unrelated.

The conversion constructor is fairly trivial, since internally you can convert *DerivedClass to *BaseClass automatically. Code may be very similar to that for the copy constructor.

Gorpik