Ниже приведен очень простой пример того, что я понимаю как статический полиморфизм. Причина, по которой я не использую динамический полиморфизм, состоит в том, что я не хочу препятствовать встраиванию функций PROCESSOR
в op
,
template <class PROCESSOR>
void op(PROCESSOR* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
int main() {
ProcessorY py;
op<ProcessorY>(&py);
return 0;
}
Проблема с этим примером: не существует явного определения того, какие функции PROCESSOR
должен определить. Если один из них отсутствует, вы просто получите ошибку компиляции. Я думаю, что это плохой стиль.
Он также имеет очень практический недостаток: интерактивная помощь IDE, конечно, не может показать вам функции, доступные для этого объекта.
Что такое хороший / официальный способ определения публичного интерфейса PROCESSOR
?
Во-первых, я думаю, что нет проблем с вашим примером статического полиморфизма. Поскольку он статичен, то есть разрешен во время компиляции, он по определению предъявляет менее строгие требования к определению интерфейса.
Также абсолютно законно, что неправильный код просто не будет компилироваться / ссылаться, хотя более понятное сообщение об ошибке от компилятора будет лучше.
Однако если вы настаиваете на определении интерфейса, вы можете переписать свой пример следующим образом:
template <class Type>
class Processor
{
public:
void doSomething(int);
void doSomethingElse();
};
template <class Type>
void op(Processor<Type>* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
// specialization
template <>
class Processor<Type_Y>
{
// implement the specialized methods
};
typedef Processor<Type_Y> ProcessorY;
int main() {
ProcessorY py;
op(&py);
return 0;
}
Не существует четкого определения того, какие методы должен определять ПРОЦЕССОР. Если один из них отсутствует, вы просто получите ошибку компиляции. Я думаю, это плохой стиль.
Это. Это не. Это может быть. Это зависит.
Да, если вы хотите определить поведение таким образом, вы можете также ограничить содержимое, которое должны иметь параметры шаблона. К сожалению, это невозможно сделать прямо сейчас.
Что вы хотите ограничения и концепции функция, которая должна была появиться как часть C ++ 11, но была отложена и до сих пор недоступна в C ++ 14.
Однако получение ошибки во время компиляции часто является лучшим способом ограничения параметров шаблона. В качестве примера мы можем использовать std
библиотека:
1) Итераторы.
Библиотека C ++ определяет несколько типов итераторов: forward_iterator
, random_access_iterator
и другие. Для каждого типа определен набор свойств и допустимых выражений, которые гарантированно будут доступны. Если вы использовали итератор, это не полностью совместимо с random_access_iterator
в контейнере, который требует random_access_iterator
вы получите ошибку компилятора в некоторый момент (скорее всего, при использовании оператора разыменования ([]), который требуется в этом классе итераторов).
2) Распределители.
Все контейнеры в std
библиотека использует распределитель для выполнения выделения / освобождения памяти и построения объектов. По умолчанию, станд :: распределитель используется. Если вы хотите обменять его на свой, вы должны убедиться, что он имеет все, что std::allocator
гарантированно иметь. В противном случае вы получите ошибку во время компиляции.
Итак, пока мы не получим концепции, это лучшее и наиболее широко используемое решение.