Девиртуализация может помочь или нет, в зависимости от того, строит ли ваш компилятор ваш материал.
Обратите внимание, что CRTP обычно используется для реализации миксинов и шаблона метода шаблона, например. как это:
template <typename T, typename Derived>
class pointer_base {
const Derived& self() const { return static_cast<const Derived&>(*this); }
public:
T& operator *() const { return *self().get(); }
T* operator ->() const { return self().get(); }
};
template <typename T>
class smart_pointer : public pointer_base<T, smart_pointer<T>> {
public:
T* get() const;
};
И форме виртуального вызова:
template <typename T>
class pointer_base {
protected:
~pointer_base() = default;
public:
virtual T* get() const = 0;
T& operator *() const { return *get(); }
T* operator ->() const { return get(); }
};
template <typename T>
class smart_pointer : public pointer_base<T> {
public:
T* get() const override;
};
Использование в любом случае
smart_pointer<int> p(new int);
*p = 42;
Обратите внимание, что там может быть несколько различных смарт-классов указатель. В версии виртуальной функции все они происходят из одного и того же pointer_base. Это означает, что существует одна версия базовой функции, которая будет использоваться для всех из них. И если это так, девиртуализация не может работать.
Он будет работать только в том случае, если соответствующая функция встроена в вызывающего абонента, потому что тогда компилятор может специализировать код для конкретного конкретного типа интеллектуального указателя.
Конечно, с помощниками, настолько маленькими, шансы на то, что они становятся вложенными, высоки. С другой стороны, теперь у вас есть класс pointer_base, который клиенты видят и могут испытывать соблазн использовать. Вы можете получить конфиденциальность из базы, но затем вам нужно добавить использование объявлений для всех участников, которые вы хотите открыть в каждом производном классе. С такими классами, как pointer_base, который состоит из лотов (2 в моем случае, но на самом деле также должно быть логическое преобразование) небольших функций, это раздражает. Но тогда и синтаксический беспорядок CRTP. Думаю, дело доходит до вкуса.
Когда у вас есть только один, большой метод шаблона, компилятор не сделает его наиболее вероятным. В этом случае он не может девитировать. Но CRTP имеет свой собственный недостаток: метод дублируется для каждого экземпляра базы, независимо от того, хотите вы этого или нет. Это может привести к раздуванию кода.
Таким образом, это в конечном итоге сводится к обычному вопросу о шаблонах и виртуальных функциях: специализированный код с соответствующим увеличением размера кода или ограничение производительности виртуальных вызовов и встроенный барьер, который они создают.
Отличное объяснение, спасибо. – Jepessen