Playing around with Lambdas I found an interesting behaviour that I do not fully understand.
Supose I have a struct Overload
that derives from 2 template parameters, and has a using F1::operator();
clause.
Now if I derive from two functors I can only access the operator() of F1 (as I would expect)
If I derive from two Lambda Functions this is no longer true: I can access the operator() from F2 too.
#include <iostream> // I compiled with g++ (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) // // g++ -Wall -std=c++11 -g main.cc // g++ -Wall -std=c++11 -DFUNCTOR -g main.cc // // or clang clang version 3.3 (tags/RELEASE_33/rc2) // // clang++ -Wall -std=c++11 -g main.cc // clang++ -Wall -std=c++11 -DFUNCTOR -g main.cc // // on a Linux localhost.localdomain 3.9.6-200.fc18.i686 #1 SMP Thu Jun 13 // 19:29:40 UTC 2013 i686 i686 i386 GNU/Linux box struct Functor1 { void operator()() { std::cout << "Functor1::operator()()\n"; } }; struct Functor2 { void operator()(int) { std::cout << "Functor2::operator()(int)\n"; } }; template <typename F1, typename F2> struct Overload : public F1, public F2 { Overload() : F1() , F2() {} Overload(F1 x1, F2 x2) : F1(x1) , F2(x2) {} using F1::operator(); }; template <typename F1, typename F2> auto get(F1 x1, F2 x2) -> Overload<F1, F2> { return Overload<F1, F2>(x1, x2); } int main(int argc, char *argv[]) { auto f = get(Functor1(), Functor2()); f(); #ifdef FUNCTOR f(2); // this one doesn't work IMHO correctly #endif auto f1 = get( []() { std::cout << "lambda1::operator()()\n"; }, [](int) { std::cout << "lambda2::operator()(int)\n"; } ); f1(); f1(2); // this one works but I don't know why return 0; }
The standard states that:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non- union class type
So every Lambda's types should be unique.
I cannot explain why this is so: can anyone shed some light on this please?
Java supports lambda expressions but not the Closures. A lambda expression is an anonymous function and can be defined as a parameter. The Closures are like code fragments or code blocks that can be used without being a method or a class.
Lambda functions may be implemented as closures, but they are not closures themselves. This really depends on the context in which you use your application and the environment. When you are creating a lambda function that uses non-local variables, it must be implemented as a closure.
All lambdas are inline. Not all calls to them are necessarily inlined.
The Base class members and member functions are inherited to Object of the derived class. A base class is also called parent class or superclass. Derived Class: A class that is created from an existing class. The derived class inherits all members and member functions of a base class.
In addition to operator()
, a the class defined by a lambda can (under the right circumstances) provide a conversion to a pointer to function. The circumstance (or at least the primary one) is that the lambda can't capture anything.
If you add a capture:
auto f1 = get( []() { std::cout << "lambda1::operator()()\n"; }, [i](int) { std::cout << "lambda2::operator()(int)\n"; } ); f1(); f1(2);
...the conversion to pointer to function
is no longer provided, so trying to compile the code above gives the error you probably expected all along:
trash9.cpp: In function 'int main(int, char**)': trash9.cpp:49:9: error: no match for call to '(Overload<main(int, char**)::<lambda()>, main(int, char**)::<lambda(int)> >) (int)' trash9.cpp:14:8: note: candidate is: trash9.cpp:45:23: note: main(int, char**)::<lambda()> trash9.cpp:45:23: note: candidate expects 0 arguments, 1 provided
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With