开发者

How to accomplish covariant return types when returning a shared_ptr?

using namespace boost;

class A {};
class B : public A {};

class X {
  virtual shared_ptr<A> foo();
};

class Y : public X {
  virtual shared_ptr<B> foo();
};

The return types aren't covariant (nor are they, therefore, legal), but they would be if I was using raw pointers instead. What's the commonly accepted idiom to work around this, if ther开发者_C百科e is one?


I think that a solution is fundamentally impossible because covariance depends on pointer arithmetic which is incompatible with smart pointers.

When Y::foo returns shared_ptr<B> to a dynamic caller, it must be cast to shared_ptr<A> before use. In your case, a B* can (probably) simply be reinterpreted as an A*, but for multiple inheritance, you would need some magic to tell C++ about static_cast<A*>(shared_ptr<B>::get()).


Not directly, but you can fake it by making the actual virtual functions inaccessible from outside the class and wrapping the virtual function call into a non-virtual function. Downside is that you'll have to remember to implement this wrapper function on each derived class. But you could get around this by puting both the virtul function declaration and the wrapper into the macro.

using namespace boost; // for shared_ptr, make_shared and static_pointer_cast.

// "Fake" implementation of the clone() function.
#define CLONE(MyType) \
    shared_ptr<MyType> clone() \
    { \
        shared_ptr<Base> res = clone_impl(); \
        assert(dynamic_cast<MyType*>(res.get()) != 0); \
        return static_pointer_cast<MyType>(res); \
    }

class Base 
{
protected:
    // The actual implementation of the clone() function. 
    virtual shared_ptr<Base> clone_impl() { return make_shared<Base>(*this); }

public:
    // non-virtual shared_ptr<Base> clone();
    CLONE(Base)
};

class Derived : public Base
{
protected:
    virtual shared_ptr<Base> clone_impl() { return make_shared<Derived>(*this); }

public:
    // non-virtual shared_ptr<Derived> clone();
    CLONE(Derived)
};


int main()
{
    shared_ptr<Derived> p = make_shared<Derived>();
    shared_ptr<Derived> clone = p->clone();

    return 0;
}


I just return a bare pointer and wrap it immediately in the shared pointer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