Ich versuche, ein Messaging-System mit Vorlagen, das Besuchermuster und mit Hilfe von CRTPs zu schreiben. Ich verstehe diese Konzepte, aber ich bin immer noch in einer Situation, in der ich einen "verlorenen" Typ wiederfinden muss. Ich habe eine Base
Klasse und ich möchte eine Derived<T>
finden. Das sind "zwei" Typen, die abzuleiten sind [Derived
könnte alles Mögliche sein, T
könnte alles sein] (selbst wenn es als ein Typ betrachtet wird).Retreive den Typ einer Klassenvorlage in einem Besuchermuster
Ich habe versucht, ein zweites Besuchermuster zu verwenden, das schwer und verrückt scheint, aber ich habe keine funktionierende Lösung gefunden. Auch wenn es spielbezogen ist, ist es nur ein Beispiel, es könnte auch auf andere Programme angewendet werden, ich kann es nicht in einem anderen Kontext darstellen. Hier
ist die Namensgebung I (mit unnötigen Beispielen) verwendet:
SubscriberBase
ist eine Klasse, die Nachrichten sendet und empfängt (wie ein Netzwerk-Client)Broadcaster
die Brücke zwischen den Teilnehmern ist (wie ein Netzwerk Switch/Server) und enthält einen Vektor vonSubscriberBase
.
kam ich mit diesem minimalen Code oben:
class SubscriberBase {};
class Broadcaster {
std::vector<SubscriberBase*> subscribers;
public:
template<typename TMessage>
void broadcast(TMessage& message) {
for(auto subscriber : subscribers) {
// <<< Here is my problem <<<
message.accept<THE_ACTUAL_SUBSCRIBER_TYPE>(subscriber);
}
}
void attach(SubscriberBase* subscriber) {
subscribers.push_back(subscriber);
}
};
//Base class for handling messages of any type
template<typename TMessage>
class MessageHandler {
public:
virtual void handleMessage(TMessage& message) {}
};
//Base class for messages
template<typename TMessage>
class Message {
friend class Broadcaster;
private:
//Visitor pattern with CRTP
template<typename TSubscriber>
void accept(TSubscriber* subscriber) {
subscriber->handleMessage(*static_cast<TMessage*>(this));
}
};
//Messages
struct EntityCreated : public Message<EntityCreated> {};
struct EntityDestroyed : public Message<EntityDestroyed> {};
struct BurnAllGummyBears : public Message<BurnAllGummyBears> {};
//Subscribers
class EntityCache : public SubscriberBase,
public MessageHandler<EntityCreated>,
public MessageHandler<EntityDestroyed>,
public MessageHandler<BurnAllGummyBears>
{
public:
void handleMessage(EntityCreated& message) override { /* add to cache */ }
void handleMessage(EntityDestroyed& message) override { /* remove from cache */ }
//does not override BurnAllGummyBears because it's not relevant for EntityCache
};
Das Problem THE_ACTUAL_SUBSCRIBER_TYPE
der Typ ist. Es könnte jeder "konkrete" Abonnent sein; in diesem Fall wäre es sonst zum Beispiel EntityCache
oder so etwas wie Logger
, CommandRecorder
...
ich versucht, einen anderen CRTP mit einer anderen Klasse gekoppelt zu verwenden:
class SubscriberBase {};
template<typename TSubscriber>
class Subscriber : public SubscriberBase { /* some other visitor pattern ? */ };
class EntityCache : public Subscriber<EntityCache>, /* ... */
ohne Erfolg.
Alle Ideen geschätzt, danke :)