Search code examples
c++templatesvirtual

Use non-virtual dispatch in a template


I want to call a member function which is virtual (inheritance is used in most places to keep things simple), but I want to force calling it using non-virtual dispatch sometimes, in performance critical places, and in such places the exact type is known compile time. I do this for performance reasons, on a platform where virtual call performance is bad. For most functionality the overhead of virtual functions is fine, but for a few it is not. I would like to avoid duplicating all functions as both virtual and non-virtual.

Example:

class Interface
{
  public:
  virtual void Do(){}   
};

class Implementation: public Interface
{
  public:
  virtual void Do(){}   
};


void DoIt(Interface &func)
{
  func.Do();
};

int main()
{
  Implementation a;
  DoIt(a);
  // can DoIt be constructed as a template to avoid virtual dispatch?
  return 0;
}

Solution

  • If you know the exact type you can do it as:

    template <typename StaticType>
    void DoIt(Interface &func)
    {
      static_cast<StaticType&>(func).StaticType::Do();
    };
    

    Where you need to manually downcast to the type you need (static_cast is fine if you do know the type). Then you need to qualify the method call, do disable dynamic dispatch.

    struct DerivedType : Interface {
        virtual void Do() { std::cout << "Derived::Do" << std::endl; }   
    };
    struct MostDerived : DerivedType {
        virtual void Do() { std::cout << "MostDerived::Do" << std::endl; }
    };
    void processDerived( Interface & iface ) {
       DoIt<DerivedType>( iface );
    }
    int main() {
       MostDerived obj;
       DoIt<Derived>( obj );    // Will call Derived::Do
    }
    

    Note that using the qualified name will disable dynamic dispatch, and that means that it will not be dispatched to the runtime type of the object, but to the type that you tell it to call.