Существует два пути.
первый - путем определения интерфейса статически для структуры типов:
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
Настолько объединяющийся определение структуры/интерфейса и вычет типа времени компиляции в Ваших функциях позволяет Вам делать статическую отправку вместо динамической отправки. Это - сущность статического полиморфизма.
Я искал достойные обсуждения CRTP сам. Todd Veldhuizen Методы для Научного C++ является большим ресурсом для этого (1.3) и много других усовершенствованных методов как шаблоны выражения.
кроме того, я нашел, что Вы могли прочитать большую часть исходной статьи Gems C++ Coplien в книгах Google. Возможно, это все еще имеет место.
Я должен был искать CRTP. Сделав это, однако, я нашел некоторый материал [приблизительно 111] Статический Полиморфизм . Я подозреваю, что это - ответ на Ваш вопрос.
оказывается, что ATL использует этот шаблон вполне экстенсивно.
Этот ответ Википедии имеет все, в чем Вы нуждаетесь. А именно:
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: