C ++ CRTP类层次结构

时间:2011-10-24 10:04:51

标签: c++ templates crtp

来自Wikipedia

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

现在如果我想要derived_from_derived,我可以写:

// 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>
{
    // ...
};

现在假设我只想要一个derived对象。这不起作用:

derived<derived> obj;

derived必须是抽象的,还是有办法实例化它?

5 个答案:

答案 0 :(得分:2)

使用CRTP支持更深层次的继承层次结构通常是通过在继承层次结构中自己的类之间“插入”CRTP类来实现的:


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>
{};

答案 1 :(得分:2)

我自己的答案是:

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>
    {
        // ...
    };
};

现在我可以拥有derived::type<> obj。此外,参数化继承也起作用(例如装饰器模式):

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;

答案 2 :(得分:1)

这样做是不合法的,因为内部派生不是一个类,但它本身就是一个模板,而不是派生模板的合法参数。

通常这样做的方法是拥有一组派生模板实现,然后每个实现都有一个单独的类,用于将该实现实例化为具体类。

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>
{

};

答案 3 :(得分:0)

derived<derived> obj;

是不允许的,因为derivedtemplate类,内部derived尚未完成。它需要有类似derived<int>的类型。

答案 4 :(得分:0)

没有“只是”派生对象这样的东西,就像你不能拥有“只是”std::vector一样,也不能拥有float x = sqrt();。该类型需要一个参数,您必须提供它。