Topic: Small improvements: Implicitely bindable func


Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Sun, 2 Nov 2014 20:53:19 -0800 (PST)
Raw View
------=_Part_3_1974761981.1414990399546
Content-Type: text/plain; charset=UTF-8

Hello everyone,

I would like to know if there would be interest for the following proposal:

Sometimes we write lambdas or bind expressions for algorithms in the
standard library.
I feel that this could be made shorter in many common cases, since in this
kind of code the lambda introducer
+ a return statement + opening and closing braces can make typing
considerably larger for short uses, which
abound in the standard library algorithms. I also find function objects for
standard math functions missing.
When I want to pass a standard math function, I have to wrap it in a
lambda, so that it is not deduced as a
function pointer, which causes indirection. It does not place well with
overloading either, I have to do:

myalgo(...., sqrt<int>); // This will cause function pointer deduction,
which is bad for inlining + I must say <int> explicitely to resolve
overloading.


My proposal has 3 parts: 1. and 3. target making code shorter. 2. targets
making the code shorter + at the same time
making optimizer opportunities for inlining better.

I would like to know if there would be interest for a proposal like the
following:

1. Make all function object (less etc.) implicitely bindable through an
external function that returns the result of calling bind.
The is_class assert in this implementation is to avoid binding function
pointers, for performance reasons. The function looks like this:


template <class FuncObject, class... Args>
constexpr auto implicitely_bindable(FuncObject && f, Args &&... args)
noexcept {
    static_assert(std::is_class<FuncObject>::value, "");
    return std::bind(std::forward<FuncObject>(f),
std::forward<Args>(args)...);
}

For each function object in the std library, there would be something
similar to this (ib stands for implicitely bindable):

template <class T1, class T2 = T1>
constexpr auto less_ib(T1 const & t1, T2 const & t2) noexcept {
    return implicitely_bindable(less<>(), t1, t2);
}


2. Math functions from <cmath> header should have a function object
version, since a function pointer is not reified and can prevent inlining,
though my tests in gcc showed that the compiler could optimize it in the
benchmark I did. But I guess it could be otherwise depending
on the compiler optimizer, so I don't think we should rely on smart
optimizers.
I would propose to have function objects for standard math functions like
the following:

struct sqrt_func {
    template <class T>
    auto operator()(T && arg) const { return
std::sqrt(std::forward<Arg>(arg)); }
};

template <class T>
constexpr auto sqrt_ib(T && arg) noexcept { return
implicitely_bindable(sqrt_func(), std::forward<Arg>(arg)); }



3. Overload placeholders with all operators.

