c++ - Defining operators using lambda functions -


consider example:

struct {     int val;     a(int val) : val(val){};      operator+(const a& a1) {         return (+[](const a& a1, const a& a2) -> {             return a(a1.val + a2.val);         })(*this, a1);     }; };  int main(int argc, char* argv[]) {     a(14);     b(12);     auto c = + b;      return 0; } 

i have 2 questions:

  1. will compiler optimize-out use of lambda in case (which wrapper operator+ or there overhead?
  2. is there simpler syntax writing operators using lambda functions?

some parts of code seem pointless. go through them , strip them out one-by-one.

a operator+(const a& a1) {     return (+[](const a& a1, const a& a2) -> {         return a(a1.val + a2.val);     })(*this, a1); }; 

first, +[] decays needlessly function pointer. can nothing useful here, except possibly confuse optimizer. can rid of ()s:

a operator+(const a& a1) {     return [](const a& a1, const a& a2) -> {         return a(a1.val + a2.val);     }(*this, a1); }; 

now, ->a part noise, can deduce return type:

a operator+(const a& a1) {     return [](const a& a1, const a& a2) {         return a(a1.val + a2.val);     }(*this, a1); }; 

next, why use member operator+? + symmetric, , using koenig-style operator becomes more obvious:

friend operator+(const a& a1, const a& a2) {     return [](const a& a1, const a& a2) {         return a(a1.val + a2.val);     }(a1, a2); }; 

which gets rid of numbering confusion introduced (where a1 in 1 scope a2 in another, , new variable called a1 introduced refers *this).

finally, lambda nothing @ point:

friend operator+(const a& a1, const a& a2) {   return a(a1.val + a2.val); }; 

and deleting results in clearer code.


now question.

a compiler more optimize out lambda go through these simplification steps. suspect worst thing did unary +, converted lambda function pointer: know gcc @ inlining function pointers, , last checked msvc bad @ it. every compiler @ inlining call stateless lambda, however.

at point of call, method being invoked known compiler type system, no analysis of providence of function pointer has done. data copied arguments used, in small function. easy inline.

even if have modest capture requirements, long don't type erase or copy lambda around, have bunch of local references or copies of local variables used in body of lambda. easy inline.

now, each simplifying step in first part of answer makes code simpler, until end, when lambda gone , thing "optimize" simple rvo (which have suppress compiler flags prevent happening), aka eliding temporary a in return statement.

if a has implicit constructor result of .val+.val, don't need a in return statement.


there isn't simple way write operators in terms of lambdas. you'll need store said lambda somewhere, glue operator+ (or whatever) it, 2 steps going require more code injecting body directly operator+.

i fancy decltype , macro nonsense let bind global lambda being body of given operator+ class (using crtp , traits class), calling "simpler" more bit of stretch.

it let like:

const auto print_via_to_string = [](std::ostream& os, auto&& val){   using std::to_string;   os << to_string(decltype(val)(val)); };  struct foo { /* ... */ };  bind_operator( <<, std::ostream&, foo const&, print_via_to_string ); 

or somesuch, , expect << inlined.

again, considering "simpler" stretch.


Comments

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -