Нет лямбда std::function
. std::function
- это стиратель типа - он требует чего-то уничтожаемого, с возможностью копирования и invokable с подписью и стирает остальную часть типа.
Поскольку ваша лямбда не может быть скопирована, ее нельзя хранить в std::function
.
Вы можете сделать это с возможностью копирования (например, сохраняя свое состояние в std::shared_ptr
) или написать только для перемещения std::function
.
#include <utility>
#include <memory>
template<class Sig>class func;
namespace details{
template<class Sig>struct inner;
template<class R,class...Args>
struct inner<R(Args...)>{
virtual ~inner() {};
virtual R invoke(Args&&...args) =0;
};
template<class F,class Sig>struct impl;
template<class F,class R,class...Args>
struct impl<F,R(Args...)>:inner<R(Args...)>{
F f;
template<class... Ts>
impl(Ts&&...ts):f(std::forward<Ts>(ts)...){}
R invoke(Args&&...args)override{
return f(std::forward<Args>(args)...);
}
};
}
template<class T>struct emplace_as{};
template<class R,class...Args>
class func<R(Args...)>{
std::unique_ptr<details::inner<R(Args...)>> pImpl;
public:
R operator()(Args...args){
return pImpl->invoke(std::forward<Args>(args)...);
}
explicit operator bool()const{return pImpl;}
func(func&&)=default;
template<class F,class...Ts,class=typename std::enable_if<
std::is_convertible<decltype(std::declval<F>()(std::declval<Args>()...)),R>::value
>::type>
func(emplace_as<F>,Ts&&...ts):
pImpl(new details::impl<F, R(Args...)>{std::forward<Ts>(ts)...})
{}
template<class F,class=typename std::enable_if<
std::is_convertible<decltype(std::declval<F>()(std::declval<Args>()...)),R>::value
>::type>
func(F&&f):
func(
emplace_as<typename std::decay<F>::type>(),
std::forward<F>(f)
)
{}
};
или something like that.
(Характеристики, необходимые для быть добавлено: Rvalue ссылки на эти перегрузки на ()
, может быть swap
, может быть assign
и emplace
, возможно, определением типов для result_type
и т.д.), может быть target
и target_type
)
Лямбда имеет «нецензурный» уникальную тип, сгенерированный компилятором. Ваша проблема заключается в том, что 'std :: function' требует, чтобы объект функции был' CopyConstructible', а 'unique_ptr' не может быть скопирован. –
Но в примере 'lambda' является ссылкой rvalue, он вызывает конструктор перемещения. Не так ли? – herolover
Это не имеет значения. 'std :: function' имеет жесткое требование, что объект функции, используемый' CopyConstructible', и ваш лямбда не потому, что он захватил 'unique_ptr'. Конец истории. –