Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ lambda capture constraints

Tags:

c++

c++11

lambda

Is it possible to constrain the type of capture of a lambda given as parameter ?
For example, Is it possible to take only lambdas that don't capture anything by reference ?

template <typename F>
void f(const F& lambda) // F must be a lambda that do not capture by ref
{
  :::
}
like image 823
log0 Avatar asked Mar 12 '12 13:03

log0


People also ask

What does it mean to lambda capture this?

A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.

Does C support lambda function?

Significance of Lambda Function in C/C++Lambda Functions can also be used as a value by the variable to store. Lambda can be referred to as an object that can be called by the function (called functors).

Can a lambda capture itself?

But a lambda cannot be recursive, it has no way to invoke itself. A lambda has no name and using this within the body of a lambda refers to a captured this (assuming the lambda is created in the body of a member function, otherwise it is an error).

Can a lambda closure be used to create a C++11 thread?

Can you create a C++11 thread with a lambda closure that takes a bunch of arguments? Yes – just like the previous case, you can pass the arguments needed by the lambda closure to the thread constructor.


1 Answers

MSalters notes that "non-capturing lambda's can be converted to a pointer-to-function." What does this mean? The lambda object will match a pointer to function parameter type.

It's tricky to translate the lambda type to a pointer-to-function. Here is my attempt at a compliant implementation. It's slightly 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.

Also, as the demo shows, it won't accept lambdas that capture anything by value, as well as by reference. There is no way in C++ to make the restriction so specific.

like image 128
Potatoswatter Avatar answered Oct 08 '22 04:10

Potatoswatter