考虑以下返回lambda函数的函数:
std::function<int()> make_counter()
{
int i = 0;
return [=]() mutable { return i++; };
}
是否可能返回实际的lambda类型,而无需将其封装到std::function
中?
考虑以下返回lambda函数的函数:
std::function<int()> make_counter()
{
int i = 0;
return [=]() mutable { return i++; };
}
是否可能返回实际的lambda类型,而无需将其封装到std::function
中?
auto const make_counter = [](int i = 0) {
return [i]() mutable { return i++; };
};
C++1y:是的,通过普通函数的返回类型推断(N3582)实现。
如果你作弊并使用返回类型推导,是的,你可以(Link)。
请注意,这只在C++11之后才可能实现,但可以通过lambda表达式在常规的、不会产生警告的C++11中实现(即,在返回该lambda的lambda内部使用lambda表达式)。
是的,你可以通过一些受这篇博客文章启发的lambda技巧来实现这个。
第一步是提供一个帮助器,使lambda成为字面类型:
template<class F>
struct literal_lambda_t {
static_assert(std::is_empty<F>(), "Lambdas must be empty (have no captures)");
template<typename... Args>
auto operator()(Args&&... args) const -> decltype(
std::declval<F const&>()(std::forward<Args>(args)...)
) {
// since the object is empty, reinterpreting it should be safe
return reinterpret_cast<const F&>(*this)(std::forward<Args>(args)...);
}
};
template<class F>
constexpr literal_lambda_t<typename std::remove_reference<F>::type> literal_lambda(F &&f) {
return {};
}
namespace detail {
static constexpr auto make_counter = literal_lambda([](){
int i = 0;
return [=]() mutable { return i++; };
});
}
最后,您可以使用这个私有 lambda 来声明您的真实函数:
auto make_counter() -> decltype(detail::make_counter()) {
return detail::make_counter();
}
namespace detail {
template<typename T>
struct typed_counter_helper {
// can't template this, so have to template an enclosing struct
static constexpr auto f = literal_lambda([](){
T i = 0;
return [=]() mutable { return i++; };
});
};
}
template<typename T>
auto make_typed_counter() -> decltype(typed_counter_helper<T>::f()) {
return typed_counter_helper<T>::f::make_counter();
}
return expression;
之外的内容,返回类型推断将无法工作(§5.1.2,4)。 - Arne Mertz