[英]C++ lambda capture constraints
是否可以约束作为参数给出的lambda的捕获类型?
例如,是否可以仅采用不通过引用捕获任何内容的lambda?
template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
:::
}
也许你误解了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)
,则接收方函数与call_me(f)
函数或闭包对象的构造无关。
MSalters指出“非捕获lambda可以转换为指向函数的指针”。 这是什么意思? lambda对象将匹配指向函数参数类型的指针。
将lambda类型转换为指向函数的指针是很棘手的。 以下是我对合规实施的尝试。 这有点hackish。
#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
提供接受指向函数类型的指针的专门化来ptmf_to_pf
。
此外,正如演示所示,它不会接受通过值以及引用捕获任何内容的lambda。 在C ++中没有办法使限制如此具体。
间接黑客:只有非捕获的lambda才能转换为指向函数的指针。 当然,这也涵盖了许多根本不是lambda的F
类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.