Лямбда - это уникальный анонимный тип.Единственный способ назвать тип лямбда-экземпляра - это сохранить его в переменной, а затем сделать decltype
для этого типа переменной.
Существует несколько способов поймать брошенную лямбду.
try {
throw []{};
} catch(...) {
}
в этом случае вы не можете использовать его, кроме как бросить его снова.
try {
throw +[]{};
} catch(void(*f)()) {
}
лямбда без сохранения состояния может быть преобразована в указатель функции.
try {
throw std::function<void()>([]{});
} catch(std::function<void()> f) {
}
вы можетепреобразовать его в std::function
.Недостатком std::function
является то, что он выделяет кучу для больших лямбд, что теоретически может вызвать его выброс.
Мы можем устранить это выделение кучи:
template<class Sig>
struct callable;
template<class R, class...Args>
struct callable<R(Args...)> {
void* state = nullptr;
R(*action)(void*, Args&&...) = nullptr;
R operator()(Args...args) const {
return action( state, std::forward<Args>(args)... );
}
};
template<class Sig, class F>
struct lambda_wrapper;
template<class R, class...Args, class F>
struct lambda_wrapper<R(Args...), F>
:
F,
callable<R(Args...)>
{
lambda_wrapper( F fin ):
F(std::move(fin)),
callable<R(Args...)>{
static_cast<F*>(this),
[](void* self, Args&&...args)->R {
return static_cast<R>( (*static_cast<F*>(self))( std::forward<Args>(args)... ) );
}
}
{}
lambda_wrapper(lambda_wrapper && o):
F(static_cast<F&&>(o)),
callable<R(Args...)>( o )
{
this->state = static_cast<F*>(this);
}
lambda_wrapper& operator=(lambda_wrapper && o)
{
static_cast<F&>(*this) = (static_cast<F&&>(o));
static_cast<callable<R(Args...)>&>(*this) = static_cast<callable<R(Args...)>&>( o );
this->state = static_cast<F*>(this);
}
};
template<class Sig, class F>
lambda_wrapper<Sig, F> wrap_lambda( F fin ) {
return std::move(fin);
}
теперь вы можете сделать:
try {
throw wrap_lambda<void()>([]{});
} catch( callable<void()> const& f ) {
}
callable
- это стирание типа «меньшего веса», чем std::function
, поскольку оно не может быть причиной выделения новой памяти кучи.
Пример в реальном времени .