Использовать не виртуальную отправку в шаблоне - PullRequest
1 голос
/ 17 июня 2011

Я хочу вызвать функцию-член, которая является виртуальной (наследование используется в большинстве мест для простоты), но я хочу иногда вызывать ее с помощью не виртуальной диспетчеризации, в местах, критичных к производительности, и в таких местах Точный тип известен время компиляции. Я делаю это по соображениям производительности на платформе, где производительность виртуальных вызовов плохая. Для большинства функций накладные расходы виртуальных функций - это хорошо, но для некоторых это не так. Я хотел бы избежать дублирования всех функций как виртуальных, так и не виртуальных.

Пример:

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

Ответы [ 2 ]

2 голосов
/ 17 июня 2011

Если вы знаете точный тип, вы можете сделать это как:

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
}

Обратите внимание, что использование полного имени отключит динамическую диспетчеризацию, и это означает, что оно будет отправлено не типу объекта времени выполнения, а типу, который вы указали для вызова.

1 голос
/ 17 июня 2011

Я думаю, что вы ищете шаблон CURLY 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() {}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...