C ++ lambda capture restrictions

Is it possible to limit the capture type of a lambda specified as a parameter?
For example, is it possible to take only lambdas that do not capture anything by reference?

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

MSalters notes that "non-capturing lambda can be converted to a function pointer." What does it mean? The lambda object will correspond to a pointer to the type of the function parameter.

It's hard to translate a lambda type to a function pointer. Here is my attempt to implement a compatible implementation. It hacked a bit.

 #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 must be resolved to a functor. You can do this by providing a specialization for ptmf_to_pf , which accepts a pointer to function types.

In addition, as the demo shows, it will not accept lambdas that capture anything by value, as well as by reference. In C ++, there is no way to make the restriction so specific.

+5
source

Perhaps you misunderstand the behavior of capturing lambda expressions: the closure object is exactly the same as the functor object, therefore

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

exactly matches

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

Once the snapping object is constructed, all capture and snapping is completed and locked forever in the object.

If we now transfer the object to another place, for example, call_me(f) , then the receiver function has nothing to do with the construction of the functor object or closure.

+5
source

Indirect hack: only non-invasive lambda can be converted to a pointer to a function. Of course, this also covers many types of F , which are not lambdas at all.

+3
source

Source: https://habr.com/ru/post/910506/


All Articles