在模板中使用非虚拟调度

Use non-virtual dispatch in a template

本文关键字:虚拟 调度      更新时间:2023-10-16

我想调用一个虚拟的成员函数(在大多数地方使用继承来保持简单),但有时我想在性能关键的地方强制使用非虚拟调度来调用它,在这种地方,确切的类型是已知的编译时。我这样做是出于性能原因,在虚拟呼叫性能较差的平台上。对于大多数功能来说,虚拟功能的开销是可以的,但对于少数功能来说则不然。我希望避免将所有功能都复制为虚拟和非虚拟功能。

示例:

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;
}

如果你知道确切的类型,你可以这样做:

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

您需要手动向下转换到所需类型的位置(如果您确实知道类型,static_cast也可以)。然后,您需要限定方法调用,禁用动态调度。

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
}

请注意,使用限定名称将禁用动态调度,这意味着它不会被调度到对象的运行时类型,而是被调度到您让它调用的类型。

我认为您正在寻找一种能够实现静态多态性的奇怪递归模板模式(CRTP):

template <typename Derived>
class Base {
public:
    virtual ~Base() {}
    void foo() { Derived::func_in_derived(); }
};
class Derived : public Base<Derived> {
public:
    void func_in_derived() {}
};