What's polymorphic in CRTP

Discussion in 'C++' started by Jarek Blakarz, Feb 11, 2013.

  1. Hi

    I understand what is CRTP. What I don't understand is why CRTP is called a
    static polymorphism or rather polymorphism in particular.

    I think that it is "static" since the function call is resolved at compile
    time, right ?

    Assuming that I'm right about "static", plese explain me based on the following
    example why it is "polymorphic".

    thanks for clarification.



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

    struct Derived1 : Base<Derived1> {
    void implementation() { }
    };

    struct Derived2 : Base<Derived2> {
    void implementation() { }
    };

    Derived1 *d1 = new Derived1;
    Derived2 *d2 = new Derived2;

    d1->interface();
    d2->interface();
    Jarek Blakarz, Feb 11, 2013
    #1
    1. Advertising

  2. Jarek Blakarz

    Stuart Guest

    On 02/11/13, Jarek Blakarz wrote:
    > Hi
    >
    > I understand what is CRTP. What I don't understand is why CRTP is called a
    > static polymorphism or rather polymorphism in particular.


    Never heard of this though I have used CRTP lots of times. Most
    textbooks make a difference between static and dynamic polymorphism with
    regard to whether the polymorphic behaviour is resolved at compile time
    or run-time. The classic example for static polymorphism is function
    overloading. Although, the term may also be applied to CRTP, I guess.

    > I think that it is "static" since the function call is resolved at compile
    > time, right ?


    I'd say right.

    > Assuming that I'm right about "static", plese explain me based on the following
    > example why it is "polymorphic".
    >
    > thanks for clarification.
    >
    >
    >
    > template <class Derived> struct Base {
    > void interface() { static_cast<Derived*>(this)->implementation(); }


    At this place the writer of this code cannot tell which implementation
    of the invoked member function "implementation" will be called, so one
    could say that the invokation of the "implementation" method on the
    "this" pointer is polymorphic behaviour.

    I don't like the term "static polymorphism" very much. In my opinion
    "polymorphism" and "static" contradict each other. But apparently most
    scientist from "applied computer science" (another contradiction?) think
    otherwise.

    > };
    >
    > struct Derived1 : Base<Derived1> {
    > void implementation() { }
    > };
    >
    > struct Derived2 : Base<Derived2> {
    > void implementation() { }
    > };
    >
    > Derived1 *d1 = new Derived1;
    > Derived2 *d2 = new Derived2;
    >
    > d1->interface();
    > d2->interface();
    >


    Regards,
    Stuart
    Stuart, Feb 11, 2013
    #2
    1. Advertising

  3. Jarek Blakarz

    Öö Tiib Guest

    On Monday, 11 February 2013 17:40:04 UTC+2, Jarek Blakarz wrote:
    > Hi
    >
    > I understand what is CRTP. What I don't understand is why CRTP is called a
    > static polymorphism or rather polymorphism in particular.


    It is not called static polymorphism. It is common technique in C++ to achieve
    static polymorphism.

    > I think that it is "static" since the function call is resolved at compile
    > time, right ?


    Yes. You are correct. Exactly like there are arrays with static size
    (std::array<T,N>) and dynamic size (std::vector<T>). Static size means lost
    flexibility (that is maybe not needed) and won efficiency (that is always
    great to have).

    > Assuming that I'm right about "static", plese explain me based on the
    > following example why it is "polymorphic".


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


    This may or not be bare-bone interface. This is basic part of implementation
    that calls possibly "statically overriden" member function from derived class.
    You can even provide default implementation here:

    void implementation() { }

    > };
    >
    > struct Derived1 : Base<Derived1> {
    > void implementation() { }
    > };
    >
    > struct Derived2 : Base<Derived2> {
    > void implementation() { }
    > };


    Lets take you have default and also such Derived3 here:

    struct Derived3 : Base<Derived3> {
    };


    > Derived1 *d1 = new Derived1;
    > Derived2 *d2 = new Derived2;
    > d1->interface();
    > d2->interface();


    Your example leaks memory and feels like Java with its tons of news at
    each corner. C++11 just forgot to add 'std::make_unique<T>()', if that
    was in language then need to write 'new' or 'delete' in C++ code was
    close to none.

    Derived1 d1;
    Derived2 d2;
    Derived3 d3;
    d1.interface();
    d2.interface();
    d3.interface();

    It is polymorphism. All 3 calls may do different things. All 3 calls have
    part (possibly everything) of what they do inherited from Base, and part
    (possibly nothing) overriden. All 3 calls have exactly same common user
    interface.

    It is subtly less flexible and more efficient than virtual call ... so
    better *you* explain ... what is your problem of calling it polymorphism?
    Öö Tiib, Feb 11, 2013
    #3
  4. On Monday, February 11, 2013 5:38:03 PM UTC+1, Öö Tiib wrote:
    > On Monday, 11 February 2013 17:40:04 UTC+2, Jarek Blakarz wrote:
    >
    > > Hi

    >
    > >

    >
    > > I understand what is CRTP. What I don't understand is why CRTP is called a

    >
    > > static polymorphism or rather polymorphism in particular.

    >
    >
    >
    > It is not called static polymorphism. It is common technique in C++ to achieve
    >
    > static polymorphism.
    >
    >
    >
    > > I think that it is "static" since the function call is resolved at compile

    >
    > > time, right ?

    >
    >
    >
    > Yes. You are correct. Exactly like there are arrays with static size
    >
    > (std::array<T,N>) and dynamic size (std::vector<T>). Static size means lost
    >
    > flexibility (that is maybe not needed) and won efficiency (that is always
    >
    > great to have).
    >
    >
    >
    > > Assuming that I'm right about "static", plese explain me based on the

    >
    > > following example why it is "polymorphic".

    >
    >
    >
    > > template <class Derived> struct Base {

    >
    > > void interface() { static_cast<Derived*>(this)->implementation(); }

    >
    >
    >
    > This may or not be bare-bone interface. This is basic part of implementation
    >
    > that calls possibly "statically overriden" member function from derived class.
    >
    > You can even provide default implementation here:
    >
    >
    >
    > void implementation() { }
    >
    >
    >
    > > };

    >
    > >

    >
    > > struct Derived1 : Base<Derived1> {

    >
    > > void implementation() { }

    >
    > > };

    >
    > >

    >
    > > struct Derived2 : Base<Derived2> {

    >
    > > void implementation() { }

    >
    > > };

    >
    >
    >
    > Lets take you have default and also such Derived3 here:
    >
    >
    >
    > struct Derived3 : Base<Derived3> {
    >
    > };
    >
    >
    >
    >
    >
    > > Derived1 *d1 = new Derived1;

    >
    > > Derived2 *d2 = new Derived2;

    >
    > > d1->interface();

    >
    > > d2->interface();

    >
    >
    >
    > Your example leaks memory and feels like Java with its tons of news at
    >
    > each corner. C++11 just forgot to add 'std::make_unique<T>()', if that
    >
    > was in language then need to write 'new' or 'delete' in C++ code was
    >
    > close to none.
    >
    >
    >
    > Derived1 d1;
    >
    > Derived2 d2;
    >
    > Derived3 d3;
    >
    > d1.interface();
    >
    > d2.interface();
    >
    > d3.interface();
    >
    >
    >
    > It is polymorphism. All 3 calls may do different things. All 3 calls have
    >
    > part (possibly everything) of what they do inherited from Base, and part
    >
    > (possibly nothing) overriden. All 3 calls have exactly same common user
    >
    > interface.
    >
    >
    >
    > It is subtly less flexible and more efficient than virtual call ... so
    >
    > better *you* explain ... what is your problem of calling it polymorphism?


    Thanks for explanation to everyone.
    My goal was just to understand why it is called polymorphism.
    Earlier I only suspected why. Now I think I got it.
    Jarek Blakarz, Feb 12, 2013
    #4
  5. Jarek Blakarz

    Cholo Lennon Guest

    On 12/02/2013 12:55, Jarek Blakarz wrote:

    >
    > Thanks for explanation to everyone.
    > My goal was just to understand why it is called polymorphism.
    > Earlier I only suspected why. Now I think I got it.
    >


    If you are not afraid of Microsoft/Windows/COM you can take a look to
    Microsoft ATL library (or its cousin WTL, a tiny header-only library
    http://wtl.sourceforge.net/) in order to view an extensive usage of CRTP.

    Regards

    --
    Cholo Lennon
    Bs.As.
    ARG
    Cholo Lennon, Feb 13, 2013
    #5
  6. Thanks for the reply to all of you.
    I spent some time looking at Windows examples but it seems to complex to me at
    the beginning.
    Could you please give me a simple example of CRTP as a replacement for dynamic
    polymorphism. In case of dynamic polymorphism it seems quite obvious to me why
    it is powerful. In case of CRTP I still don't feel how it can replace dynamic
    polymorphism.

    In case of dynamic polymorphism I can refer to the derived classes using
    exactly the same interface e.g:

    void fun ( Base &base )
    {
    base.makeSound(); // exactly the same interface for distinct derived classes
    }

    Unfortunately I cannot apply the same logic to CRTP static polymorphism.
    In my initial example above the interface is not "exactly" the same. It is
    only "similar". It differs with object name. In case of dynamic polymorphism
    whenever I inherit from the base class the interface remains the same. In case
    of CRTP static polymorphism whenever I inherit from the base class the
    interface changes.

    Thanks for the explanation.
    Jarek Blakarz, Feb 15, 2013
    #6
  7. Jarek Blakarz

    Öö Tiib Guest

    On Friday, 15 February 2013 17:01:53 UTC+2, Jarek Blakarz wrote:
    > Thanks for the reply to all of you.
    > I spent some time looking at Windows examples but it seems to complex to me at
    > the beginning.


    WTL (static polymorphism) was made to be alternative GUI toolkit to MFC (deep
    dynamic polymorphism). It sort of works so it can replace over-used dynamic
    polymorphism.

    > Could you please give me a simple example of CRTP as a replacement for dynamic
    > polymorphism. In case of dynamic polymorphism it seems quite obvious to me why
    > it is powerful. In case of CRTP I still don't feel how it can replace dynamic
    > polymorphism.


    Yes, whole GUI toolkit is indeed not a simple example but that is it. You want low
    level techniques how to convert one to other but there are no such things. There
    are real, high-level goals (like GUI toolkit) that can be achieved using one way or
    other. CRTP is more efficient than virtual inheritance but it has its limitations too.

    > In case of dynamic polymorphism I can refer to the derived classes using
    > exactly the same interface e.g:
    >
    > void fun ( Base &base )
    > {
    > base.makeSound(); // exactly the same interface for distinct derived classes
    > }


    What is so hard about it?

    template<class T>
    void fun( T& t )
    {
    t.makeSound(); // works for all classes with such member
    }

    > Unfortunately I cannot apply the same logic to CRTP static polymorphism.
    > In my initial example above the interface is not "exactly" the same. It is
    > only "similar". It differs with object name. In case of dynamic polymorphism
    > whenever I inherit from the base class the interface remains the same. In case
    > of CRTP static polymorphism whenever I inherit from the base class the
    > interface changes.


    Template is more flexible since it does not require you to derive from same base.
    Just be "similar" (your word) and you *have* same interface for a template.
    If you require exact class in interface then that is what is needed.

    Can you explain why you require exact class? There are only limited cases,
    like when you want to use exactly same pointer to point to one or other.
    That is where you need dynamic polymorphism. Achieve your goal (GUI toolkit)
    without having such undetermined pointers in code and CRTP works fine.
    Öö Tiib, Feb 15, 2013
    #7
  8. Jarek Blakarz

    Cholo Lennon Guest

    On 02/15/2013 12:01 PM, Jarek Blakarz wrote:
    > Thanks for the reply to all of you.
    > I spent some time looking at Windows examples but it seems to complex to me at
    > the beginning.
    > Could you please give me a simple example of CRTP as a replacement for dynamic
    > polymorphism. In case of dynamic polymorphism it seems quite obvious to me why
    > it is powerful. In case of CRTP I still don't feel how it can replace dynamic
    > polymorphism.
    >
    > In case of dynamic polymorphism I can refer to the derived classes using
    > exactly the same interface e.g:
    >
    > void fun ( Base &base )
    > {
    > base.makeSound(); // exactly the same interface for distinct derived classes
    > }
    >
    > Unfortunately I cannot apply the same logic to CRTP static polymorphism.
    > In my initial example above the interface is not "exactly" the same. It is
    > only "similar". It differs with object name. In case of dynamic polymorphism
    > whenever I inherit from the base class the interface remains the same. In case
    > of CRTP static polymorphism whenever I inherit from the base class the
    > interface changes.
    >
    > Thanks for the explanation.
    >


    How about this?


    #include <iostream>

    template<class T>
    class Base {

    public:
    void callDynamic()
    {
    onDynamic();
    }

    void callStatic()
    {
    T* pThis = static_cast<T*>(this);
    pThis->onStatic();
    }


    virtual void onDynamic()
    {
    std::cout << "Base::eek:nDynamic" << std::endl;
    }

    void onStatic()
    {
    std::cout << "Base::eek:nStatic" << std::endl;
    }

    };


    class Derived: public Base<Derived> {

    public:

    virtual void onDynamic()
    {
    std::cout << "Derived::eek:nDynamic" << std::endl;
    }

    // "pseudo virtual" function :)
    void onStatic()
    {
    std::cout << "Derived::eek:nStatic" << std::endl;
    }

    };


    int main(int, char**)
    {
    Derived derived;
    derived.callDynamic();
    derived.callStatic();
    }


    Also, try commenting out functions in Derived class to see what happens

    Regards


    --
    Cholo Lennon
    Bs.As.
    ARG
    Cholo Lennon, Feb 15, 2013
    #8
  9. Jarek Blakarz

    Öö Tiib Guest

    On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    > How about this?


    It is example that works but does not achieve much else but inefficiency.
    ;-)

    > #include <iostream>
    >
    > template<class T>
    > class Base {


    Note that T is meant to be derived class.
    So you can not use Base<Derived>* as dynamically polymorphic interface
    pointer for several different "Derived"s.

    > public:
    > void callDynamic()
    > {
    > onDynamic();
    > }
    >
    > void callStatic()
    > {
    > T* pThis = static_cast<T*>(this);
    > pThis->onStatic();
    > }
    >
    > virtual void onDynamic()
    > {
    > std::cout << "Base::eek:nDynamic" << std::endl;
    > }
    >
    > void onStatic()
    > {
    > std::cout << "Base::eek:nStatic" << std::endl;
    > }
    >
    > };
    >
    >
    > class Derived: public Base<Derived> {
    >
    > public:
    >
    > virtual void onDynamic()
    > {
    > std::cout << "Derived::eek:nDynamic" << std::endl;
    > }
    >
    > // "pseudo virtual" function :)
    > void onStatic()
    > {
    > std::cout << "Derived::eek:nStatic" << std::endl;
    > }
    > };
    >
    >
    > int main(int, char**)
    > {
    > Derived derived;
    > derived.callDynamic();
    > derived.callStatic();
    > }
    >
    >
    > Also, try commenting out functions in Derived class to see what happens


    Just try making it with Derived1, Derived2 and Derived3 and you see where you
    went wrong. Do not mix CRTP with dynamic polymorphism. Use typical
    pure abstract interface base and multiple inheritance side by side with
    CRTP if you need to mix them.
    Öö Tiib, Feb 15, 2013
    #9
  10. Jarek Blakarz

    Cholo Lennon Guest

    On 02/15/2013 01:33 PM, Öö Tiib wrote:
    > On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    >> How about this?

    >
    > It is example that works but does not achieve much else but inefficiency.
    > ;-)


    Why the example is inefficient? The call to Derived::eek:nStatic is
    resolved at compile time.

    Also, in order to simplify the code I put the dynamic/static variants in
    the same class.

    The example shows static polymorphism as is used in ATL (WTL). It was
    not intended to be used/interpreted in another way.

    >
    >> #include <iostream>
    >>
    >> template<class T>
    >> class Base {

    >
    > Note that T is meant to be derived class.
    > So you can not use Base<Derived>* as dynamically polymorphic interface
    > pointer for several different "Derived"s.
    >
    >> public:
    >> void callDynamic()
    >> {
    >> onDynamic();
    >> }
    >>
    >> void callStatic()
    >> {
    >> T* pThis = static_cast<T*>(this);
    >> pThis->onStatic();
    >> }
    >>
    >> virtual void onDynamic()
    >> {
    >> std::cout << "Base::eek:nDynamic" << std::endl;
    >> }
    >>
    >> void onStatic()
    >> {
    >> std::cout << "Base::eek:nStatic" << std::endl;
    >> }
    >>
    >> };
    >>
    >>
    >> class Derived: public Base<Derived> {
    >>
    >> public:
    >>
    >> virtual void onDynamic()
    >> {
    >> std::cout << "Derived::eek:nDynamic" << std::endl;
    >> }
    >>
    >> // "pseudo virtual" function :)
    >> void onStatic()
    >> {
    >> std::cout << "Derived::eek:nStatic" << std::endl;
    >> }
    >> };
    >>
    >>
    >> int main(int, char**)
    >> {
    >> Derived derived;
    >> derived.callDynamic();
    >> derived.callStatic();
    >> }
    >>
    >>
    >> Also, try commenting out functions in Derived class to see what happens

    >
    > Just try making it with Derived1, Derived2 and Derived3 and you see where you
    > went wrong. Do not mix CRTP with dynamic polymorphism. Use typical
    > pure abstract interface base and multiple inheritance side by side with
    > CRTP if you need to mix them.
    >



    --
    Cholo Lennon
    Bs.As.
    ARG
    Cholo Lennon, Feb 15, 2013
    #10
  11. Jarek Blakarz

    Öö Tiib Guest

    On Friday, 15 February 2013 18:55:12 UTC+2, Cholo Lennon wrote:
    > On 02/15/2013 01:33 PM, Öö Tiib wrote:
    > > On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    > >> How about this?

    > >
    > > It is example that works but does not achieve much else but inefficiency.
    > > ;-)

    >
    > Why the example is inefficient? The call to Derived::eek:nStatic is
    > resolved at compile time.


    Because there are virtual functions (more expensive) that can not be used for
    dynamic polymorphism (purpose is lost).
    I explained it further. In my post that you quoted but apparently did not read.
    Öö Tiib, Feb 15, 2013
    #11
  12. Jarek Blakarz

    Cholo Lennon Guest

    On 02/15/2013 02:05 PM, Öö Tiib wrote:
    > On Friday, 15 February 2013 18:55:12 UTC+2, Cholo Lennon wrote:
    >> On 02/15/2013 01:33 PM, Öö Tiib wrote:
    >>> On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    >>>> How about this?
    >>>
    >>> It is example that works but does not achieve much else but inefficiency.
    >>> ;-)

    >>
    >> Why the example is inefficient? The call to Derived::eek:nStatic is
    >> resolved at compile time.

    >
    > Because there are virtual functions (more expensive) that can not be used for
    > dynamic polymorphism (purpose is lost).
    > I explained it further. In my post that you quoted but apparently did not read.
    >


    and... have you read my explanation? This was an *example*, not a
    production code. The idea was to show the dynamic and static variant in
    a simple way.

    Regards


    --
    Cholo Lennon
    Bs.As.
    ARG
    Cholo Lennon, Feb 15, 2013
    #12
  13. Jarek Blakarz

    Öö Tiib Guest

    On Friday, 15 February 2013 19:25:10 UTC+2, Cholo Lennon wrote:
    > On 02/15/2013 02:05 PM, Öö Tiib wrote:
    > > On Friday, 15 February 2013 18:55:12 UTC+2, Cholo Lennon wrote:
    > >> On 02/15/2013 01:33 PM, Öö Tiib wrote:
    > >>> On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    > >>>> How about this?
    > >>>
    > >>> It is example that works but does not achieve much else but inefficiency.
    > >>> ;-)
    > >>
    > >> Why the example is inefficient? The call to Derived::eek:nStatic is
    > >> resolved at compile time.

    > >
    > > Because there are virtual functions (more expensive) that can not be used for
    > > dynamic polymorphism (purpose is lost).
    > > I explained it further. In my post that you quoted but apparently did not read.

    >
    > and... have you read my explanation? This was an *example*, not a
    > production code. The idea was to show the dynamic and static variant in
    > a simple way.


    I do not, yes, understand something here. Can you elaborate? Example must
    be ideally simplest that works. Simpler than that is a lie, not example.
    Someone may see it and think that it is showing how to mix dynamic and static
    polymorphism, but it can't. What production code? I was saying that it should
    be example on "never do like that" page with large red cross on it.
    Öö Tiib, Feb 15, 2013
    #13
  14. Jarek Blakarz

    Cholo Lennon Guest

    On 02/15/2013 03:03 PM, Öö Tiib wrote:
    > On Friday, 15 February 2013 19:25:10 UTC+2, Cholo Lennon wrote:
    >> On 02/15/2013 02:05 PM, Öö Tiib wrote:
    >>> On Friday, 15 February 2013 18:55:12 UTC+2, Cholo Lennon wrote:
    >>>> On 02/15/2013 01:33 PM, Öö Tiib wrote:
    >>>>> On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    >>>>>> How about this?
    >>>>>
    >>>>> It is example that works but does not achieve much else but inefficiency.
    >>>>> ;-)
    >>>>
    >>>> Why the example is inefficient? The call to Derived::eek:nStatic is
    >>>> resolved at compile time.
    >>>
    >>> Because there are virtual functions (more expensive) that can not be used for
    >>> dynamic polymorphism (purpose is lost).
    >>> I explained it further. In my post that you quoted but apparently did not read.

    >>
    >> and... have you read my explanation? This was an *example*, not a
    >> production code. The idea was to show the dynamic and static variant in
    >> a simple way.

    >
    > I do not, yes, understand something here. Can you elaborate? Example must
    > be ideally simplest that works. Simpler than that is a lie, not example.
    > Someone may see it and think that it is showing how to mix dynamic and static
    > polymorphism, but it can't. What production code? I was saying that it should
    > be example on "never do like that" page with large red cross on it.
    >


    OMG, the OP asked for an example of static polymorphism with CRTP and
    you gave him an example of static polymorphism with templates but
    without CRTP! Nice way to teach the concept!

    Just in case you insist with my example, I re-wrote it for you:


    #include <iostream>

    namespace dynamic_polymorphism
    {
    class Base {
    public:
    void callFoo()
    {
    onFoo();
    }

    virtual void onFoo()
    {
    std::cout << "Base::eek:nFoo" << std::endl;
    }

    };

    class Derived: public Base {
    public:
    virtual void onFoo()
    {
    std::cout << "Derived::eek:nFoo" << std::endl;
    }

    };
    }


    namespace static_polymorphism
    {
    template<class T>
    class Base {
    public:
    void callFoo()
    {
    T* pThis = static_cast<T*>(this);
    pThis->onFoo();
    }

    void onFoo()
    {
    std::cout << "Base::eek:nFoo" << std::endl;
    }

    };

    class Derived: public Base<Derived> {
    public:
    // "pseudo virtual" function
    void onFoo()
    {
    std::cout << "Derived::eek:nFoo" << std::endl;
    }

    };
    }


    int main(int, char**)
    {
    dynamic_polymorphism::Derived der1;
    der1.callFoo();

    static_polymorphism::Derived der2;
    der2.callFoo();
    }


    Are you happy now?

    Regards


    --
    Cholo Lennon
    Bs.As.
    ARG
    Cholo Lennon, Feb 15, 2013
    #14
  15. Jarek Blakarz

    Öö Tiib Guest

    On Saturday, 16 February 2013 00:18:44 UTC+2, Cholo Lennon wrote:
    > On 02/15/2013 03:03 PM, Öö Tiib wrote:
    > > On Friday, 15 February 2013 19:25:10 UTC+2, Cholo Lennon wrote:
    > >> On 02/15/2013 02:05 PM, Öö Tiib wrote:
    > >>> On Friday, 15 February 2013 18:55:12 UTC+2, Cholo Lennon wrote:
    > >>>> On 02/15/2013 01:33 PM, Öö Tiib wrote:
    > >>>>> On Friday, 15 February 2013 18:18:47 UTC+2, Cholo Lennon wrote:
    > >>>>>> How about this?
    > >>>>>
    > >>>>> It is example that works but does not achieve much else but inefficiency.
    > >>>>> ;-)
    > >>>>
    > >>>> Why the example is inefficient? The call to Derived::eek:nStatic is
    > >>>> resolved at compile time.
    > >>>
    > >>> Because there are virtual functions (more expensive) that can not be used for
    > >>> dynamic polymorphism (purpose is lost).
    > >>> I explained it further. In my post that you quoted but apparently didnot read.
    > >>
    > >> and... have you read my explanation? This was an *example*, not a
    > >> production code. The idea was to show the dynamic and static variant in
    > >> a simple way.

    > >
    > > I do not, yes, understand something here. Can you elaborate? Example must
    > > be ideally simplest that works. Simpler than that is a lie, not example..
    > > Someone may see it and think that it is showing how to mix dynamic and static
    > > polymorphism, but it can't. What production code? I was saying that it should
    > > be example on "never do like that" page with large red cross on it.
    > >

    >
    > OMG, the OP asked for an example of static polymorphism with CRTP and
    > you gave him an example of static polymorphism with templates but
    > without CRTP! Nice way to teach the concept!


    The concept we discussed before. CRTP is just one pattern for to use static
    polymorphism, but that I said to him in my first reply already.

    Now he was asking what to do with the resulting with CRTP functions that
    have same signature (he said are "similar") but do not belong to same virtual
    hierarchy (he said are not "same"). So I said that he should continue using
    static polymorphism.

    > Just in case you insist with my example, I re-wrote it for you:


    Thanks.

    > Are you happy now?


    Sometimes people see me more grumpy than I really am. I try to point out the
    flaws to be helpful. Everything contains mistakes, mine code too, yours was
    not making me unhappy or anything.

    Mixing static and dynamic polymorphism may be needed in same application.
    For example if you need a container that contains polymorphic pointers then
    there you have to use dynamic polymorphism, static does not work.
    Öö Tiib, Feb 16, 2013
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike Smith

    ABC vs. CRTP?

    Mike Smith, Mar 2, 2005, in forum: C++
    Replies:
    7
    Views:
    910
    Dietmar Kuehl
    Mar 3, 2005
  2. fabioppp

    CRTP question

    fabioppp, Apr 15, 2005, in forum: C++
    Replies:
    2
    Views:
    382
    James Aguilar
    Apr 15, 2005
  3. CRTP question

    , Apr 17, 2006, in forum: C++
    Replies:
    2
    Views:
    391
  4. CRTP and Factories

    , Jul 25, 2006, in forum: C++
    Replies:
    2
    Views:
    330
  5. Noah Roberts

    CRTP

    Noah Roberts, Jan 12, 2007, in forum: C++
    Replies:
    6
    Views:
    894
    kwikius
    Jan 15, 2007
Loading...

Share This Page