C++ CRTP class hierarchy

半世苍凉 提交于 2021-02-07 03:42:56

问题


From Wikipedia:

// The Curiously Recurring Template Pattern (CRTP)
template <typename T>
struct base
{
    // ...
};
struct derived : base<derived>
{
    // ...
};

Now if I want derived_from_derived, I can write:

// The Curiously Recurring Template Pattern (CRTP)
template <typename T>
struct base
{
    // ...
};
template <typename T>
struct derived : base<T>
{
    // ...
};
struct derived_from_derived : derived <derived_from_derived>
{
    // ...
};

Now suppose I just want a derived object. This doesn't work:

derived<derived> obj;

Does derived have to be abstract, or is there a way to instantiate it?


回答1:


Support for deeper inheritance hierarchies with CRTP usually is implemented by "inserting" CRTP classes between your own classes in the inheritance hierarchy:


struct empty
{};

template <class Derived, class Base = empty>
struct crtp_services : Base
{};

class base : public crtp_services<base>
{};

class derived : public crtp_services<derived, base>
{};

class derived_of_derived : public crtp_services<derived_of_derived, derived>
{};




回答2:


My own answer is this:

struct base
{
    template <typename T>
    struct type
    {
        // ...
    };
};
struct derived
{
    template <typename T=derived>
    struct type : base::type<T>
    {
        // ...
    };
}
struct derived_from_derived 
{
    template <typename T=derived_from_derived >
    struct type : derived::type<T>
    {
        // ...
    };
};

Now I can have a derived::type<> obj. Also, parametized inheritance works (e.g. decorator pattern):

template <typename whatever>
struct derived_from_whatever 
{
    template <typename T=derived_from_whatever>
    struct type : whatever::type<T>
    {
        // ...
    };
};

derived_from_whatever<derived_from_derived>::type<> obj_whatever;



回答3:


It's not legal to do that, since the inner derived is not a class, but is itself a template, and not a legal argument for the derived template.

The way that this is usually done is to have a set of derived templates implementations, and then each implementation has a separate class which is used to instantiate that implementation as a concrete class.

template <typename T>
struct base
{

};


template <typename T>
struct derived_impl : base<T>
{


};


struct derived : derived_impl<derived>
{


};


template <typename T>
struct derived_of_derived_impl: derived_impl<T>
{


};

struct derived_of_derived : derived_of_derived_impl<derived_of_derived>
{

};



回答4:


derived<derived> obj;

is not allowed because derived is a template class and the inner derived is not yet complete. It needs to have a type like derived<int>.




回答5:


There's no such thing as "just" a derived object, just like you cannot have "just" std::vector, nor can you have float x = sqrt();. The type requires an argument, and you must provide it.



来源:https://stackoverflow.com/questions/7873989/c-crtp-class-hierarchy

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