In C++ you can pass instances of Derived
to functions accepting Base
, if Base
is a base class of Derived
. This is very useful for satisfying APIs and a very common design pattern for APIs.
Currently I am faced with a situation, where I want to upcast through an std::any
. That is I have an std::any
that stores an instance of Derived
and I would like to cast its address to a pointer to Base
in an API function, that should not know of the existence of Derived
. My use case is a runtime reflection library that passes around std::any
s storing instances of the reflected types.
I understand that upcasting through std::any
is not possible, because std::any_cast
checks the typeid
before casting and returns a nullptr
if the types don't match, see cppreference.
But maybe there is a workaround or some clever trick that I could use? It feels like it must be possible somehow, as upcasting is such a common thing in C++ and the std::any
has the address and type I need.
Here is a code example. The following code segfaults as expected because the std::any_cast
returns a nullptr
in any_function
which is dereferenced in the following line. Compiler explorer: https://godbolt.org/z/E9sG9G3ff
#include <any>
#include <iostream>
class Base
{
public:
double get_val() const {
return val;
}
private:
double val {1.23};
};
void normal_function(Base const& b){
std::cout << b.get_val() << std::endl;
};
void any_function(std::any const& b){
auto* ptr = std::any_cast<Base>(&b);
std::cout << ptr->get_val() << std::endl;
}
class Derived : public Base {};
int main()
{
Derived d;
// normal upcasting
normal_function(d);
// upcasting thru std::any
std::any ad = d;
any_function(ad);
return 0;
}