What is the curiously recurring template pattern (CRTP)?

前端 未结 5 1914
小鲜肉
小鲜肉 2020-11-21 11:27

Without referring to a book, can anyone please provide a good explanation for CRTP with a code example?

5条回答
  •  半阙折子戏
    2020-11-21 12:04

    This is not a direct answer, but rather an example of how CRTP can be useful.


    A good concrete example of CRTP is std::enable_shared_from_this from C++11:

    [util.smartptr.enab]/1

    A class T can inherit from enable_­shared_­from_­this to inherit the shared_­from_­this member functions that obtain a shared_­ptr instance pointing to *this.

    That is, inheriting from std::enable_shared_from_this makes it possible to get a shared (or weak) pointer to your instance without access to it (e.g. from a member function where you only know about *this).

    It's useful when you need to give a std::shared_ptr but you only have access to *this:

    struct Node;
    
    void process_node(const std::shared_ptr &);
    
    struct Node : std::enable_shared_from_this // CRTP
    {
        std::weak_ptr parent;
        std::vector> children;
    
        void add_child(std::shared_ptr child)
        {
            process_node(shared_from_this()); // Shouldn't pass `this` directly.
            child->parent = weak_from_this(); // Ditto.
            children.push_back(std::move(child));
        }
    };
    

    The reason you can't just pass this directly instead of shared_from_this() is that it would break the ownership mechanism:

    struct S
    {
        std::shared_ptr get_shared() const { return std::shared_ptr(this); }
    };
    
    // Both shared_ptr think they're the only owner of S.
    // This invokes UB (double-free).
    std::shared_ptr s1 = std::make_shared();
    std::shared_ptr s2 = s1->get_shared();
    assert(s2.use_count() == 1);
    

提交回复
热议问题