У меня есть базовый класс MessageBase
, из которого я получаю различные другие классы сообщений, например MessageDerived
. У меня есть еще один класс, который обрабатывает некоторые типы данных, включая шаблон метода catchall:
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
объекта MessageBase
. Если я вызываю его на объект MessageDerived
, вместо этого выбирается метод шаблона.
Есть ли способ получить пользовательскую функцию, выбранную во всех классах сообщений, позволяя шаблону захватывать все остальные типы?
Здесь вы должны использовать SFINAE. Вот пример (обратите внимание, что для работы требуется С++ 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
ProcessDerived :: f затеняет все определения процесса :: f (см. Здесь: Правила перегрузки для наследования в C++). Поэтому вызов ProcessDerived :: f с объектом MessageDerived вызывает ProcessDerived :: f (const MessageBase &), поскольку это единственный видимый f, но, например,
ProcessDerived pd;
pd(42);
не будет компилироваться. Вам нужно добавить
using Process::f;
в ProcessDerived для проблемы, описанной выше. Однако решение, предложенное Алексом Телишевым, когда я писал, исправляет обе проблемы сразу.