Curiously recurring template pattern

Posted on Thu 09 June 2022 in Journal

CRTP (Curiously Recurring Template Pattern) 即奇异重复模板模式, 它其实很早就出现了,看起来有点奇怪,用起来却很爽, 其最主要的用途就是静态多态

它有两个特点:

  • 子类继承自模板类。
  • 派生类将自身作为参数传给模板类。
#include <string>
#include <memory>
#include <sstream>
#include <iostream>

template <typename T>
class Entity  {
public:
    Entity(uint32_t id, const std::string& name): m_id(id), m_name(name) {

    }
    std::string& getName() const { return m_name; }
    uint32_t getId() const { return m_id; }
    std::string toString() const {

        return static_cast<T*>(this)->toString();
    }

    static std::shared_ptr<T> createInstance(uint32_t id, const std::string& name)
    {
        return T::createInstance(id, name);
    }
protected:
    uint32_t m_id;
    std::string m_name;

};


class User : Entity<User>
{
public:

    User(uint32_t id, const std::string& name):Entity<User>(id, name) {  }
    std::string toString() const {
        std::ostringstream out;
        out << "user: id=" << m_id;
        out << ", name=" << m_name;
        return out.str();

    }
    static std::shared_ptr<User> createInstance(uint32_t id, const std::string& name) {
        return std::make_shared<User>(id, name);
    }
};

class Room : Entity<Room>
{
public:

    Room(uint32_t id, const std::string& name):Entity<Room>(id, name) {  }
    std::string toString() const {
        std::ostringstream out;
        out << "room: id=" << m_id;
        out << ", name=" << m_name;
        return out.str();

    }
    static std::shared_ptr<Room> createInstance(uint32_t id, const std::string& name) {
        return std::make_shared<Room>(id, name);
    }
};

int main(int argc, char** argv)
{
    auto user = User::createInstance(1, "Alice");
    std::cout<< user->toString()<<std::endl;

    auto room = Room::createInstance(2, "House");
    std::cout<< room->toString()<<std::endl;

    return 0;
}

output:

user: id=1, name=Alice
room: id=2, name=House

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。