Friday, 15 April 2011

c++ - lambdas and equality/inequality operator -



c++ - lambdas and equality/inequality operator -

i have question equality comparing of lambdas. i've tried read references i've found nil this.

[] (args ...args) -> returntype { ... };

for type of lambdas, not closures because have empty capture list, operators == , != works in same way static functions (well, seems, compiler generates them static functions well). closures effort compare in same way causes compilation error.

here simple programm example:

#include <typeinfo> #include <iostream> struct wrapperbase { virtual ~wrapperbase() = default; virtual bool operator==(wrapperbase& v) = 0; virtual bool operator!=(wrapperbase& v) = 0; }; template<typename _tp> struct wrapper : wrapperbase { wrapper(const _tp& v) : value(v) { } bool operator==(wrapperbase& v) override { seek { wrapper<_tp>& vv = dynamic_cast<wrapper<_tp>&>(v); homecoming value == vv.value; } catch(std::bad_cast& err) { } homecoming false; } bool operator!=(wrapperbase& v) override { seek { wrapper<_tp>& vv = dynamic_cast<wrapper<_tp>&>(v); homecoming value != vv.value; } catch(std::bad_cast& err) { } homecoming true; } // _tp value; }; template<typename _tp> wrapperbase* create_wrapper(const _tp& v) { homecoming new wrapper<_tp>(v); } struct base of operations { base(int a, int b) : wrapper(nullptr), a(a), b(b) { } virtual ~base() { delete wrapper; } virtual wrapperbase* create_wrapper() = 0; wrapperbase* wrapper; int a; int b; }; struct classa : base of operations { classa(int a, int b) : base(a, b) { wrapper = create_wrapper(); } wrapperbase* create_wrapper() override { auto lambda = [] (int v1, int v2) { homecoming v1 + v2; }; homecoming ::create_wrapper(lambda); } }; struct classb : base of operations { classb(int a, int b) : base(a, b) { wrapper = create_wrapper(); } wrapperbase* create_wrapper() override { auto lambda = [=] (int v1, int v2) { homecoming + b + v1 + v2; }; homecoming ::create_wrapper(lambda); } }; int main(int argc, char** argv) { std::cout << std::boolalpha; // works fine: classa a1(1, 2); classa a2(3, 4); std::cout << (*a1.wrapper == *a1.wrapper) << std::endl; // true std::cout << (*a2.wrapper == *a2.wrapper) << std::endl; // true std::cout << (*a1.wrapper == *a2.wrapper) << std::endl; // true // cause compilation error: classb b1(1, 2); classb b2(3, 4); std::cout << (*b1.wrapper == *b1.wrapper) << std::endl; std::cout << (*b2.wrapper == *b2.wrapper) << std::endl; std::cout << (*b1.wrapper == *b2.wrapper) << std::endl; homecoming 0; }

comparing lambdas created in instances of classa homecoming true if created in different context (just said). on other hand, classb not compile because operator == , != lambda not found.

it seems, programm not well-formed, , comparing of lambdas in way i've tried causes undefined behavior of programm. if it's undefined behavior, how can compared? (i guess, nohow)

for type of lambdas, not closures because have empty capture list, operators == , != works in same way static functions (well, seems, compiler generates them static functions well).

it works because closure type of lambda without captures provides conversion operator returns function pointer. comparable. [expr.prim.lambda]/6 (emphasis mine):

the closure type lambda-expression no lambda-capture has public non-virtual non-explicit const conversion function pointer function having same parameter , homecoming types closure type’s function phone call operator. value returned conversion function shall address of function that, when invoked, has same effect invoking closure type’s function phone call operator.

(if conversion operator explicit comparing not work) roughly, lambda of form [] {} translates to

struct closure_type { private: static void call() {} public: // closure_type() = delete; // commented sake of demo closure_type& operator=(closure_type const&) = delete; void operator()() const { /*return call();*/ } operator decltype(&call)() const { homecoming &call; } };

as may have noted, conversion operator returns same function pointer each time. though utterly surprising if happened, standard allow different function pointers returned phone call conversion operator same closure object; comparing of 2 closure objects has hence implementation-defined value. (it should, though, on implementations true 2 closure objects of same type.)

c++ c++11 lambda closures

No comments:

Post a Comment