J'essaie d'écrire un système de messagerie avec des modèles, le modèle de visiteur et avec l'aide de CRTP. Je comprends ces concepts mais je suis dans une situation où je dois retrouver un type "perdu". J'ai une classe Base
et je veux trouver un Derived<T>
. C'est "deux" types à déduire [Derived
pourrait être n'importe quoi, T
pourrait être quelque chose] (même si c'est considéré comme un type).Récupérer le type d'un modèle de classe dans un modèle de visiteur
J'ai essayé de faire usage d'un deuxième modèle de visiteur, qui semble lourd et fou mais je n'ai trouvé aucune solution de travail. Même si c'est lié au jeu, c'est juste un exemple, il pourrait être appliqué à d'autres programmes, je suppose, je ne peux pas l'exposer dans un autre contexte.
Voici la dénomination je (avec des exemples inutiles):
SubscriberBase
est une classe qui envoie et reçoit des messages (comme un client réseau)Broadcaster
est le pont entre les abonnés (comme un réseau commutateur/serveur) et contient un vecteur deSubscriberBase
.
je suis venu avec ce code minimal:
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
};
Le problème est le type THE_ACTUAL_SUBSCRIBER_TYPE
. Cela pourrait être n'importe quel abonné "concret"; dans ce cas, il serait par exemple EntityCache
ou quelque chose d'autre comme Logger
, CommandRecorder
...
J'ai essayé d'utiliser un autre CRTP couplé avec une autre classe:
class SubscriberBase {};
template<typename TSubscriber>
class Subscriber : public SubscriberBase { /* some other visitor pattern ? */ };
class EntityCache : public Subscriber<EntityCache>, /* ... */
sans succès.
Toutes les idées sont appréciées, merci :)