C ++: «специализация» шаблона функции-члена для работы с производными классами из определенного базового класса

0

У меня есть базовый класс 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, вместо этого выбирается метод шаблона.

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

Теги:
templates
overload-resolution

2 ответа

2
Лучший ответ

Здесь вы должны использовать 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

0

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

ProcessDerived pd; 
pd(42);

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

using Process::f;

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню