views:

318

answers:

2

In C++, a subclass can specify a different return type when overriding a virtual function, as long as the return type is a subclass of the original return type (And both are returned as pointers/references).

Is it possible to expand this feature to smart pointers as well? (Assuming a smart pointer is some template class)

To illustrate:

class retBase {...};
class retSub : public retBase {...};

class Base
{
    virtual retBase *f();
};

class Sub : public Base
{
    virtual retSub *f();     // This is ok.
};


class smartBase
{
    virtual smartPtr<retBase> f();
};

class smartSub : public smartBase
{
    virtual smartPtr<retSub> f();     // Can this be somehow acheived?
};

EDIT: As Konrad Rudolph suggested, this is not directly possible. However, I ran accross this method:

class smartBase
{
    protected:
        virtual retBase *f_impl();
    public:
        smartPtr<refBase> f()
        {
             return f_impl();
        }
};

class smartSub : public smartBase
{
    protected:
        virtual retSub *f_impl();
    public:
        smartPtr<refSub> f()
        {
             return f_impl();
        }
};

Would you suggest going this way?

+5  A: 

Is it possible to expand this feature to smart pointers as well? (Assuming a smart pointer is some template class)

No: C++ doesn't know/allow covariant or contravariant templates. There's no relation between types Ptr<A> and Ptr<B>, even if A inherits from B.

Konrad Rudolph
but you can emulate it.
Alexandre C.
@Alexandre: what do you mean? How? (ignoring type erasure and copying)
Konrad Rudolph
by providing template copy constructors, or template conversion operators (yeah I know I'm disappointing you)...
Alexandre C.
How do template copy constructors or conversion operators fix this? A subclass signature will still need a base class return type, which to convert to a subclass return type would involve downcasting. If you could have Ptr<B> inherit from Ptr<A>, then you could make it work. If classes had a builtin typelist of their parent classes I think you could do this.
Joseph Garvin
A: 

Boost shared_ptr can hold a polymorphic pointer. If you want a covariant return type, then you want to use something specific to the subtype. In that case, you can leave return type unchanged and use dynamic_pointer_cast to downcast the pointer.