6
votes

I've been reading a bit about lambda expressions on the internet recently and it seems to me that C++0x's lambda expressions will not have a single type (or types) that will bind exclusively to lambda expressions -- in other words, lambda expressions will only match template arguments or auto arguments/variables. What happens, as described here, is that

Compilers that support lambdas will create a unique anonymous functor type for each lambda expression

My question is, is that a bad thing? Wouldn't it make sense to have some keyword that matches only to lambda expressions, e.g. lambda, which would work as follows

void f(std::function<int(int)> func)
{
     func(2);
}

template<typename T>
void g(T func)
{
     func(2);
}

void h(lambda func)
{
     func(2);
}

int main()
{
    int fpointer(int);
    struct { int operator()(int var) { return var; } } functor;

    f(fpointer); //ok (actually a linker error, but for the sake of example)
    f(functor); //ok
    f([](int var) { return var; }); //ok

    g(fpointer); //ok
    g(functor); //ok
    g([](int var) { return var; }); //ok

    h(fpointer); //error -- function pointer isn't a lambda expr
    h(functor); //error -- functor isn't a lambda expr
    h([](int var) { return var; }); //ok

    return 0;
}

To be honest, I actually can't see the usefulness of this (especially given that auto accepts lambda expressions, so one could then assign a lambda to a variable), but it still doesn't sit right with me that lambda expressions are anonymous types and cannot be bound specifically to just one particular type (to the exclusion of all others).

In essence, my question is, is it fine that lambda expressions are anonymous (both in terms of utility -- does the lack of a lambda type devoid us of some functionality -- and philosophically -- does it really make sense that lambda expressions always have the 'type' auto)?

2
It slightly sounds like you are not aware that you can accept lambda expressions using std::function<int(int)> too.Johannes Schaub - litb
I was, however since the general functionality matches how auto works (afaik), I thought it unnecessary to add another set of example functions/function calls (but it's still good to mention, so thanks litb)GRB
I think there's a misunderstanding about auto. auto can't be used as a parameter type in a function. It's not a type. auto just says "deduce the type from the initializer because I'm too lazy or just unable to name the type".sellibitze
I've changed the auto parameter in that case. I am still confident that you can do auto = [](int a) { ... }; however (...right? ;) )GRB
the whole purpose of op() was that you don't have to worry about the functor type. now if you restrict something to only lambdas (surely i think implementations will provide some __is_lambda metafunction or something you could use with enable_if), what sense would it make to get rid of the ability to acccept function pointers etc. I don't see any and i believe there is no sense in it.Johannes Schaub - litb

2 Answers

11
votes

Lambdas are independent types. The code

void h(lambda func)
{
     func(2);
}

doesn't make any sense because lambdas don't have runtime polymorphism. Recall that a lambda is the equivalent of

struct unique_name
{
    return_type operator()(Arg1 a1, Arg2 a2, ... , Argn an)
    {
        code_inside_lambda;
    }
}

Which is itself a unique type. The code above would be the same as saying

void h(class C)
{
     C(2);
}

Which also makes no sense even if we assure that C has operator(). You need a template:

template<typename T>
void g(T func)
{
     func(2);
}

int main()
{
    g([](int x){return x + 2;});
}
3
votes

I see no reason to differentiate function types based on whether the function has a name or not. Lambda functions are just a shorthand, allowing you to define a convenience function easily. Name or no name, the behaviour of the function when called is the same.

Think of it this way. An early version of your software has a predicate defined as an anonymous function. Over time, requirements get more complex, and your predicate gets more complex too - and maybe you need to call it from more than one place. The sensible thing to do is to refactor so that you have a named function.

There's no reason why the called function (the one that calls the predicate) should care about that. Simple or complex, named or anonymous - it's still just a predicate function.

One minor issue is that of closures - I haven't checked, but with a bit of luck, C++ will get nested named functions with closures as well as lambdas.