macformula / racecar

Monorepo for all firmware running on our custom ECUs.
https://macformula.github.io/racecar/
9 stars 2 forks source link

Abstract classes vs templates / concepts #163

Open BlakeFreer opened 2 months ago

BlakeFreer commented 2 months ago

Our current architecture uses abstract classes to enable platform abstraction. This incurs a runtime overhead during virtual method table resolution despite the platform being fully determined at runtime.

Consider trying this approach:

Interface polymorphism

How can I define an interface class in CPP that compile-time resolves to a specific implementation to avoid the overhead of a virtual method table?

To define an interface in C++ that resolves to a specific implementation at compile time and avoids the overhead of a virtual method table (vtable), you can use templates. Here's how you can achieve this:

  1. Template-Based Interface

    Define the interface as a template class and provide a concrete implementation as a template parameter. This way, the compiler will instantiate the class with the specific implementation at compile time, avoiding the need for virtual methods.

    template <typename Implementation>
    class Interface {
    public:
        void DoSomething() {
            // Delegate the call to the implementation
            static_cast<Implementation*>(this)->DoSomething();
        }
    
        // Other methods can be defined similarly...
    };
  2. Concrete Implementation

    Next, define a concrete class that provides the actual implementation of the interface methods:

    class ConcreteImplementation {
    public:
        void DoSomething() {
            // Actual implementation
            std::cout << "Doing something in ConcreteImplementation" << std::endl;
        }
    
        // Other methods can be implemented here...
    };
  3. Using the Interface

    You can then use the interface by creating an instance of the interface template with the desired implementation:

    int main() {
        Interface<ConcreteImplementation> obj;
        obj.DoSomething();  // Calls ConcreteImplementation::DoSomething()
        return 0;
    }

Benefits:

Considerations:

Neither of these considerations affect our project as we will only use one platform at a time

This approach is ideal when you need high performance and know the implementation type at compile time.

Required Changes

We cannot provide the ConcreteImplementation in main as it violates platform abstraction. Is there a way to use concepts or templates to request an implementation from the platform layer?