std::function
can wrap lambdas with capture list but how std::function
implemented? We don't know what is the type of it, it can be assigned to void*
but then it is not possible to call lambda

- 509
- 2
- 12
-
2Have you looked at implementations in libstdc++ and libc++? – Stephen Newell Jan 07 '21 at 06:45
-
1@StephenNewell that libraries are just a big mess – Kanony Jan 07 '21 at 06:54
1 Answers
Disclaimer: this is incomplete, possibly incorrect and doesn't follow std::function
api and conventions (e.g. it is not copyable). This is just an example to show one way of how the type erasure of a std::function
like type can be implemented, striped down to the bare minimum to understand the type erasure technique.
In order to store any type and be able to call it according to a function signature we use polymorphism.
This is the base abstract class for a Signature
that defines the calling API. Signature
must be a function type:
template <class Signature> struct CallableBase;
template <class R, class... Args>
struct CallableBase<R(Args...)>
{
virtual R call(Args... args) = 0;
};
Next we need a derived class that holds the actual callable object F
and can call it:
template <class F, class Signature> struct Callable;
template <class F, class R, class... Args>
struct Callable<F, R(Args...)> : CallableBase<R(Args...)>
{
F f;
Callable(F f) : f{f} {}
R call(Args... args) override
{
return f(args...);
}
};
In our Function
class we hold a pointer of type CallableBase
to an object of type Callable<F>
to enable polymorphism and get the desired behavior:
template <class Signature> struct Func;
template <class R, class... Args>
struct Func<R(Args...)>
{
using Signature = R(Args...);
std::unique_ptr<CallableBase<Signature>> callable_;
template <class F>
Func(F f) : callable_{std::make_unique<Callable<F, Signature>>(f)} {}
R operator()(Args... args)
{
return callable_->call(args...);
}
};
And this gets us a basic type erased Function
:
auto test()
{
int x = 10;
Func<int(int, int)> f = [=] (int a, int b) { return a * x + b; };
return f(2, 5); // 25
}

- 72,283
- 15
- 145
- 224