在模板中使用非虚拟调度

发布于 2024-11-16 02:14:17 字数 520 浏览 1 评论 0原文

我想调用一个虚拟的成员函数(在大多数地方使用继承来使事情变得简单),但有时我想在性能关键的地方强制使用非虚拟分派来调用它,在这些地方,确切的类型是已知编译时间。我这样做是出于性能原因,在虚拟调用性能很差的平台上。对于大多数功能来说,虚拟函数的开销还可以,但对于少数功能来说则不然。我想避免将所有功能复制为虚拟和非虚拟。

例子:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二智少女猫性小仙女 2024-11-23 02:14:17

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

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
}

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

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.

水晶透心 2024-11-23 02:14:17

我认为您正在寻找 Curiously Recurring Template Pattern (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() {}
};

I think you are looking for Curiously Recurring Template Pattern (CRTP) which enables you static polymorphism :

template <typename Derived>
class Base {
public:
    virtual ~Base() {}
    void foo() { Derived::func_in_derived(); }
};
class Derived : public Base<Derived> {
public:
    void func_in_derived() {}
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文