是否可以約束作爲參數給定的lambda捕獲類型?
例如,是否可以只採取不通過引用捕獲任何東西的lambda表達式?C++ lambda捕獲約束條件
template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
:::
}
是否可以約束作爲參數給定的lambda捕獲類型?
例如,是否可以只採取不通過引用捕獲任何東西的lambda表達式?C++ lambda捕獲約束條件
template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
:::
}
MSalters注意到「非捕獲的lambda可以轉換爲函數指針。」這是什麼意思? lambda對象將匹配指向函數參數類型的指針。
將lambda類型轉換爲指向函數的指令是非常棘手的。這是我嘗試遵循一個合規的實現。這有點駭人聽聞。
#include <type_traits>
template< typename fn >
struct ptmf_to_pf;
template< typename r, typename c, typename ... a >
struct ptmf_to_pf< r (c::*) (a ...) const >
{ typedef r (* type)(a ...); };
// Use SFINAE to hide function if lambda is not convertible to function ptr.
// Only check that the conversion is legal, it never actually occurs.
template< typename lambda >
typename std::enable_if< std::is_constructible<
typename ptmf_to_pf< decltype(&lambda::operator()) >::type,
lambda >::value >::type
f(lambda arg) {
arg("hello ");
arg("world\n");
}
#include <iostream>
int main() {
int x = 3;
f([](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s; }); // OK
f([=](char const *s){ std::cout << s << x; }); // error
}
這不會接受函數指針作爲直接參數,因爲模板參數需要解析爲函子。您可以通過爲ptmf_to_pf
提供專門接受指向函數類型的指針來實現此目的。
另外,如演示所示,它不會接受通過值來捕獲任何內容的lambda表達式,也可以通過引用來接受它。 C++沒有辦法使限制如此具體。
爲什麼不把lambda作爲函數指針傳遞,然後沒有模板? – perreal 2012-03-15 01:37:08
@perreal:如果你知道所需的函數指針類型,那就這樣做。在一般情況下,這是不知道的。 – Potatoswatter 2012-03-15 02:20:19
也許你誤解lambda表達式的捕捉行爲:一個閉包對象就像是一個仿函數對象闡明,所以
struct Fun
{
Fun (int & a) : n(a) { }
int operator()(...) { ... }
private:
int & n;
};
int q;
Fun f(q);
f(...);
是完全一樣的
int q;
auto f = [&q](...) -> int { ... };
f(...);
構建閉包對象後,所有捕獲和綁定都會完成並永久鎖定到對象中。
如果您現在將對象傳遞到其他位置,如call_me(f)
,則收件人函數與函子或閉包對象的構造沒有關係。
這是真的,但lambda的編譯器生成類型包含捕獲發生的所有細節。人們可以很容易地想象一個元數據系統,它允許自省這種類型來查看是否有任何引用成員(或者構造函數是否有任何引用參數)。 – 2012-03-12 14:06:31
@BenVoigt是的,這可能是仿函數對象的特徵... – log0 2012-03-12 14:07:50
間接破解:只有非捕獲的lambda可以轉換爲指向函數的指針。當然,這也涵蓋了很多不屬於lambda的F
類型。
允許非lambda函數指針可能是無害的或有益的。+1 – Potatoswatter 2012-03-14 09:20:16
當閉包對象碰到你的函數時,它已經被構造了,你不知道它的內部是什麼,因爲它們是私有的。但是,如果你想知道,lambda當然不能捕獲任何*事後*,尤其是* *你的*函數'f'中沒有任何東西。 – 2012-03-12 13:55:32
這樣做毫無意義,因爲按值捕獲指針與捕獲參考一樣危險。 – 2012-03-12 14:01:34
@BenVoigt沒錯。 – log0 2012-03-12 14:02:40