Possibility to mix composite pattern and curiously recurring template pattern

人走茶凉 提交于 2019-12-01 15:22:47
Synxis

You can add one level of abstraction:

class CObjectBase
{
    public:
        // Other methods...
        virtual CObjectBase* detach() = 0;
        virtual CObjectBase* duplicate() const = 0;
};

template <typename Child>
class CObject : public CObjectBase
{
    public:
        // ...
        Child* duplicate() const
        {
            return new Child(*static_cast<Child*>(this));
        }

        Child* detach()
        {
            m_pParent->RemoveChild(this);
            m_pParent = nullptr;
            return static_cast<Child*>(this); // Cast needed here (inherent to CRTP)
        }
        std::vector<CObjectBase*> children; // Array possible now
        // ...
};

class MyObject : public CObject<MyObject>
{
    // ...
};

In natural language: an interface for all objects (CObjectBase) have a partial implementation for its descendants (CObject<Child>), which just have to inherit this partial implementation, decreasing the amount of replicated code.

I was thinking about CRTP, but I can not think of a way to keep the dynamic polymorphism along with compile time polymorphism

You can mix them by providing default virtual implementations for certain interfaces using CRTP style base classes.

Thus you have the possibility to aggregate CRTP base implementations (maybe configured with additional 'policy'-template parameters) and still being able to override particular behavior in inherited classes.

Microsoft's ATL library uses this a lot. I also make use of this technique in my STTCL state machine library.

From the snippet alone it is unclear why you need detach() to return a pointer to a delivered type.

To take advantage of detach() returning a delivered type, it needs to be called using a reference to the delivered type anyway. Like this:

CSpecificObject* specific_object = new SpecificObject();
// ...
specific_object->detach()->method_declared_in_specific_object();

But this can be replaced with equivalent that works even if detach is void:

specific_object->detach();
specific_object->method_declared_in_specific_object();

If you have a reference to the base type, you can't take advantage of detach() return type:

CObject* specific_object = new SpecificObject();
//...
// !!! Won't compile:
specific_object->detach()->method_declared_in_specific_object(); 

For this reason it is unclear what are the advantages of the approach you are trying to implement.

A side not is that the duplicate() method is smelly. It breaks when delivered class does not overwrite it, but uses the default implementation from the parent class. It can be a sign that something is wrong with the high level design.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!