f



Lamda as Operator Overload

{ edited by mod to shorten lines to ~70 characters. -mod }

Hi,

  Is it possible to create a lambda that behaves like an operator
overload? 
That is, instead of calling it with the operator() syntax, it will be
called by some other, e.g. binary, infix operator.

Is it possible to generically simulate this somehow just like lambdas
can as structs overloading the () operator. The problem is just how to
get the compiler/ADL to call the correct function based on the operator.

Thanks!
Adi


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Adi
4/27/2016 6:46:47 AM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8509) is leader. Post Follow

6 Replies
458 Views

Similar Articles

[PageSpeed] 21

On Wednesday, 27 April 2016 14:50:10 UTC+3, Adi Shavit  wrote:
>   Is it possible to create a lambda that behaves like an operator
> overload? 

No, not even as 'operator()' overload for something else since those
are totally different things. Lambda is an object of anonymous class
that has its own 'operator()' overload. That is it.

> That is, instead of calling it with the operator() syntax, it will be
> called by some other, e.g. binary, infix operator.

It is indeed possible to make an operator overload that calls whatever
callable object (including lambda) stored in variable somewhere for
actually doing its work.

> 
> Is it possible to generically simulate this somehow just like lambdas
> can as structs overloading the () operator. The problem is just how to
> get the compiler/ADL to call the correct function based on the operator.

I am sort of unsure what you want to accomplish. Perhaps you need
to start with motivating example problem. Do you want generic
lambdas of C++14? Those are simple. It is like that:

    auto glambda = [] (auto a) { return a; };

We made a 'glambda' variable that contains an object of this type:

    class /* unnamed */
    {
    public:
        template<typename T>
        T operator () (T a) const { return a; }
    };

Now if you want you can call that 'glambda' from some template operator.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
ISO
4/27/2016 8:44:07 AM
On Wednesday, 27 April 2016 13:50:10 UTC+2, Adi Shavit  wrote:
> Is it possible to create a lambda that behaves like an operator
> overload? 
> That is, instead of calling it with the operator() syntax, it will be
> called by some other, e.g. binary, infix operator.
> 
> Is it possible to generically simulate this somehow just like lambdas
> can as structs overloading the () operator. The problem is just how to
> get the compiler/ADL to call the correct function based on the operator.

I don't see how.  The point about a lambda is that it creates a thing
without a name (that you can then store in a named variable, but the thing
itself is nameless), whereas operator overloading works precisely on the
basis of the name of the (member)function.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Martin
4/27/2016 8:44:23 AM

> I don't see how.  The point about a lambda is that it creates a thing
> without a name (that you can then store in a named variable, but the thing
> itself is nameless), whereas operator overloading works precisely on the
> basis of the name of the (member)function.
> 

Well, most lambdas are eventually stored in a named variable so that they
can be called at a later time. When called they are evoked like functions
via the function call operator.
My question was whether it is possible to create a lambda-like object that
can be evoked using an operator that is not the function call operator, or,
e.g. with an infix operator.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Adi
4/27/2016 3:14:55 PM
�� Tiib <ootiib@hot.ee> writes:

> It is indeed possible to make an operator overload that calls
> whatever callable object (including lambda) stored in variable
> somewhere for actually doing its work.

I don't know why one would want this kind of thing but

#include <iostream>

template<typename Callable>
struct bracketized: private Callable
{
  bracketized(const Callable &c): Callable(c) {}

  template<typename Param>
  auto operator[](Param&& p)
    -> decltype((*this)(std::forward<Param>(p)))
  {
    return (*this)(std::forward<Param>(p));
  }
};

template<typename Callable>
bracketized<Callable> bracketize(const Callable &c)
{
  return c;
}

int main()
{
  int i = 1;
  auto lambda = [&](int j) { i += j; };
  auto b = bracketize(lambda);

  b[42];
  std::cout << i;
}

builds and runs OK with g++-4.7 -std=c++11.
With -O it even computes 43 at compile time.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Kalle
4/27/2016 3:21:08 PM
> > It is indeed possible to make an operator overload that calls
> > whatever callable object (including lambda) stored in variable
> > somewhere for actually doing its work.
> 
> I don't know why one would want this kind of thing but
> 
> #include <iostream>
> 
> template<typename Callable>
> struct bracketized: private Callable
> {
>   bracketized(const Callable &c): Callable(c) {}
> 
>   template<typename Param>
>   auto operator[](Param&& p)
>     -> decltype((*this)(std::forward<Param>(p)))
>   {
>     return (*this)(std::forward<Param>(p));
>   }
> };
> 
> template<typename Callable>
> bracketized<Callable> bracketize(const Callable &c)
> {
>   return c;
> }
> 
> int main()
> {
>   int i = 1;
>   auto lambda = [&](int j) { i += j; };
>   auto b = bracketize(lambda);
> 
>   b[42];
>   std::cout << i;
> }
> 
> builds and runs OK with g++-4.7 -std=c++11.
> With -O it even computes 43 at compile time.

That's quite clever, though I am not sure this gives me
what I meant. In this case the bracket operator is essentially like the
function 
call operator.

I am more interested in overloading the arithmetic and logic 
infix operators (+,+=, &, &=, etc) where one does not invoke the function
explicitly.

Do you think this approach will work for that type of operator?
Could you "plusize" an add() lambda?
 


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Adi
4/27/2016 5:13:10 PM
On Thursday, 28 April 2016 01:20:08 UTC+3, Adi Shavit  wrote:
> > > It is indeed possible to make an operator overload that calls
> > > whatever callable object (including lambda) stored in variable
> > > somewhere for actually doing its work.
> > 
> > I don't know why one would want this kind of thing but
> > 
> > #include <iostream>
> > 
> > template<typename Callable>
> > struct bracketized: private Callable
> > {
> >   bracketized(const Callable &c): Callable(c) {}
> > 
> >   template<typename Param>
> >   auto operator[](Param&& p)
> >     -> decltype((*this)(std::forward<Param>(p)))
> >   {
> >     return (*this)(std::forward<Param>(p));
> >   }
> > };
> > 
> > template<typename Callable>
> > bracketized<Callable> bracketize(const Callable &c)
> > {
> >   return c;
> > }
> > 
> > int main()
> > {
> >   int i = 1;
> >   auto lambda = [&](int j) { i += j; };
> >   auto b = bracketize(lambda);
> > 
> >   b[42];
> >   std::cout << i;
> > }
> > 
> > builds and runs OK with g++-4.7 -std=c++11.
> > With -O it even computes 43 at compile time.
> 
> That's quite clever, though I am not sure this gives me
> what I meant. In this case the bracket operator is essentially like the
> function 
> call operator.

You perhaps need to type it here explicitly what code you have and what
you want it to look like.

> 
> I am more interested in overloading the arithmetic and logic 
> infix operators (+,+=, &, &=, etc) where one does not invoke the function
> explicitly.
> 
> Do you think this approach will work for that type of operator?
> Could you "plusize" an add() lambda?

C++ syntax can be altered rather heavily with macros and templates
and operator overloading. However beware. Making different language
using C++ is generally bad idea. Tiny typo in usage will typically
cause hard to understand diagnostics about such bastardization code
and all the immersion is gone.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
ISO
4/28/2016 6:30:29 AM
Reply: