捕獲發生在構建std::function
之前。
所以你捕捉std::function<void()> func
未初始化(甚至不是默認的構造!)副本。所有其本身捕獲的std::function
都是UB(在構建它之前複製一個變量!),並且調用它將甚至是「更多UB」(調用非構造的std::function
的副本!)。
的參考情況捕獲參考func
,它被初始化之前也被允許的,只要它是隻使用一次初始化。
缺點到參考情況是拉姆達僅保留的func
的範圍內有效。一旦func
超出範圍,它的副本也是無效的。根據我的經驗,這很糟糕。
要做到真正的「充滿力量」遞歸拉姆達,你需要像Y型組合子。
這裏是短一個C++ 14的y組合子:
template<class F>
auto y_combinate(F&& f) {
return [f = std::forward<F>(f)](auto&&...args) {
return f(f, decltype(args)(args)...);
};
}
傳遞給它的是期望到自身的引用作爲第一個參數的λ:
std::function<void()> func = y_combinate([](auto&& self) {
self(self);
}
);
和它的休息。
的y組合子的要求是因爲你沒有一個lambda體內訪問自己的this
。所以我們添加一個。
上述的y組合子是隻有90%的,因爲它不能處理R/L值和完全通過了功能對象的常量性。但它大部分時間都會用到。
這是一個稍微好一點的y combinate:
template<class F>
struct y_combinate_t {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return f(*this, std::forward<Args>(args)...);
}
};
template<class F>
y_combinate_t<std::decay_t<F>> y_combinate(F&& f) {
return {std::forward<F>(f)};
}
這使得使用好一點:
std::function<void()> func = y_combinate([](auto&& self) {
self();
}
);
調用時在現已通過了self
不必傳遞self
本身。
第二個片段複製一個尚未初始化的值,因此它尚未「活着」。 –
@Alex函數沒有被調用,所以它只應該創建lambda函數,然後退出。 –
@KerrekSB啊!因此,使用'&func'可以工作,因爲它只複製lambda函數的地址?直到現在我還不明白捕獲是否真的像函數參數。 –