奇异递归模板模式 (CRTP, Curiously Recurr

2020-09-02  本文已影响0人  fck_13

这个名字念起来有些拗口,先看一下代码示例:

// The Curiously Recurring Template Pattern (CRTP)
template<class T>
class Base{
    // methods within Base can use template to access members of Derived
};
class Derived : public Base<Derived>{
    // ...
};

这是CRTP一个最基本的形式,可以看出,将派生类作为基类的模板参数,意味基类可以访问派生类的一些内容,这也是名字中为什么会有递归两个字的原因。

下面是一些CRTP的使用示例:

静态多态

template <class T>
struct Base{
    void interface(){
        static_cast<T*>(this)->implementation();
    }

    static void static_func(){
        T::static_sub_func();
    }
};

struct Derived : Base<Derived>
{
    void implementation(){
    }
    static void static_sub_func();
};

void Derived::static_sub_func(){
}

int main(){
    Derived d{};
    d.static_func();
    return 0;
}

代码注入

template <typename T>
struct counter{
    static int objects_created;
    static int objects_alive;

    counter(){
        ++objects_created;
        ++objects_alive;
    }

    counter(const counter&){
        ++objects_created;
        ++objects_alive;
    }

    ~counter(){ // objects should never be removed through pointers of this type
        --objects_alive;
    }
};
template <typename T> int counter<T>::objects_created( 0 );
template <typename T> int counter<T>::objects_alive( 0 );

struct MyClass : public counter<MyClass>
{};

int main(){
    MyClass h{};
    {
        MyClass a{};
        MyClass c{};
        MyClass d{};
    }
    return MyClass::objects_alive;
}

单例模式

#include <memory>

template <class ActualClass>
class Singleton{
public:
    static ActualClass& GetInstance(){
       if(p == nullptr)
         p = std::unique_ptr<ActualClass>(new ActualClass);
       return *p;
     }

   protected:
    Singleton() = default;
    static std::unique_ptr<ActualClass> p;
};
template <class T>
std::unique_ptr< T > Singleton<T>::p;

class A: public Singleton<A>
{
};

int main(){
    auto& i = A::GetInstance();
}

最佳实践

namespace detail{
    template <class T>
    class Base{
    public:
        void interface()
        {
            // ...
            self()->implementation();
            // ...
        }
    private:
        T* self(){
            return static_cast<T*>(this);
        }
        // methods within Base can use template to access members of Derived
    };
};

class Derived : public detail::Base<Derived>{
public:
    void implementation(){
        // do something
    }
    // ...
};

int main(){
    Derived d;
    d.interface();
}

C++ 库中,std::shared_ptr中的std::enable_shared_from_this使用了CRTP.

上一篇 下一篇

猜你喜欢

热点阅读