This would enable to write code like this (ib stands for
implicitely_bindable, ignore the naming, it is just a detail):

   //With lambda
   partition(begin(vec), end(vec), [](int v) { return v < 5; });
   //With this proposal
   partition(begin(vec), end(vec), less_ib(_1, 5));

    //With lambda
    transform(begin(vec), end(vec), begin(out), [](double v) { return
sqrt(v) + pow(v, 5); });
    //With this proposal (overloaded placeholders + implicitely bindable
    transform((begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow(_1, 5));


I already wrote some code but it is not finished.

Regards


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_3_1974761981.1414990399546
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hello everyone,<div><br></div><div>I would like to know if=
 there would be interest for the following proposal:</div><div><br></div><d=
iv>Sometimes we write lambdas or bind expressions for algorithms in the sta=
ndard library.</div><div>I feel that this could be made shorter in many com=
mon cases, since in this kind of code the lambda introducer</div><div>+ a r=
eturn statement + opening and closing braces can make typing considerably l=
arger for short uses, which</div><div>abound in the standard library algori=
thms. I also find function objects for standard math functions missing.</di=
v><div>When I want to pass a standard math function, I have to wrap it in a=
 lambda, so that it is not deduced as a&nbsp;</div><div>function pointer, w=
hich causes indirection. It does not place well with overloading either, I =
have to do:</div><div><br></div><div>myalgo(...., sqrt&lt;int&gt;); // This=
 will cause function pointer deduction, which is bad for inlining + I must =
say &lt;int&gt; explicitely to resolve overloading.</div><div><br></div><di=
v><br></div><div>My proposal has 3 parts: 1. and 3. target making code shor=
ter. 2. targets making the code shorter + at the same time</div><div>making=
 optimizer opportunities for inlining better.</div><div><br></div><div>I wo=
uld like to know if there would be interest for a proposal like the followi=
ng:</div><div><br></div><div>1. Make all function object (less etc.) implic=
itely bindable through an external function that returns the result of call=
ing bind.&nbsp;</div><div>The is_class assert in this implementation is to =
avoid binding function pointers, for performance reasons. The function look=
s like this:</div><div><br></div><div><br></div><div><div>template &lt;clas=
s FuncObject, class... Args&gt;</div><div>constexpr auto implicitely_bindab=
le(FuncObject &amp;&amp; f, Args &amp;&amp;... args) noexcept {</div><div>&=
nbsp; &nbsp; static_assert(std::is_class&lt;FuncObject&gt;::value, "");</di=
v><div>&nbsp; &nbsp; return std::bind(std::forward&lt;FuncObject&gt;(f), st=
d::forward&lt;Args&gt;(args)...);</div><div>}</div></div><div><br></div><di=
v>For each function object in the std library, there would be something sim=
ilar to this (ib stands for implicitely bindable):</div><div><br></div><div=
><div>template &lt;class T1, class T2 =3D T1&gt;</div><div>constexpr auto l=
ess_ib(T1 const &amp; t1, T2 const &amp; t2) noexcept {</div><div>&nbsp; &n=
bsp; return implicitely_bindable(less&lt;&gt;(), t1, t2);</div><div>}</div>=
</div><div><br></div><div><br></div><div>2. Math functions from &lt;cmath&g=
t; header should have a function object version, since a function pointer i=
s not reified and can prevent inlining,</div><div>though my tests in gcc sh=
owed that the compiler could optimize it in the benchmark I did. But I gues=
s it could be otherwise depending</div><div>on the compiler optimizer, so I=
 don't think we should rely on smart optimizers.</div><div>I would propose =
to have function objects for standard math functions like the following:</d=
iv><div><br></div><div>struct sqrt_func {</div><div>&nbsp; &nbsp; template =
&lt;class T&gt;</div><div>&nbsp; &nbsp; auto operator()(T &amp;&amp; arg) c=
onst { return std::sqrt(std::forward&lt;Arg&gt;(arg)); }</div><div>};</div>=
<div><br></div><div>template &lt;class T&gt;</div><div>constexpr auto sqrt_=
ib(T &amp;&amp; arg) noexcept { return implicitely_bindable(sqrt_func(), st=
d::forward&lt;Arg&gt;(arg)); }</div><div><br></div><div><br></div><div><br>=
</div><div>3. Overload placeholders with all operators.&nbsp;</div><div><br=
></div><div>This would enable to write code like this (ib stands for implic=
itely_bindable, ignore the naming, it is just a detail):</div><div><br></di=
v><div>&nbsp; &nbsp;//With lambda</div><div>&nbsp; &nbsp;partition(begin(ve=
c), end(vec), [](int v) { return v &lt; 5; });</div><div>&nbsp; &nbsp;//Wit=
h this proposal</div><div>&nbsp; &nbsp;partition(begin(vec), end(vec), less=
_ib(_1, 5));</div><div><br></div><div>&nbsp; &nbsp; //With lambda</div><div=
><div>&nbsp; &nbsp; transform(begin(vec), end(vec), begin(out), [](double v=
) { return sqrt(v) + pow(v, 5); });</div><div>&nbsp; &nbsp; //With this pro=
posal (overloaded placeholders + implicitely bindable</div><div>&nbsp; &nbs=
p; transform((begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow(_1, 5));<=
/div></div><div><br></div><div><br></div><div>I already wrote some code but=
 it is not finished.</div><div><br></div><div>Regards</div><div><br></div><=
div><br></div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_3_1974761981.1414990399546--

.


Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Sun, 2 Nov 2014 23:28:36 -0800 (PST)
Raw View
------=_Part_1339_967482130.1414999716237
Content-Type: multipart/alternative;
 boundary="----=_Part_1340_1873467473.1414999716237"

------=_Part_1340_1873467473.1414999716237
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Attached a proof of concept. Tested under gcc 4.8.1 mingw.

El lunes, 3 de noviembre de 2014 11:53:19 UTC+7, Germ=C3=A1n Diago escribi=
=C3=B3:
>
> Hello everyone,
>
> I would like to know if there would be interest for the following proposa=
l:
>
> Sometimes we write lambdas or bind expressions for algorithms in the=20
> standard library.
> I feel that this could be made shorter in many common cases, since in thi=
s=20
> kind of code the lambda introducer
> + a return statement + opening and closing braces can make typing=20
> considerably larger for short uses, which
> abound in the standard library algorithms. I also find function objects=
=20
> for standard math functions missing.
> When I want to pass a standard math function, I have to wrap it in a=20
> lambda, so that it is not deduced as a=20
> function pointer, which causes indirection. It does not place well with=
=20
> overloading either, I have to do:
>
> myalgo(...., sqrt<int>); // This will cause function pointer deduction,=
=20
> which is bad for inlining + I must say <int> explicitely to resolve=20
> overloading.
>
>
> My proposal has 3 parts: 1. and 3. target making code shorter. 2. targets=
=20
> making the code shorter + at the same time
> making optimizer opportunities for inlining better.
>
> I would like to know if there would be interest for a proposal like the=
=20
> following:
>
> 1. Make all function object (less etc.) implicitely bindable through an=
=20
> external function that returns the result of calling bind.=20
> The is_class assert in this implementation is to avoid binding function=
=20
> pointers, for performance reasons. The function looks like this:
>
>
> template <class FuncObject, class... Args>
> constexpr auto implicitely_bindable(FuncObject && f, Args &&... args)=20
> noexcept {
>     static_assert(std::is_class<FuncObject>::value, "");
>     return std::bind(std::forward<FuncObject>(f),=20
> std::forward<Args>(args)...);
> }
>
> For each function object in the std library, there would be something=20
> similar to this (ib stands for implicitely bindable):
>
> template <class T1, class T2 =3D T1>
> constexpr auto less_ib(T1 const & t1, T2 const & t2) noexcept {
>     return implicitely_bindable(less<>(), t1, t2);
> }
>
>
> 2. Math functions from <cmath> header should have a function object=20
> version, since a function pointer is not reified and can prevent inlining=
,
> though my tests in gcc showed that the compiler could optimize it in the=
=20
> benchmark I did. But I guess it could be otherwise depending
> on the compiler optimizer, so I don't think we should rely on smart=20
> optimizers.
> I would propose to have function objects for standard math functions like=
=20
> the following:
>
> struct sqrt_func {
>     template <class T>
>     auto operator()(T && arg) const { return=20
> std::sqrt(std::forward<Arg>(arg)); }
> };
>
> template <class T>
> constexpr auto sqrt_ib(T && arg) noexcept { return=20
> implicitely_bindable(sqrt_func(), std::forward<Arg>(arg)); }
>
>
>
> 3. Overload placeholders with all operators.=20
>
> This would enable to write code like this (ib stands for=20
> implicitely_bindable, ignore the naming, it is just a detail):
>
>    //With lambda
>    partition(begin(vec), end(vec), [](int v) { return v < 5; });
>    //With this proposal
>    partition(begin(vec), end(vec), less_ib(_1, 5));
>
>     //With lambda
>     transform(begin(vec), end(vec), begin(out), [](double v) { return=20
> sqrt(v) + pow(v, 5); });
>     //With this proposal (overloaded placeholders + implicitely bindable
>     transform((begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow(_1, 5)=
);
>
>
> I already wrote some code but it is not finished.
>
> Regards
>
>
>

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_1340_1873467473.1414999716237
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Attached a proof of concept. Tested under gcc 4.8.1 mingw.=
<br><br>El lunes, 3 de noviembre de 2014 11:53:19 UTC+7, Germ=C3=A1n Diago =
 escribi=C3=B3:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">Hello everyone,<div><br></div><div>I would like to know if there would be=
 interest for the following proposal:</div><div><br></div><div>Sometimes we=
 write lambdas or bind expressions for algorithms in the standard library.<=
/div><div>I feel that this could be made shorter in many common cases, sinc=
e in this kind of code the lambda introducer</div><div>+ a return statement=
 + opening and closing braces can make typing considerably larger for short=
 uses, which</div><div>abound in the standard library algorithms. I also fi=
nd function objects for standard math functions missing.</div><div>When I w=
ant to pass a standard math function, I have to wrap it in a lambda, so tha=
t it is not deduced as a&nbsp;</div><div>function pointer, which causes ind=
irection. It does not place well with overloading either, I have to do:</di=
v><div><br></div><div>myalgo(...., sqrt&lt;int&gt;); // This will cause fun=
ction pointer deduction, which is bad for inlining + I must say &lt;int&gt;=
 explicitely to resolve overloading.</div><div><br></div><div><br></div><di=
v>My proposal has 3 parts: 1. and 3. target making code shorter. 2. targets=
 making the code shorter + at the same time</div><div>making optimizer oppo=
rtunities for inlining better.</div><div><br></div><div>I would like to kno=
w if there would be interest for a proposal like the following:</div><div><=
br></div><div>1. Make all function object (less etc.) implicitely bindable =
through an external function that returns the result of calling bind.&nbsp;=
</div><div>The is_class assert in this implementation is to avoid binding f=
unction pointers, for performance reasons. The function looks like this:</d=
iv><div><br></div><div><br></div><div><div>template &lt;class FuncObject, c=
lass... Args&gt;</div><div>constexpr auto implicitely_bindable(<wbr>FuncObj=
ect &amp;&amp; f, Args &amp;&amp;... args) noexcept {</div><div>&nbsp; &nbs=
p; static_assert(std::is_class&lt;<wbr>FuncObject&gt;::value, "");</div><di=
v>&nbsp; &nbsp; return std::bind(std::forward&lt;<wbr>FuncObject&gt;(f), st=
d::forward&lt;Args&gt;(args)...);</div><div>}</div></div><div><br></div><di=
v>For each function object in the std library, there would be something sim=
ilar to this (ib stands for implicitely bindable):</div><div><br></div><div=
><div>template &lt;class T1, class T2 =3D T1&gt;</div><div>constexpr auto l=
ess_ib(T1 const &amp; t1, T2 const &amp; t2) noexcept {</div><div>&nbsp; &n=
bsp; return implicitely_bindable(less&lt;&gt;(), t1, t2);</div><div>}</div>=
</div><div><br></div><div><br></div><div>2. Math functions from &lt;cmath&g=
t; header should have a function object version, since a function pointer i=
s not reified and can prevent inlining,</div><div>though my tests in gcc sh=
owed that the compiler could optimize it in the benchmark I did. But I gues=
s it could be otherwise depending</div><div>on the compiler optimizer, so I=
 don't think we should rely on smart optimizers.</div><div>I would propose =
to have function objects for standard math functions like the following:</d=
iv><div><br></div><div>struct sqrt_func {</div><div>&nbsp; &nbsp; template =
&lt;class T&gt;</div><div>&nbsp; &nbsp; auto operator()(T &amp;&amp; arg) c=
onst { return std::sqrt(std::forward&lt;Arg&gt;(<wbr>arg)); }</div><div>};<=
/div><div><br></div><div>template &lt;class T&gt;</div><div>constexpr auto =
sqrt_ib(T &amp;&amp; arg) noexcept { return implicitely_bindable(sqrt_<wbr>=
func(), std::forward&lt;Arg&gt;(arg)); }</div><div><br></div><div><br></div=
><div><br></div><div>3. Overload placeholders with all operators.&nbsp;</di=
v><div><br></div><div>This would enable to write code like this (ib stands =
for implicitely_bindable, ignore the naming, it is just a detail):</div><di=
v><br></div><div>&nbsp; &nbsp;//With lambda</div><div>&nbsp; &nbsp;partitio=
n(begin(vec), end(vec), [](int v) { return v &lt; 5; });</div><div>&nbsp; &=
nbsp;//With this proposal</div><div>&nbsp; &nbsp;partition(begin(vec), end(=
vec), less_ib(_1, 5));</div><div><br></div><div>&nbsp; &nbsp; //With lambda=
</div><div><div>&nbsp; &nbsp; transform(begin(vec), end(vec), begin(out), [=
](double v) { return sqrt(v) + pow(v, 5); });</div><div>&nbsp; &nbsp; //Wit=
h this proposal (overloaded placeholders + implicitely bindable</div><div>&=
nbsp; &nbsp; transform((begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow=
(_1, 5));</div></div><div><br></div><div><br></div><div>I already wrote som=
e code but it is not finished.</div><div><br></div><div>Regards</div><div><=
br></div><div><br></div></div></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_1340_1873467473.1414999716237--
------=_Part_1339_967482130.1414999716237
Content-Type: text/x-c++src; charset=US-ASCII;
 name=implicit_bindable_objects.cpp
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=implicit_bindable_objects.cpp
X-Attachment-Id: d61f6439-d7cc-419a-866a-bafab95389b8
Content-ID: <d61f6439-d7cc-419a-866a-bafab95389b8>

#include <chrono>
#include <cassert>
#include <utility>
#include <functional>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;


template <class FuncObject, class... Args>
constexpr auto implicitely_bindable(FuncObject && f, Args &&... args) noexcept {
    static_assert(std::is_class<FuncObject>::value, "");
    return std::bind(std::forward<FuncObject>(f), std::forward<Args>(args)...);
}


struct sqrt_func {
    template <class T>
    auto operator()(T arg)
            const {
        return std::sqrt(arg);
    }
};

struct pow_func {
    template <class T, class U>
    auto operator()(T && arg, U && arg2)
            const {
        return std::pow(std::forward<T>(arg), std::forward<U>(arg2));
    }
};


struct less_func {
    template <class T1, class T2 = T1>
    bool operator()(T1 const & t1, T2 const & t2) const {
        return t1 < t2;
    }
};


template <class T1, class T2 = T1>
constexpr auto less_ib(T1 const & t1, T2 const & t2) noexcept {
    return implicitely_bindable(less_func(), t1, t2);
}


template <class T1>
constexpr auto sqrt_ib(T1 arg) noexcept {
    return implicitely_bindable(sqrt_func(), arg);
}


template <class T1, class T2>
constexpr auto pow_ib(T1 && arg1, T2 && arg2) noexcept {
    return implicitely_bindable(pow_func(), std::forward<T1>(arg1),
                                std::forward<T2>(arg2));
}


void test_implicitly_bindable_less() {
    using std::placeholders::_1;

    std::vector<int> vec{1, 4, -7, 2, 21, 47};

    //With lambda
    auto part_point = partition(begin(vec), end(vec), [](int v) { return v < 5; });

    //With this proposal
    auto part_point2 = partition(begin(vec), end(vec), less_ib(_1, 5));
    assert(distance(begin(vec), part_point) == 4);
}


struct plus_func {
    template <class T1, class T2>
    auto operator()(T1 && arg1, T2 && arg2) const {
        return arg1 + arg2;
    }
};

struct minus_func {
    template <class T1, class T2>
    auto operator()(T1 && arg1, T2 && arg2) const {
        return arg1 - arg2;
    }
};

template <class T>
struct generates_function_object :
        std::integral_constant<
    bool,
    std::is_bind_expression<T>::value ||
    std::is_placeholder<typename std::decay<T>::type>::value>
{};

template <class T1, class T2,
          class = typename std::enable_if<
              generates_function_object<T1>::value ||
              generates_function_object<T2>::value
              >::type
          >
        constexpr auto operator+(T1 && arg1, T2 && arg2) {
    return std::bind(plus_func(), std::forward<T1>(arg1), std::forward<T2>(arg2));
          }


template <class T1, class T2,
          class = typename std::enable_if<
              generates_function_object<T1>::value ||
              generates_function_object<T2>::value
              >::type
          >
        constexpr auto operator-(T1 && arg1, T2 && arg2) {
    return std::bind(minus_func(), std::forward<T1>(arg1), std::forward<T2>(arg2));
          }


void test_implicitly_bindable_math_funcs_with_placeholders() {
    using std::placeholders::_1;
    std::vector<int> vec{1, 4, -7, 2, 21, 47};
    std::vector<double> out(vec.size());

    //With lambdas
    //transform(begin(vec), end(vec), begin(out), [](double v) { return sqrt(v) + pow(v, 5); });

    //With this proposal
    transform(begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow_ib(_1, 5));

    //With Eric's and others proposal
}


int main(int argc, char * argv[]) {
    using namespace std;
    using namespace std::placeholders;

    //Placeholder extension to function objects.
    test_implicitly_bindable_less();
    test_implicitly_bindable_math_funcs_with_placeholders();

    //An expression that generates bind expression

    auto val = (pow_ib(_1, 4) - _2)(2, 3);
    std::cout << val << std::endl;

    return 0;
}

------=_Part_1339_967482130.1414999716237--

.


Author: Miro Knejp <miro.knejp@gmail.com>
Date: Mon, 3 Nov 2014 11:43:29 +0100
Raw View
--Apple-Mail=_C0242F3C-EA37-4335-A880-3DA086B7EAD2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8

I had something similar in mind a few times, though I was thinking along th=
e lines of anonymous constexpr types.

constexpr struct
{
 template<class T>
 auto operator()(T&& t) { return sqrt(forward<T>(t)); }
}
sqrt_f{};

If only we had constexpr stateless lambdas=E2=80=A6 This works in principle=
, but it might be considered an issue having an instance of sqrt_f in every=
 translation unit though, but using it is straightforward. And it makes bin=
ding consistent.

partition(begin(vec), end(vec), [](int v) { return v < 5; });
- vs -
partition(begin(vec), end(vec), less_ib(_1, 5));
- vs -
partition(begin(vec), end(vec), bind(less_f(_1, 5)));

Having overloads of all the operators on these objects sounds interesting, =
but I wonder if having a general purpose expression template machinery woul=
dn=E2=80=99t make more sense.

> On 03 Nov 2014, at 08:28 , Germ=C3=A1n Diago <germandiago@gmail.com> wrot=
e:
>=20
> Attached a proof of concept. Tested under gcc 4.8.1 mingw.
>=20
> El lunes, 3 de noviembre de 2014 11:53:19 UTC+7, Germ=C3=A1n Diago escrib=
i=C3=B3:
> Hello everyone,
>=20
> I would like to know if there would be interest for the following proposa=
l:
>=20
> Sometimes we write lambdas or bind expressions for algorithms in the stan=
dard library.
> I feel that this could be made shorter in many common cases, since in thi=
s kind of code the lambda introducer
> + a return statement + opening and closing braces can make typing conside=
rably larger for short uses, which
> abound in the standard library algorithms. I also find function objects f=
or standard math functions missing.
> When I want to pass a standard math function, I have to wrap it in a lamb=
da, so that it is not deduced as a=20
> function pointer, which causes indirection. It does not place well with o=
verloading either, I have to do:
>=20
> myalgo(...., sqrt<int>); // This will cause function pointer deduction, w=
hich is bad for inlining + I must say <int> explicitely to resolve overload=
ing.
>=20
>=20
> My proposal has 3 parts: 1. and 3. target making code shorter. 2. targets=
 making the code shorter + at the same time
> making optimizer opportunities for inlining better.
>=20
> I would like to know if there would be interest for a proposal like the f=
ollowing:
>=20
> 1. Make all function object (less etc.) implicitely bindable through an e=
xternal function that returns the result of calling bind.=20
> The is_class assert in this implementation is to avoid binding function p=
ointers, for performance reasons. The function looks like this:
>=20
>=20
> template <class FuncObject, class... Args>
> constexpr auto implicitely_bindable(FuncObject && f, Args &&... args) noe=
xcept {
>     static_assert(std::is_class<FuncObject>::value, "");
>     return std::bind(std::forward<FuncObject>(f), std::forward<Args>(args=
)...);
> }
>=20
> For each function object in the std library, there would be something sim=
ilar to this (ib stands for implicitely bindable):
>=20
> template <class T1, class T2 =3D T1>
> constexpr auto less_ib(T1 const & t1, T2 const & t2) noexcept {
>     return implicitely_bindable(less<>(), t1, t2);
> }
>=20
>=20
> 2. Math functions from <cmath> header should have a function object versi=
on, since a function pointer is not reified and can prevent inlining,
> though my tests in gcc showed that the compiler could optimize it in the =
benchmark I did. But I guess it could be otherwise depending
> on the compiler optimizer, so I don't think we should rely on smart optim=
izers.
> I would propose to have function objects for standard math functions like=
 the following:
>=20
> struct sqrt_func {
>     template <class T>
>     auto operator()(T && arg) const { return std::sqrt(std::forward<Arg>(=
arg)); }
> };
>=20
> template <class T>
> constexpr auto sqrt_ib(T && arg) noexcept { return implicitely_bindable(s=
qrt_func(), std::forward<Arg>(arg)); }
>=20
>=20
>=20
> 3. Overload placeholders with all operators.=20
>=20
> This would enable to write code like this (ib stands for implicitely_bind=
able, ignore the naming, it is just a detail):
>=20
>    //With lambda
>    partition(begin(vec), end(vec), [](int v) { return v < 5; });
>    //With this proposal
>    partition(begin(vec), end(vec), less_ib(_1, 5));
>=20
>     //With lambda
>     transform(begin(vec), end(vec), begin(out), [](double v) { return sqr=
t(v) + pow(v, 5); });
>     //With this proposal (overloaded placeholders + implicitely bindable
>     transform((begin(vec), end(vec), begin(out), sqrt_ib(_1) + pow(_1, 5)=
);
>=20
>=20
> I already wrote some code but it is not finished.
>=20
> Regards
>=20
>=20
>=20
> --=20
>=20
> ---=20
> You received this message because you are subscribed to the Google Groups=
 "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
 email to std-proposals+unsubscribe@isocpp.org <mailto:std-proposals+unsubs=
cribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org <mailto:std=
-proposals@isocpp.org>.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-propo=
sals/ <http://groups.google.com/a/isocpp.org/group/std-proposals/>.
> <implicit_bindable_objects.cpp>

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--Apple-Mail=_C0242F3C-EA37-4335-A880-3DA086B7EAD2
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D"">I had something si=
milar in mind a few times, though I was thinking along the lines of anonymo=
us constexpr types.<div class=3D""><br class=3D""></div><div class=3D"">con=
stexpr struct</div><div class=3D"">{</div><div class=3D""><span class=3D"Ap=
ple-tab-span" style=3D"white-space:pre"> </span>template&lt;class T&gt;</di=
v><div class=3D""><span class=3D"Apple-tab-span" style=3D"white-space:pre">=
 </span>auto operator()(T&amp;&amp; t) { return sqrt(forward&lt;T&gt;(t)); =
}</div><div class=3D"">}</div><div class=3D"">sqrt_f{};</div><div class=3D"=
"><br class=3D""></div><div class=3D"">If only we had constexpr stateless l=
ambdas=E2=80=A6 This works in principle, but it might be considered an issu=
e having an instance of sqrt_f in every translation unit though, but using =
it is straightforward. And it makes binding consistent.</div><div class=3D"=
"><br class=3D""></div><div class=3D"">partition(begin(vec), end(vec), [](i=
nt v) { return v &lt; 5; });</div><div class=3D"">- vs -</div><div class=3D=
"">partition(begin(vec), end(vec), less_ib(_1, 5));</div><div class=3D"">- =
vs -</div><div class=3D"">partition(begin(vec), end(vec), bind(less_f(_1, 5=
)));</div><div class=3D""><br class=3D""></div><div class=3D"">Having overl=
oads of all the operators on these objects sounds interesting, but I wonder=
 if having a general purpose expression template machinery wouldn=E2=80=99t=
 make more sense.</div><div class=3D""><br class=3D""><div><blockquote type=
=3D"cite" class=3D""><div class=3D"">On 03 Nov 2014, at 08:28 , Germ=C3=A1n=
 Diago &lt;<a href=3D"mailto:germandiago@gmail.com" class=3D"">germandiago@=
gmail.com</a>&gt; wrote:</div><br class=3D"Apple-interchange-newline"><div =
class=3D""><div dir=3D"ltr" class=3D"">Attached a proof of concept. Tested =
under gcc 4.8.1 mingw.<br class=3D""><br class=3D"">El lunes, 3 de noviembr=
e de 2014 11:53:19 UTC+7, Germ=C3=A1n Diago  escribi=C3=B3:<blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr" class=3D"">Hello everyone,<di=
v class=3D""><br class=3D""></div><div class=3D"">I would like to know if t=
here would be interest for the following proposal:</div><div class=3D""><br=
 class=3D""></div><div class=3D"">Sometimes we write lambdas or bind expres=
sions for algorithms in the standard library.</div><div class=3D"">I feel t=
hat this could be made shorter in many common cases, since in this kind of =
code the lambda introducer</div><div class=3D"">+ a return statement + open=
ing and closing braces can make typing considerably larger for short uses, =
which</div><div class=3D"">abound in the standard library algorithms. I als=
o find function objects for standard math functions missing.</div><div clas=
s=3D"">When I want to pass a standard math function, I have to wrap it in a=
 lambda, so that it is not deduced as a&nbsp;</div><div class=3D"">function=
 pointer, which causes indirection. It does not place well with overloading=
 either, I have to do:</div><div class=3D""><br class=3D""></div><div class=
=3D"">myalgo(...., sqrt&lt;int&gt;); // This will cause function pointer de=
duction, which is bad for inlining + I must say &lt;int&gt; explicitely to =
resolve overloading.</div><div class=3D""><br class=3D""></div><div class=
=3D""><br class=3D""></div><div class=3D"">My proposal has 3 parts: 1. and =
3. target making code shorter. 2. targets making the code shorter + at the =
same time</div><div class=3D"">making optimizer opportunities for inlining =
better.</div><div class=3D""><br class=3D""></div><div class=3D"">I would l=
ike to know if there would be interest for a proposal like the following:</=
div><div class=3D""><br class=3D""></div><div class=3D"">1. Make all functi=
on object (less etc.) implicitely bindable through an external function tha=
t returns the result of calling bind.&nbsp;</div><div class=3D"">The is_cla=
ss assert in this implementation is to avoid binding function pointers, for=
 performance reasons. The function looks like this:</div><div class=3D""><b=
r class=3D""></div><div class=3D""><br class=3D""></div><div class=3D""><di=
v class=3D"">template &lt;class FuncObject, class... Args&gt;</div><div cla=
ss=3D"">constexpr auto implicitely_bindable(<wbr class=3D"">FuncObject &amp=
;&amp; f, Args &amp;&amp;... args) noexcept {</div><div class=3D"">&nbsp; &=
nbsp; static_assert(std::is_class&lt;<wbr class=3D"">FuncObject&gt;::value,=
 "");</div><div class=3D"">&nbsp; &nbsp; return std::bind(std::forward&lt;<=
wbr class=3D"">FuncObject&gt;(f), std::forward&lt;Args&gt;(args)...);</div>=
<div class=3D"">}</div></div><div class=3D""><br class=3D""></div><div clas=
s=3D"">For each function object in the std library, there would be somethin=
g similar to this (ib stands for implicitely bindable):</div><div class=3D"=
"><br class=3D""></div><div class=3D""><div class=3D"">template &lt;class T=
1, class T2 =3D T1&gt;</div><div class=3D"">constexpr auto less_ib(T1 const=
 &amp; t1, T2 const &amp; t2) noexcept {</div><div class=3D"">&nbsp; &nbsp;=
 return implicitely_bindable(less&lt;&gt;(), t1, t2);</div><div class=3D"">=
}</div></div><div class=3D""><br class=3D""></div><div class=3D""><br class=
=3D""></div><div class=3D"">2. Math functions from &lt;cmath&gt; header sho=
uld have a function object version, since a function pointer is not reified=
 and can prevent inlining,</div><div class=3D"">though my tests in gcc show=
ed that the compiler could optimize it in the benchmark I did. But I guess =
it could be otherwise depending</div><div class=3D"">on the compiler optimi=
zer, so I don't think we should rely on smart optimizers.</div><div class=
=3D"">I would propose to have function objects for standard math functions =
like the following:</div><div class=3D""><br class=3D""></div><div class=3D=
"">struct sqrt_func {</div><div class=3D"">&nbsp; &nbsp; template &lt;class=
 T&gt;</div><div class=3D"">&nbsp; &nbsp; auto operator()(T &amp;&amp; arg)=
 const { return std::sqrt(std::forward&lt;Arg&gt;(<wbr class=3D"">arg)); }<=
/div><div class=3D"">};</div><div class=3D""><br class=3D""></div><div clas=
s=3D"">template &lt;class T&gt;</div><div class=3D"">constexpr auto sqrt_ib=
(T &amp;&amp; arg) noexcept { return implicitely_bindable(sqrt_<wbr class=
=3D"">func(), std::forward&lt;Arg&gt;(arg)); }</div><div class=3D""><br cla=
ss=3D""></div><div class=3D""><br class=3D""></div><div class=3D""><br clas=
s=3D""></div><div class=3D"">3. Overload placeholders with all operators.&n=
bsp;</div><div class=3D""><br class=3D""></div><div class=3D"">This would e=
nable to write code like this (ib stands for implicitely_bindable, ignore t=
he naming, it is just a detail):</div><div class=3D""><br class=3D""></div>=
<div class=3D"">&nbsp; &nbsp;//With lambda</div><div class=3D"">&nbsp; &nbs=
p;partition(begin(vec), end(vec), [](int v) { return v &lt; 5; });</div><di=
v class=3D"">&nbsp; &nbsp;//With this proposal</div><div class=3D"">&nbsp; =
&nbsp;partition(begin(vec), end(vec), less_ib(_1, 5));</div><div class=3D""=
><br class=3D""></div><div class=3D"">&nbsp; &nbsp; //With lambda</div><div=
 class=3D""><div class=3D"">&nbsp; &nbsp; transform(begin(vec), end(vec), b=
egin(out), [](double v) { return sqrt(v) + pow(v, 5); });</div><div class=
=3D"">&nbsp; &nbsp; //With this proposal (overloaded placeholders + implici=
tely bindable</div><div class=3D"">&nbsp; &nbsp; transform((begin(vec), end=
(vec), begin(out), sqrt_ib(_1) + pow(_1, 5));</div></div><div class=3D""><b=
r class=3D""></div><div class=3D""><br class=3D""></div><div class=3D"">I a=
lready wrote some code but it is not finished.</div><div class=3D""><br cla=
ss=3D""></div><div class=3D"">Regards</div><div class=3D""><br class=3D""><=
/div><div class=3D""><br class=3D""></div></div></blockquote></div><div cla=
ss=3D""><br class=3D"webkit-block-placeholder"></div>

-- <br class=3D"">
<br class=3D"">
--- <br class=3D"">
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.<br class=3D"">
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" class=3D"">=
std-proposals+unsubscribe@isocpp.org</a>.<br class=3D"">
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" class=3D"">std-proposals@isocpp.org</a>.<br class=3D"">
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" class=3D"">http://groups.google.com/a/isocpp.org/group/std-=
proposals/</a>.<br class=3D"">
<span id=3D"cid:d61f6439-d7cc-419a-866a-bafab95389b8">&lt;implicit_bindable=
_objects.cpp&gt;</span></div></blockquote></div><br class=3D""></div></body=
></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--Apple-Mail=_C0242F3C-EA37-4335-A880-3DA086B7EAD2--

.


Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Mon, 3 Nov 2014 03:03:49 -0800 (PST)
Raw View
------=_Part_416_807977793.1415012629183
Content-Type: multipart/alternative;
 boundary="----=_Part_417_1143666970.1415012629183"

------=_Part_417_1143666970.1415012629183
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable



El lunes, 3 de noviembre de 2014 17:43:35 UTC+7, Miro Knejp escribi=C3=B3:
>
> I had something similar in mind a few times, though I was thinking along=
=20
> the lines of anonymous constexpr types.
>
> constexpr struct
> {
> template<class T>
> auto operator()(T&& t) { return sqrt(forward<T>(t)); }
> }
> sqrt_f{};
>
> If only we had constexpr stateless lambdas=E2=80=A6 This works in princip=
le, but=20
> it might be considered an issue having an instance of sqrt_f in every=20
> translation unit though, but using it is straightforward. And it makes=20
> binding consistent.
>
> Well, the important thing is the feature. Maybe that is better than what =
I=20
proposed.

=20

> partition(begin(vec), end(vec), [](int v) { return v < 5; });
> - vs -
> partition(begin(vec), end(vec), less_ib(_1, 5));
> - vs -
> partition(begin(vec), end(vec), bind(less_f(_1, 5)));
>
> I noticed that having less_b and all operators is nonsense actually.=20
Overloading operators for placeholders is enough and you can forward
it to bind. I attach my latest implementation. It has a bunch of math=20
functions working and all binary operators.

Adding the rest should not be difficult, since I am using macros to=20
generate all the bolerplate.
=20

> Having overloads of all the operators on these objects sounds interesting=
,=20
> but I wonder if having a general purpose expression template machinery=20
> wouldn=E2=80=99t make more sense.
>

Well, I think that this would cover many common use cases and it is quite=
=20
simple. A general metaprogramming library is something
that it is more difficult with no much gain, since when you want to do=20
something complicated, you can go back to lambdas. At least
now you could do (with ranges):

transform(vec, _1 * _1);
vs
transform(vec, [](double val) { return val * val; });

I think wrapping the math library is a common case and there are many=20
context where you would like, for example:

transform(vec, &sqrt<int>); //But this is a func pointer, not good!=20

So you end up doing:

transform(vec, [](int val) { return sqrt(val); });

which is tedious.

Having a wrapper for that will eliminate the common use:

transform(vec, sqrt_b(_1));

You can also combine things:

transform(vec, pow_b(_1, 5) + 1);

Of course, this idea is not original from me, there are libraries which do=
=20
that already, but would be nice to save some typing.

Regards


>

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_417_1143666970.1415012629183
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>El lunes, 3 de noviembre de 2014 17:43:35 UTC+7, M=
iro Knejp  escribi=C3=B3:<blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
style=3D"word-wrap:break-word">I had something similar in mind a few times,=
 though I was thinking along the lines of anonymous constexpr types.<div><b=
r></div><div>constexpr struct</div><div>{</div><div><span style=3D"white-sp=
ace:pre"> </span>template&lt;class T&gt;</div><div><span style=3D"white-spa=
ce:pre"> </span>auto operator()(T&amp;&amp; t) { return sqrt(forward&lt;T&g=
t;(t)); }</div><div>}</div><div>sqrt_f{};</div><div><br></div><div>If only =
we had constexpr stateless lambdas=E2=80=A6 This works in principle, but it=
 might be considered an issue having an instance of sqrt_f in every transla=
tion unit though, but using it is straightforward. And it makes binding con=
sistent.</div><div><br></div></div></blockquote><div>Well, the important th=
ing is the feature. Maybe that is better than what I proposed.</div><div><b=
r></div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
style=3D"word-wrap:break-word"><div></div><div>partition(begin(vec), end(ve=
c), [](int v) { return v &lt; 5; });</div><div>- vs -</div><div>partition(b=
egin(vec), end(vec), less_ib(_1, 5));</div><div>- vs -</div><div>partition(=
begin(vec), end(vec), bind(less_f(_1, 5)));</div><div><br></div></div></blo=
ckquote><div>I noticed that having less_b and all operators is nonsense act=
ually. Overloading operators for placeholders is enough and you can forward=
</div><div>it to bind. I attach my latest implementation. It has a bunch of=
 math functions working and all binary operators.</div><div><br></div><div>=
Adding the rest should not be difficult, since I am using macros to generat=
e all the bolerplate.</div><div>&nbsp;</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div style=3D"word-wrap:break-word"><div></div><div>Having ov=
erloads of all the operators on these objects sounds interesting, but I won=
der if having a general purpose expression template machinery wouldn=E2=80=
=99t make more sense.</div></div></blockquote><div><br></div><div>Well, I t=
hink that this would cover many common use cases and it is quite simple. A =
general metaprogramming library is something</div><div>that it is more diff=
icult with no much gain, since when you want to do something complicated, y=
ou can go back to lambdas. At least</div><div>now you could do (with ranges=
):</div><div><br></div><div>transform(vec, _1 * _1);</div><div>vs</div><div=
>transform(vec, [](double val) { return val * val; });</div><div><br></div>=
<div>I think wrapping the math library is a common case and there are many =
context where you would like, for example:</div><div><br></div><div>transfo=
rm(vec, &amp;sqrt&lt;int&gt;); //But this is a func pointer, not good!&nbsp=
;</div><div><br></div><div>So you end up doing:</div><div><br></div><div>tr=
ansform(vec, [](int val) { return sqrt(val); });</div><div><br></div><div>w=
hich is tedious.</div><div><br></div><div>Having a wrapper for that will el=
iminate the common use:</div><div><br></div><div>transform(vec, sqrt_b(_1))=
;</div><div><br></div><div>You can also combine things:</div><div><br></div=
><div>transform(vec, pow_b(_1, 5) + 1);</div><div><br></div><div>Of course,=
 this idea is not original from me, there are libraries which do that alrea=
dy, but would be nice to save some typing.</div><div><br></div><div>Regards=
</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div styl=
e=3D"word-wrap:break-word"><div><br></div></div></blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_417_1143666970.1415012629183--
------=_Part_416_807977793.1415012629183
Content-Type: text/x-c++src; charset=US-ASCII;
 name=implicit_bindable_objects.cpp
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=implicit_bindable_objects.cpp
X-Attachment-Id: 6caf61a2-0097-4992-95ec-bafbbaf2b81e
Content-ID: <6caf61a2-0097-4992-95ec-bafbbaf2b81e>

#include <chrono>
#include <cassert>
#include <utility>
#include <functional>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;

template <class FuncObject, class... Args>
constexpr auto generate_bindable(FuncObject && f, Args &&... args) noexcept {
    static_assert(std::is_class<FuncObject>::value, "");
    return std::bind(std::forward<FuncObject>(f), std::forward<Args>(args)...);
}

template <class T>
struct generates_function_object :
        std::integral_constant<
    bool,
    std::is_bind_expression<T>::value ||
    std::is_placeholder<typename std::decay<T>::type>::value>
{};



#define FOREACH_BINARY_OPERATOR(apply)          \
    apply(less, <)                              \
    apply(plus, +)                              \
    apply(minus, -)                             \
    apply(times, *)                             \
    apply(divides, /)                           \
    apply(modulus, %)                           \
    apply(logical_and, &&)                      \
    apply(logical_or, ||)                       \
    apply(less_eq, <=)                          \
            apply(greater, >)                   \
    apply(greater_eq, >=)                       \
    apply(not_equal_to, !=)                     \
    apply(bit_or, |)                            \
    apply(bit_and, &)                           \
    apply(bit_xor, ^)


#define FOREACH_CMATH_FUNC(apply)               \
    apply(sqrt)                                 \
    apply(pow)                                  \
    apply(abs)                                  \
    apply(labs)                                 \
    apply(llabs)                                \
    apply(div)                                  \
    apply(ldiv)                                 \
    apply(lldiv)                                \
    apply(fabs)                                 \
    apply(fmod)                                 \
    apply(remainder)                            \
    apply(remquo)                               \
    apply(fma)                                  \
    apply(fmax)                                 \
    apply(fmin)                                 \
    apply(nanf)                                 \
    apply(nan)                                  \
    apply(nanl)                                 \
    apply(exp)                                  \
    apply(exp2)                                 \
    apply(expm1)                                \
    apply(log)                                  \
    apply(log10)                                \
    apply(log2)                                 \
    apply(log1p)                                \
            apply(cbrt)                         \
    apply(hypot)                                \
    apply(sin)                                  \
    apply(cos)                                  \
    apply(tan)                                  \
            apply(asin)                         \
    apply(acos)                                 \
    apply(atan)                                 \
    apply(atan2)                                \
    apply(sinh)                                 \
    apply(cosh)                                 \
            apply(tanh)                         \
    apply(asinh)                                \
    apply(acosh)                                \
    apply(atanh)                                \
    apply(ceil)                                 \
    apply(floor)                                \
    apply(trunc)                                \
    apply(round)                                \
    apply(lround)                               \
    apply(llround)                              \
    apply(rint)                                 \
    apply(lrint)                                \
    apply(llrint)


#define GENERATE_BINDABLE_BINARY_OPS(opname, op)   \
    struct opname##_func {                          \
template <class T1, class T2> \
auto operator ()(T1 && t1, T2 && t2) const { return std::forward<T1>(t1) \
            op std::forward<T2>(t2); } \
}; \
    template <class T1, class T2,               \
              class = typename std::enable_if \
