1

I am interrested in interface implementation. I know the standard way of doing so is to code a class having pure virtual methods which is going to be used as interface, for instance:

class Interface {
public:
  virtual void doSometing() = 0;
}

and to have it used:

class Implementation : public Interface {
public:
  virtual void doSomething() override { ... }
}

Or even better to apply NVI (non virtual interface).

But all those use virtual functions which I am trying to avoid - as I am coding for embedded where performance loss due to vtable indirections must be considered.

Threfore I focused onto 'static polymorphism' and try to use CRTP to implement the interfaces:

template<typename T>
class Interface {
public:
  void doSomething() {
    static_cast<T&>(*this)._doSomething();
}

class Implementation : public Interface<Implementation> {
public:
  void _doSomething() { /* Do implementation specific stuff here */ }
}

class Implmentation2 : public Interface<Implementation2> {...}

So far so good. But there is one big trouble I see. Once I want to store a bunch of pointers to the interface to some container and want to access the instances of various implementation classes I face the trouble the Interface<T> is allways a different class by itself, not a single interface:

Interface<Implementation> and Interface<Implementation2> are different types.

Ok, let's make a common base class to derive the interfaces from...

template<typename T>
class Interface : public IfaceBase {
public:
  void doSomething() {
    static_cast<T&>(*this)._doSomething();
}

...but then I cannot access the final instance using the interface. It seems to me I am trying to create interface to interface which sounds crazy by itself anyway...

So I found CRTP not too usable in this case. I have searched the internet and have found MIXIN which seems to be a "CRTP turned upside down". But I am not sure whether it can be used for my purpose...

Could you please help me? If there is a way how to apply MIXINS or any other idiom/whatever to have C++ interfaces without virtuals, please share the idea :)

Many thanks in advance to anybody willing to help! Cheers Martin

Martin Kopecký
  • 912
  • 5
  • 16
  • Have you actually measured the performance impact of virtual functions on your system? It is possible that you are optimizing prematurely in this case. – r3mus n0x Jun 19 '19 at 06:01
  • 2
    If you want to invoke type-specific functions on the elements of a heterogeneous container, you’re going to do something *awfully* similar to virtual dispatch regardless of what syntax you use. – Davis Herring Jun 19 '19 at 06:33
  • No, I have not measured the impact of virtual function in my system as it is in early implementation phase. I am aware I might be optimizing prematurely but once there is a known solution to that (maybe not known to me - that's why I am asking) I find it better to implement the it the right way from the beginning than rewriting the whole think once again in the future. My style is think twice first and then write it once. So please understand my question as rather concept clarification now... – Martin Kopecký Jun 19 '19 at 07:59
  • @r3musn0x Lets assume I am not optimizing prematurely, do you know whether there is a way to implement static interfaces by Mixins or aby other construct? – Martin Kopecký Jun 19 '19 at 09:20

1 Answers1

1

I know two ways of calling non-virtual methods from different types in a polymorphic way:

  1. Type erasure: wraps non-virtual classes into others that have virtual methods (this is relatively close to what you attempted).
  2. Visitor pattern applied to variant types. This one requires all types to be known at compile time where the method is called.

Since you don't want virtual methods at all, I'll only explain solution 2. If you're more interested about type erasure, C++ 'Type Erasure' Explained (Dave Kilian's blog) is a good read.

Visitor pattern & variant types (C++17)

Assuming you have types with non virtual methods:

class Implementation1 {
    void doSomething() { /* ... */ }
};

class Implementation2 {
    void doSomething() { /* ... */ }
};

You can store any combinaison of them in a container using std::variant:

// #include <variant>
// #include <vector>
using ImplVariant = std::variant<Implementation1,Implementation2>;
std::vector<ImplVariant> array = {Implementation2(), Implementation1() /*, ...*/};

To call doSomething on a MyVariant object, you apply a visitor to it. This is simply done in C++17 by passing a generic lambda to std::visit:

for (auto& variant : array) {
    std::visit([](auto&& object) { object.doSomething(); }, variant);
}

Live demo

Alternatively, you can make a variant of (smart) pointers.

  • Note that `std::variant`'s codegen is not great in many (all?) implementations at the moment, sadly. So I would measure, because it is possible that the virtual functions approach happens to be faster. – Acorn Jun 21 '19 at 09:14
  • @Acorn - Why do you think `std::variant` is not mature enough to be used? What is the limit? – Martin Kopecký Aug 30 '19 at 14:01
  • @MartinKopecký Check the codegen for several compilers even with trivial examples and you will see for yourself :) There have been a bunch of posts and articles over the years about it. See for instance [this question](https://stackoverflow.com/questions/57726401/stdvariant-vs-inheritance-vs-other-ways-performance) or [this one from today](https://stackoverflow.com/questions/47383563/is-there-any-hope-to-call-a-common-base-class-method-on-a-stdvariant-efficient) (it is a recurring topic!). – Acorn Aug 31 '19 at 06:52
  • @Acorn Thanks for the links. I have read the one with benchmarks and the conclusion I made was that once the optimizations are turned off, the approach of using std::variant is not slower than virtual functions, am I right? Also the question seems to be rather about which way of accessing the variant’s value is chosen than about the usage of variant itself, isn’t it? – Martin Kopecký Aug 31 '19 at 08:01