c++stdany

Is there any way to cast a std::any containing a derived pointer to a base pointer, without knowing the derived type?


Let's say I have a std::any object which may or may not contain a pointer to some derived class of a given base class B. Is there any way I can do something that:

  1. Returns a B *, if the std::any object holds something convertible to B *, or
  2. Throws an exception if not?

It seems like dynamic_cast and std::any_cast each provide one half of this functionality, but I don't see any way of putting the two together.

I'm aware that I can make this work in various ways that involve explicitly enumerating every type convertible to B *, but that's the mother of all DRY violations.


Sample use case:

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);
}

I don't want to include a bunch of boilerplate code listing every single kind of saw in existence just so I can grab a saw -- any Saw -- to use in Factory1.


Solution

  • This is unachievable. It is only possible to get an object out from std::any using exactly the type that was put inside. Thus, you must know the type to get anything out of it.

    It seems that std::any does not fit your use case.