CRTP для предотвращения динамического полиморфизма

88
задан Lightness Races with Monica 20 November 2011 в 13:45
поделиться

4 ответа

Существует два пути.

первый - путем определения интерфейса статически для структуры типов:

template <class Derived>
struct base {
  void foo() {
    static_cast<Derived *>(this)->foo();
  };
};

struct my_type : base<my_type> {
  void foo(); // required to compile.
};

struct your_type : base<your_type> {
  void foo(); // required to compile.
};

второй - путем предотвращения использования ссылки на основу или идиомы указателя на основу, и сделайте проводное соединение во время компиляции. Используя вышеупомянутое определение, у Вас могут быть шаблонные функции, которые похожи на них:

template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
  obj.foo(); // will do static dispatch
}

struct not_derived_from_base { }; // notice, not derived from base

// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload

Настолько объединяющийся определение структуры/интерфейса и вычет типа времени компиляции в Ваших функциях позволяет Вам делать статическую отправку вместо динамической отправки. Это - сущность статического полиморфизма.

136
ответ дан Dean Michael 24 November 2019 в 07:33
поделиться

Я искал достойные обсуждения CRTP сам. Todd Veldhuizen Методы для Научного C++ является большим ресурсом для этого (1.3) и много других усовершенствованных методов как шаблоны выражения.

кроме того, я нашел, что Вы могли прочитать большую часть исходной статьи Gems C++ Coplien в книгах Google. Возможно, это все еще имеет место.

18
ответ дан fizzer 24 November 2019 в 07:33
поделиться

Я должен был искать CRTP. Сделав это, однако, я нашел некоторый материал [приблизительно 111] Статический Полиморфизм . Я подозреваю, что это - ответ на Ваш вопрос.

оказывается, что ATL использует этот шаблон вполне экстенсивно.

1
ответ дан Roger Lipscombe 24 November 2019 в 07:33
поделиться

Этот ответ Википедии имеет все, в чем Вы нуждаетесь. А именно:

template <class Derived> struct Base
{
    void interface()
    {
        // ...
        static_cast<Derived*>(this)->implementation();
        // ...
    }

    static void static_func()
    {
        // ...
        Derived::static_sub_func();
        // ...
    }
};

struct Derived : Base<Derived>
{
    void implementation();
    static void static_sub_func();
};

, Хотя я не знаю, насколько это на самом деле покупает Вас. Издержки вызова виртуальной функции (зависимый компилятора, конечно):

  • Память: Один указатель функции на Время выполнения виртуальной функции
  • : Один вызов указателя функции

, В то время как издержки статического полиморфизма CRTP:

  • Память: Дублирование Основы на шаблонное инстанцирование
  • Время выполнения: Один вызов указателя функции + безотносительно static_cast делает
-4
ответ дан user23167 24 November 2019 в 07:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: