What is the motivation behind static polymorphism in C++?

前端 未结 3 1981
醉话见心
醉话见心 2020-12-04 07:21

I understand the mechanics of static polymorphism using the Curiously Recurring Template Pattern. I just do not understand what is it good for.

The declared motivat

3条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-04 07:21

    The link you provide mentions boost iterators as an example of static polymorphism. STL iterators also exhibit this pattern. Lets take a look at an example and consider why the authors of those types decided this pattern was appropriate:

    #include 
    #include 
    using namespace std;
    void print_ints( vector const& some_ints )
    {
        for( vector::const_iterator i = some_ints.begin(), end = some_ints.end(); i != end; ++i )
        {
            cout << *i;
        }
    }
    

    Now, how would we implement int vector::const_iterator::operator*() const; Can we use polymprhism for this? Well, no. What would the signature of our virtual function be? void const* operator*() const? That's useless! The type has been erased (degraded from int to void*). Instead, the curiously recurring template pattern steps in to help us generate the iterator type. Here is a rough approximation of the iterator class we would need to implement the above:

    template
    class const_iterator_base
    {
    public:
        const_iterator_base():{}
    
        T::contained_type const& operator*() const { return Ptr(); }
        T::contained_type const& operator->() const { return Ptr(); }
        // increment, decrement, etc, can be implemented and forwarded to T
        // ....
    private:
        T::contained_type const* Ptr() const { return static_cast(this)->Ptr(); }
    };
    

    Traditional dynamic polymorphism could not provide the above implementation!

    A related and important term is parametric polymorphism. This allows you to implement similar APIs in, say, python that you can using the curiously recurring template pattern in C++. Hope this is helpful!

    I think it's worth taking a stab at the source of all this complexity, and why languages like Java and C# mostly try to avoid it: type erasure! In c++ there is no useful all containing Object type with useful information. Instead we have void* and once you have void* you truely have nothing! If you have an interface that decays to void* the only way to recover is by making dangerous assumptions or keeping extra type information around.

提交回复
热议问题