简体   繁体   English

C ++ lambda捕获约束

[英]C++ lambda capture constraints

Is it possible to constrain the type of capture of a lambda given as parameter ? 是否可以约束作为参数给出的lambda的捕获类型?
For example, Is it possible to take only lambdas that don't capture anything by reference ? 例如,是否可以仅采用不通过引用捕获任何内容的lambda?

template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
  :::
}

Maybe you're misunderstanding the capturing behaviour of lambda expressions: A closure object is just like a functor object spelt out, so 也许你误解了lambda表达式的捕获行为:一个闭包对象就像一个拼写出来的仿函数对象,所以

struct Fun
{
    Fun (int & a) : n(a) { }
    int operator()(...) { ... }
private:
    int & n;
};

int q;
Fun f(q);
f(...);

is exactly the same as 与...完全相同

int q;
auto f = [&q](...) -> int { ... };
f(...);

Once the closure object is constructed, all the capturing and binding is finished and forever locked into the object. 构造闭包对象后,所有捕获和绑定都将完成并永远锁定到对象中。

If you now pass the object on to some other place, like call_me(f) , then the recipient function has no connection with the construction of the functor or closure object. 如果现在将对象传递到某个其他位置,例如call_me(f) ,则接收方函数与call_me(f)函数或闭包对象的构造无关。

MSalters notes that "non-capturing lambda's can be converted to a pointer-to-function." MSalters指出“非捕获lambda可以转换为指向函数的指针”。 What does this mean? 这是什么意思? The lambda object will match a pointer to function parameter type. lambda对象将匹配指向函数参数类型的指针。

It's tricky to translate the lambda type to a pointer-to-function. 将lambda类型转换为指向函数的指针是很棘手的。 Here is my attempt at a compliant implementation. 以下是我对合规实施的尝试。 It's slightly hackish. 这有点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
}

This will not accept function pointers as direct arguments, since the template parameter needs to resolve to a functor. 这不会接受函数指针作为直接参数,因为模板参数需要解析为仿函数。 You could make it do so by providing a specialization for ptmf_to_pf that accepts pointer to function types. 您可以通过为ptmf_to_pf提供接受指向函数类型的指针的专门化来ptmf_to_pf

Also, as the demo shows, it won't accept lambdas that capture anything by value, as well as by reference. 此外,正如演示所示,它不会接受通过值以及引用捕获任何内容的lambda。 There is no way in C++ to make the restriction so specific. 在C ++中没有办法使限制如此具体。

Indirect hack: Only non-capturing lambda's can be converted to a pointer-to-function. 间接黑客:只有非捕获的lambda才能转换为指向函数的指针。 Of course, that also covers a lot of F types that aren't lambda's at all. 当然,这也涵盖了许多根本不是lambda的F类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM