2014-02-02 2 views
0

У меня есть базовый класс , из которого я получаю различные другие классы сообщений, например MessageDerived. У меня есть еще один класс, который делает некоторую обработку различных типов данных, включая шаблон метода Catchall:C++: «специализация» шаблона функции-члена для работы с производными классами из определенного базового класса

struct Process { 
    void f(int a); 
    void f(const char* b); 
    template<typename T> void f(const T &t) { ... } 
}; 

Так что, если я называю Process::f на объект сообщения, шаблонный метод называется.

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

struct ProcessDerived : public Process { 
    void f(const MesaageBase& m) { ... } // Custom functionality for messages. 
}; 

Но это работает только тогда, когда я называю ProcessDerived::f на объекта. Если я вызываю его на объект MessageDerived, вместо этого выбирается шаблон.

Есть ли способ получить настраиваемую функцию, выбранную для всех классов сообщений, позволяя шаблону захватывать все остальные типы?

ответ

2

Здесь вы должны использовать SFINAE. Вот пример (обратите внимание, что для работы требуется C++ 11):

struct ProcessDerived : public Process 
{ 
    template<typename T> void f(const T &t, typename std::conditional<std::is_base_of<MessageBase, T>::value, int, void>::type = 0) 
    { 
    /// do something specific 
    } 

    template<typename T> void f(const T &t, ...) 
    { 
    return Process::f (t); 
    } 
}; 

};

Вы можете прочитать об этом в http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error

0

ProcessDerived :: F тени все определения процесса :: F (см здесь: Overloading rules for inheritance in C++). Поэтому вызов ProcessDerived :: f с объектом MessageDerived вызывает ProcessDerived :: f (const MessageBase &), поскольку это единственный видимый f, но, например,

ProcessDerived pd; 
pd(42); 

не компилируется. Вам необходимо добавить

using Process::f; 

in ProcessDerived для проблемы, описанной выше. Однако решение, предложенное Алексом Телишевым, когда я писал, исправляет обе проблемы сразу.

Смежные вопросы