Статический полиморфизм: как определить интерфейс?

Ниже приведен очень простой пример того, что я понимаю как статический полиморфизм. Причина, по которой я не использую динамический полиморфизм, состоит в том, что я не хочу препятствовать встраиванию функций 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?

5

Решение

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

Также абсолютно законно, что неправильный код просто не будет компилироваться / ссылаться, хотя более понятное сообщение об ошибке от компилятора будет лучше.

Однако если вы настаиваете на определении интерфейса, вы можете переписать свой пример следующим образом:

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

Другие решения

Не существует четкого определения того, какие методы должен определять ПРОЦЕССОР. Если один из них отсутствует, вы просто получите ошибку компиляции. Я думаю, это плохой стиль.

Это. Это не. Это может быть. Это зависит.

Да, если вы хотите определить поведение таким образом, вы можете также ограничить содержимое, которое должны иметь параметры шаблона. К сожалению, это невозможно сделать прямо сейчас.

Что вы хотите ограничения и концепции функция, которая должна была появиться как часть C ++ 11, но была отложена и до сих пор недоступна в C ++ 14.

Однако получение ошибки во время компиляции часто является лучшим способом ограничения параметров шаблона. В качестве примера мы можем использовать std библиотека:

1) Итераторы.

Библиотека C ++ определяет несколько типов итераторов: forward_iterator, random_access_iterator и другие. Для каждого типа определен набор свойств и допустимых выражений, которые гарантированно будут доступны. Если вы использовали итератор, это не полностью совместимо с random_access_iterator в контейнере, который требует random_access_iteratorвы получите ошибку компилятора в некоторый момент (скорее всего, при использовании оператора разыменования ([]), который требуется в этом классе итераторов).

2) Распределители.

Все контейнеры в std библиотека использует распределитель для выполнения выделения / освобождения памяти и построения объектов. По умолчанию, станд :: распределитель используется. Если вы хотите обменять его на свой, вы должны убедиться, что он имеет все, что std::allocator гарантированно иметь. В противном случае вы получите ошибку во время компиляции.

Итак, пока мы не получим концепции, это лучшее и наиболее широко используемое решение.

3

По вопросам рекламы [email protected]