Ответ в полном обобщении должен включать двойную рассылку.Идея состоит в том, что если у вас есть n
различных подклассов PacketInfo
, вам нужно n * (n - 1) / 2
реализации оператора сравнения.Действительно, что произойдет, если вы сравните CustomInfo
с AwesomePersonalInfo
?Это предполагает знание всей иерархии заблаговременно, и пример кода представлен в этом вопросе SO .
Если вы уверены, что вы можете применить карту с идентичными типами внутри(и поэтому вы уверены, что вам нужны только операторы n
), тогда нет смысла иметь map<PacketInfo, X>
.Просто используйте map<ConcretePacketInfo, X>
.
Есть несколько способов сделать это.Здесь проще всего сделать шаблон Processor
для типа пакета, возможно, сделав его наследником от класса BasicProcessor
, если вы хотите «стереть» параметр шаблона где-нибудь и вычислить общий код.
Другойдешевое решение заключается в следующем: сохранить код как есть, но сделать Processor
шаблоном, который определяет только соответствующий addPacket
:
class BasicProcessor
{
private:
template <typename T> struct pless
{
bool operator()(T const* a, T const* b) const
{
assert(a && b);
return *a < *b;
}
};
protected:
std::map<PacketInfo const*, X, pless<PacketInfo>> packets;
};
// You only need these lines in a public header file.
template <typename Packet>
class Processor : public BasicProcessor
{
public:
void addPacket(Packet const* p, X const& x)
{
this->packets[p] = x;
}
};
Это гарантирует, что вызывающая сторона будет манипулировать объектом Processor<CustomPacket>
итолько добавьте правильный тип пакета.На мой взгляд, класс Processor
должен быть классом шаблона.
Этот метод называется Тонкий шаблон идиома , где базовая реализация не являетсявведите safe (чтобы избежать раздувания кода относительно шаблонов), но добавьте тонкий слой шаблонов, чтобы восстановить безопасность типов на уровне интерфейса.