I would like to use polymorphism to have a vector of std::function<void(Base&)>
that take in a base class as a parameter, and fill the vector with std::function
with a similar signature that instead take in a derived class as a parameter.
#include <functional>
#include <vector>
#include <stdio.h>
class Base
{
public:
virtual ~Base() = default;
};
class Derived : public Base
{
public:
Derived(int x, int y) : a(x), b(y) {}
int a, b;
};
void DerivedFunction(Derived& d)
{
printf("A: %d, B: %d\n", d.a, d.b);
}
using FunctionSignature = std::function<void(Base&)>; // Changing Base& to Derived& compiles fine.
static std::vector<FunctionSignature> myVector;
int main()
{
FunctionSignature fn = [](Derived& d){ printf("A: %d, B: %d\n", d.a, d.b); };
myVector.push_back(fn); // error
myVector.push_back(std::forward<FunctionSignature>(fn)); // error
myVector.push_back(std::bind(&DerivedFunction, std::placeholders::_1)); // error
return 0;
}
What would be the correct way to push_back DerivedFunction into the vector?
Godbolt link: https://godbolt.org/z/b6Taqoqs8
A Derived&
can be implicitly converted to a Base&
. Inheritance models a is-a relation: Every Derived
instance is-a Base
. This relation is not mutual. You cannot implicitly convert a Base&
to a Derived&
(not every Base
is-a Derived
).
You can use a dynamic_cast
. It will throw an exception when the dynamic type of the object is not Derived
:
template <typename F>
auto wrap(F f) {
return [f](Base& b) {
f(dynamic_cast<Derived&>(b));
};
}
int main() {
FunctionSignature fn = wrap([](Derived& d){ printf("A: %d, B: %d\n", d.a, d.b); });
}
You could catch the exception in the wrapper, or cast between pointers to get a nullptr
rather than an exception (for details see here).
As mentioned in a comment, the vector is a distraction. If the first line in main
is fixed you can use the same with the vector.