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::anys 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;
}