<                                                                        \
 generates_function_object<T1>::value || \
 generates_function_object<T2>::value                                   \
 >::type                                                                \
 >                                                                      \
 constexpr auto operator op(T1 && arg1, T2 && arg2)                     \
{                                                                       \
    return std::bind(opname##_func(),                                     \
        std::forward<T1>(arg1), std::forward<T2>(arg2));                \
}

FOREACH_BINARY_OPERATOR(GENERATE_BINDABLE_BINARY_OPS)
#undef GENERATE_BINDABLE_BINARY_OPS


#define GENERATE_BINDABLE_CMATH_OPS(opname)                             \
    struct opname##_func {                                              \
        template <class... Args>                                        \
        auto operator()(Args &&... args) const {                        \
            return ::std::opname(std::forward<Args>(args)...);          \
        }                                                               \
    };                                                                  \
    template <class... Args>                                            \
    auto opname##_b(Args &&... args) { return                           \
                generate_bindable(                                      \
                    std::forward<opname##_func>(opname##_func()), std::forward<Args>(args)...); }


FOREACH_CMATH_FUNC(GENERATE_BINDABLE_CMATH_OPS)
#undef GENERATE_BINDABLE_CMATH_OPS


void test_implicitly_bindable_less() {
    using std::placeholders::_1;

    std::vector<int> vec{1, 4, -7, 2, 21, 47};

    //With lambda
    //auto part_point = partition(begin(vec), end(vec), [](int v) { return v < 5 && v & 1; });
    //With this proposal.
    auto part_point2 = partition(begin(vec), end(vec), _1 < 5 && _1 & 1);
    assert(distance(begin(vec), part_point2) == 2);
}



void test_implicitly_bindable_math_funcs_with_placeholders() {
    using std::placeholders::_1;
    std::vector<int> vec{1, 4, -7, 2, 21, 47};
    std::vector<double> out(vec.size());

    //transform(begin(vec), end(vec), begin(out), [](auto && a) { return sqrt(a) + pow(a, 5) * _1 });
    //With this proposal
    transform(begin(vec), end(vec), begin(out), sqrt_b(_1) + pow_b(_1, 5) * _1);
}



int main(int argc, char * argv[]) {
    using namespace std;
    using namespace std::placeholders;

    //Placeholder extension to function objects.
    test_implicitly_bindable_less();
    test_implicitly_bindable_math_funcs_with_placeholders();

    return 0;
}

------=_Part_416_807977793.1415012629183--

.