Static vs Dynamic Polymorphism

Jul 21, 2015 at 5:40pm
I just learned static polymorphism and was spending my time learning what it is about for last few days.

We create dynamic polymorphism this way
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Animal
{
public:
    Animal(){}
    ~Animal(){}

    virtual void talk() = 0;    // Just talks
};

class Dog : public Animal
{
public:
    Dog(){}
    ~Dog(){}

    void talk() override
    {
        std::cout << "Meow!" << std::endl;
    }
};

class Cat : public Animal
{
public:
    Cat(){}
    ~Cat(){}

    void talk() override
    {
        std::cout << "Voof!" << std::endl;
    }
};

and use it
1
2
3
4
5
6
7
8
9
    std::vector<std::unique_ptr<Animal>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<Animal> &animal : animals)
    {
        animal->talk();
    }


Now with static polymorphism
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template<typename T>
class Animal
{
public:
    void talk()
    {
        static_cast<T*>(this)->talkImpl();
    }
};

class Cat : public Animal<Cat>
{
    friend class Animal;
private:
    void talkImpl()
    {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal<Dog>
{
    friend class Animal;
private:
    void talkImpl()
    {
        std::cout << "Voof!" << std::endl;
    }
};

and while using it
1
2
3
4
5
6
7
8
9
    std::vector<std::unique_ptr<Animal<WHAT_HERE>>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<Animal<WHAT_HERE>> &animal : animals)
    {
        animal->talk();
    }


So coming to the question. While using static polymorphism are we giving up the ability to control every derived class without knowing what class they are? Or is there a way to this?
Last edited on Jul 21, 2015 at 5:41pm
Jul 21, 2015 at 6:01pm
Unless I'm missing something, your "WHAT HERE" comments are a problem. You no longer have a common base class. Because Animal is a template class, Cat derives from Animal<Cat> and Dog derives from Animal<Dog>. There is no such thing as an Animal, so you cannot have common pointers to a base class.
Jul 21, 2015 at 6:12pm
What you have is called CRTP, Curiously Recurring Template Pattern, where a class inherits from a template and passes itself as a template parameter.
Jul 21, 2015 at 6:48pm
Yeah, and thats the reason, we give up(dont have) the ability of controlling derived classes while using static polymorphism right?

As a second question, do we have a workaround for this? To have that ability.

EDIT: Are there maybe other methods to create static polymorphism other than crtp?
Last edited on Jul 21, 2015 at 6:49pm
Jul 21, 2015 at 7:02pm
What's the motivation of static polymorphism in C++
http://stackoverflow.com/a/19062918
Jul 21, 2015 at 9:20pm
@Duoas, i think, only after writing an example of static polymorphism i realized that such a thing was not possible. Which shocked me. It is that ability which amazes me about dynamic polymorphism. Thank you for the link by the way.

So i realized that it actually is a trade off. You choose which one better suits your needs.

Thanks for answering everyone.
Jul 22, 2015 at 12:58am
You can have your template class inherit from a non-template base class, and thus have a common base class.
Jul 22, 2015 at 8:59am
You can have your template class inherit from a non-template base class, and thus have a common base class.
Which comes back to using a mixture of static and dynamic polymorphism and therefore has no advantages over normal dynamic polymorphism, correct?
Jul 22, 2015 at 12:05pm
Even if we do so, cant use it for that purpose. For example:
1
2
3
4
5
6
7
8
9
10
    std::vector<std::unique_ptr<NonTemplateBase>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<NonTemplateBase> &animal : animals)
    {
        animal->talk();    // error: It is no longer Animal class so no talk() function
                           // Casting it is also impossible
    }
Last edited on Jul 22, 2015 at 12:06pm
Jul 22, 2015 at 12:25pm
Even if we do so, cant use it for that purpose. For example:

sure, just put a pure virtual method named talk in the non-template-base class.
Still, as mentioned before this involves dynamic polymorphism so you don't get any advantages.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <memory>

class AnimalBase {
public:
    virtual void talk() const = 0;
};
template <typename T>
class Animal : public AnimalBase {
public:
    void talk() const final override { static_cast<const T*>(this)->talk_impl(); }
};

class Cat : public Animal<Cat> {
public:
    void talk_impl() const
    {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal<Dog> {
public:
    void talk_impl() const
    {
        std::cout << "Voof!" << std::endl;
    }
};

int main()
{
    std::vector<std::unique_ptr<AnimalBase> > va;
    va.push_back(std::make_unique<Dog>());
    va.push_back(std::make_unique<Cat>());
    va.push_back(std::make_unique<Dog>());
    
    for(const auto& a : va)
        a->talk();
}
Last edited on Jul 22, 2015 at 12:35pm
Jul 22, 2015 at 12:56pm
@Gamer2015 Exactly :)
Last edited on Jul 22, 2015 at 12:57pm
Jul 22, 2015 at 2:00pm
Still, as mentioned before this involves dynamic polymorphism so you don't get any advantages.

Wrong. You may not get the advantages of static polymorphism, but you do get the advantages of dynamic polymorphism.

The undertone of this thread, explicit or not, intended or not, is that static polymorphism is better than dynamic polymorphism. That's like saying a screwdriver is better than a hammer. You can use a screwdriver to drive a nail, but a hammer is much more suited to the job. There are many times when dynamic polymorphism is exactly what is needed, and trying to use static polymorphism just won't get the job done.
Jul 22, 2015 at 2:27pm
Guys calm down.

I am not saying one is better. I said
i realized that it actually is a trade off. You choose which one better suits your needs.


So i am on the side, whichever better fits your needs, use it.
Jul 22, 2015 at 8:42pm
Wrong. You may not get the advantages of static polymorphism, but you do get the advantages of dynamic polymorphism.
I meant to say "so you don't get any advantages by using static polymorphism in this case" but I don't know what else I could've wanted to say that you needed to "correct" me

still, i think this thread is done, I hope we could help you Ceset :)
Last edited on Jul 22, 2015 at 8:42pm
Jul 23, 2015 at 7:46am
Yes it is done and i appreciate every help
Topic archived. No new replies allowed.