8 votes

Existe-t-il un moyen de transformer un std::any contenant un pointeur dérivé en un pointeur de base, sans connaître le type dérivé ?

Disons que j'ai un std::any qui peut ou non contenir un pointeur vers une classe dérivée d'une classe de base donnée. B . Y a-t-il un moyen de faire quelque chose que :

  1. Retourne un B * si le std::any l'objet détient quelque chose de convertible en B * ou
  2. Lance une exception si ce n'est pas le cas ?

Il semble que dynamic_cast y std::any_cast fournissent chacun une moitié de cette fonctionnalité, mais je ne vois aucun moyen de réunir les deux.

Je suis conscient que je peux faire fonctionner cela de différentes manières qui impliquent l'énumération explicite de chaque type convertible en B * mais c'est la mère de toutes les violations de DRY.


Exemple de cas d'utilisation :

std::vector<std::any> setupTools(const std::string & confFile)
{
  std::vector<std::any> myTools;

  auto conf = parse(confFile);

  for(std::string & wrenchInfo : conf["Wrenches"])
  {
    Wrench::setup(myTools, wrenchInfo);
  }    

  for(std::string & hammerInfo : conf["Hammers"])
  {
    Hammer::setup(myTools, hammerInfo);
  }

   // 25 more kinds of tools
}

Factory1::init(const std::vector<std::any> & tools)
{
  m_wrench = any_get<Wrench *>(tools);
  m_hammer = any_get<Hammer *>(tools);
  m_saw = any_get<Saw *>(tools);
}

Factory2::init(const std::vector<std::any> & tools)
{
  m_wrench = any_get<TorqueWrench *>(tools);
}

Factory3::init(const std::vector<std::any> & tools)
{
  m_saw = any_get<CordlessReciprocatingSaw *>(tools);
}

Je ne veux pas inclure un tas de code passe-partout listant tous les types de scie existants juste pour pouvoir prendre une scie tout Saw -- à utiliser dans Factory1 .

3voto

user2079303 Points 4916

C'est irréalisable. Il n'est possible de faire sortir un objet que de std::any en utilisant exactement le type qui a été mis à l'intérieur. Ainsi, vous devez connaître le type pour en tirer quelque chose.

Il semble que std::any ne correspond pas à votre cas d'utilisation.

2voto

Je suis en retard pour la fête, je viens juste de tomber sur cette question en cherchant moi-même une réponse.

Voici ce que j'ai fini par mettre au point.

J'avais besoin de passer soit un wxMenuItem*, soit un pointeur vers une sorte de contrôle (tous sont dérivés de wxControl) à ma fonction dans une balise std::any . Je sais si j'ai un wxMenuItem* ou un contrôle basé sur des drapeaux. Ignorez donc les wxMenuItem* pour l'instant.

Comme mon code ne doit fonctionner qu'avec ce que la classe de base wxControl possède, (et j'imagine que puisque vos marteaux partagent une classe de base commune, vous ne voulez faire que des trucs de type marteau de base), je...

static_cast<wxControl*>(myCombo*)

au point d'appel, et

auto myPtr {std::any_cast<wxControl*>(theAnyField)};

au point appelé, et voilà.

0voto

Pedro NF Points 358

L'ajout d'une classe de base "Tool" qui possède un attribut enum ToolType peut être utile. Ensuite, en utilisant le ToolType, vous pouvez décider de la distribution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X