Bonjour à tous.
Dans le cadre du défi Javaquarium, je me suis dis que j’allais me lancer dans un ECS en C++ moderne pour me faire la main. J’en suis à la partie où j’assigne des components à des entités. Le code suivant marche, mais je trouve le hack pas terrible.
class EntitiesComponentsManager
{
public:
/**
* @brief Assigne un composant à l'entité donnée.
*
* @param entity L'entité à laquelle rattacher les composants.
* @param component Le composant à rattacher.
* @pre Le composant ne doit pas déjà être rattaché à l'entité.
* @post Le composant est bien rattaché à l'entité.
*/
void assignComponent(Entity entity, components::Component && component);
/**
* @brief Associe un ou plusieurs composants à une entité.
*
* @tparam Components
* @param entity L'entité à laquelle rattacher les composants.
* @param first Le premier composant à rattacher.
* @param components Un nombre indéfini de composants.
* @pre Tous les composants doivent dériver du type components::Component.
*/
template <typename Component, class ...Args>
void assignComponents(Entity entity, Component && first, Args&&... components)
{
static_assert((std::is_base_of_v<components::Component, Args>&& ...), "All components must be sub-types of components::Component.");
assignComponent(entity, std::forward<components::Component>(first));
// Hack pour permettre l'ajout des composants variadiques sans erreur.
int _[] { 0, (assignComponent(entity, std::forward<components::Component>(components)), 0)... };
// Cast pour empêcher le compilateur de se plaindre.
(void)_;
}
// Du code...
};
Code que j’utilise ensuite comme ça.
Entity create_seeweed(EntitiesComponentsManager & manager) noexcept
{
using namespace components;
Entity seeweed { generate() };
// Une algue vit.
Health health {};
health.life = 15;
health.state = Health::State::Good;
// Ajout de tous les composants pour une algue.
manager.assignComponents(seeweed, health, Vegetal {});
return seeweed;
}
N’y a t-il pas mieux que la ligne suivante pour arriver à mes fins ? Ça marche bien, ça fait ce que je veux, mais ça n’a pas l’air très propre.
// Hack pour permettre l'ajout des composants variadiques sans erreur.
int _[] { 0, (assignComponent(entity, std::forward<components::Component>(components)), 0)... };
Merci d’avance à tous pour votre aide.
EDIT : j’ai trouvé cette solution aussi, mais je ne sais pas ce qu’elle vaut. Est-elle mieux ?
template <typename Component, class ...Args>
void assignComponents(Entity entity, Component && first, Args&&... components)
{
assignComponent(entity, std::forward<components::Component>(first));
(assignComponent(entity, std::forward<components::Component>(components)), ...);
}
+0
-0