Digamos que eu tenho um std::any
objeto que pode ou não conter um ponteiro para alguma classe derivada de uma determinada classe base B
. Existe alguma maneira de fazer algo que:
- Retorna a
B *
, se ostd::any
objeto mantiver algo convertível emB *
, ou - Lança uma exceção, se não?
Parece que dynamic_cast
e std::any_cast
cada fornecer metade desta funcionalidade, mas eu não vejo nenhuma maneira de colocar os dois juntos.
Estou ciente de que posso fazer isso funcionar de várias maneiras que envolvam enumerar explicitamente todos os tipos conversíveis B *
, mas essa é a mãe de todas as violações DRY.
Exemplo de caso de uso:
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);
}
Não quero incluir um monte de código padrão listando todos os tipos de serra existentes, para que eu possa pegar uma serra - qualquer Saw
- para usar Factory1
.
std::any
isso e o que você está tentando resolver em geral? Isso soa como um problema muito estranho e provavelmente há uma melhor maneira de contornar issoB*
s nostd::any
objeto, e não em indicadores de classe derivados, isso resolve o problema com bastante facilidade.myTools
são ferramentas, por que não apenas ter umaTool
classe base e criarmyTools
umastd::vector<std::unique_ptr<Tool>>
?myTools
existe; por que você deseja colocar o que afirma ser objetos totalmente diferentes? iterar sobre eles para tentar se lembrar do que você colocou lá?Respostas:
Isso é inatingível. Só é possível remover um objeto
std::any
usando exatamente o tipo que foi colocado dentro. Portanto, você deve conhecer o tipo para obter algo com isso.Parece que
std::any
não se encaixa no seu caso de uso.fonte
Adicionar uma classe base "Tool" com um atributo enum ToolType pode ajudar. Em seguida, usando o ToolType, você pode decidir sobre o elenco.
fonte