2015-04-26 18 views
5

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

+0

Прежде всего, почему вы принимаете указатели? Во-вторых, определение дается вами в документации этого шаблона функции. – Columbo

+0

Кроме того, IDE, не показывающие список участников, не являются очень значительным недостатком. – Columbo

+0

Вам просто нужно подождать [Концепции TS] (http://en.cppreference.com/w/cpp/language/constraints). – hynner

ответ

1

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

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

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

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; 
} 
+0

Вам не хватает отличной возможности для CRTP. – Puppy

+1

@Puppy Просьба уточнить, как это улучшит ответ. –

+0

Я думаю, что @valdo дал хороший ответ на возможное решение этой проблемы. Но меня также интересовала идея CRTP. – Michael

3

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

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

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

Что вы хотите constraints and concepts особенность, которая должна была появиться в составе C++ 11, но был задержан и до сих пор не доступна в C++ 14.

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

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

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

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

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

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

+0

Концептуальные проверки можно легко эмулировать путем создания экземпляров ожидающих указателей функций элемента проверенного класса. –