why do lambda functions in c++11 not have function<> types?

Viewed 5203

I am playing around with the c++11 functional features. One thing I find odd is that the type of a lambda function is actually NOT a function<> type. What's more, lambda's do not seem to play really well with the type-inferencing mechanism.

Attached is a small example in which I tested flipping the two arguments of a function for adding two integers. (The compiler I used was gcc 4.6.2 under MinGW.) In the example, the type for addInt_f has been explicitly defined using function<> while addInt_l is a lambda whose type is type-inferenced with auto.

When I compiled the code, the flip function can accept the explicitly type-defined version of addInt but not the lambda version, giving an error saying that, testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'

The next few lines show that the lambda version (as well as a 'raw' version) can be accepted if it's explicitly cast to the appropriate function<> type.

So my questions are:

  1. Why is it that a lambda function does not have a function<> type in the first place? In the small example, why does not addInt_l have function<int (int,int)> as the type instead of having a different, lambda type? From the perspective of functional programming, what's the difference between a function/functional object and a lambda?

  2. If there is a fundamental reason that these two have to be different. I heard that lambda's can be converted to function<> but they are different. Is this a design issue/defect of C++11, an implementation issue or is there a benefit in distinguishing the two as the way it is? It seems that the type-signature of addInt_l alone has provided enough information about the parameter and return types of the function.

  3. Is there a way to write the lambda so that the above mentioned explicit type-casting can be avoided?

Thanks in advance.

    //-- testCppBind.cpp --
    #include <functional>
    using namespace std;
    using namespace std::placeholders;

    template <typename T1,typename T2, typename T3>
    function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}

    function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
    auto addInt_l = [](int a,int b) -> int { return a + b;};

    int addInt0(int a, int b) { return a+b;}

    int main() {
      auto ff = flip(addInt_f);   //ok
      auto ff1 = flip(addInt_l);  //not ok
      auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
      auto ff3 = flip((function<int (int,int)>)addInt0);  //ok

      return 0;
    }

2 Answers
Related