0

I have a collection of class objects I want to iterate and I want them to expose a virtual function.

std::vector<Base*> sampleVector;
//...
for (auto t : sampleVector) t->Function();

The most obvious way of dealing with this would be with basic polymorphism

class Base
{
public:
    virtual void Function() {} //(or = 0 if I want it to be pure virtual)
}

class Derived : public Base
{
public:
    void Function() override { std::cout << "Derived" << std::endl; }
}

On the other hand, a Hybrid CRTP way might be like this

class Base
{
public:
    virtual void Function() {} //(or = 0 if I want it to be pure virtual)
}

template <typename T>
class CRTPBase : public Base
{
public:
    void Function() override { T::Implementation(); }
}

class Derived : public CRTPBase<Derived>
{
public:
    void Implementation() { std::cout << "Derived" << std::endl; }
}

I was thinking that the first one might be better since the resulting API might be more intuitive (user-defined classes would only have to inherit from Base). However the CRTP way doesn't look much less intuitive, and performance might benefit if many Derived classes are defined (simpler virtual method table). What is your opinion on this? Am I overthinking it?

M. P.
  • 161
  • 1
  • 6
  • Why do you think the number of derived classes as any influence on the virtual method table? – AVH Oct 26 '20 at 11:12
  • Wouldn't it be more complex if I overrode ("overrode"?) the same function in multiple classes? I think it would have more entries and with that more indirection, meaning I might be more likely to get cache misses. Am I wrong? I'm still kinda new to all of this. I thought that was one of the main benefits of CRTP over basic polymorphism – M. P. Oct 26 '20 at 11:19
  • 1
    I'd say the most important thing here is to not optimize things which don't need optimizing (see e.g. https://stackoverflow.com/questions/385506/when-is-optimisation-premature). Secondly, the virtual function table contains 1 entry per virtual function. There's only 1 virtual function in your example, so there would be only 1 entry in the table. See e.g. https://stackoverflow.com/questions/99297/how-are-virtual-functions-and-vtable-implemented for some more info. – AVH Oct 26 '20 at 11:22
  • I thought virtual tables were defined per-function, not per-class. Thanks to your link everything is much clearer now. I'm wondering if there's any benefit at all with the CRTP way of doing this or if it's just dumb. The reason why I always have problems with premature optimization is that I don't just want to solve my problem, I also get way too curious about alternatives. – M. P. Oct 26 '20 at 11:49
  • I personally don't see how the CRTP is going to help you out here. You explicitly mention that you want a bunch of pointers to `Base`. If you go the CRTP route, you'll still have `virtual CRTP::Function ()` virtual, so you end up with the exact same thing as regular `Base` & `Derived` example, with an extra unnecessary step in between. – AVH Oct 26 '20 at 13:01
  • 1
    To piggyback on my last comment: you'd use CRTP for example if you want similar functionality in a bunch of unrelated classes. Which is exactly the reason it doesn't seem like a good fit for this particular problem, since you want your all classes to derive from `Base`. – AVH Oct 26 '20 at 13:04
  • The simplest, easiest to maintain, easiest for the caller is preferable, unless profiling has indicated that due to performance concerns (based on actual measured data) a more complex or complicated solution is warranted. – Eljay Oct 26 '20 at 13:50
  • If you *can't* use Base as a base class for your objects, because perhaps you don't own the code for object, or some of the objects are primitive types like `int`, you could use this concept modeling technique: https://stackoverflow.com/a/63743699/4641116 – Eljay Oct 26 '20 at 13:58

0 Answers0