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 </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<int>); // This=
will cause function pointer deduction, which is bad for inlining + I must =
say <int> 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. </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 <clas=
s FuncObject, class... Args></div><div>constexpr auto implicitely_bindab=
le(FuncObject && f, Args &&... args) noexcept {</div><div>&=
nbsp; static_assert(std::is_class<FuncObject>::value, "");</di=
v><div> return std::bind(std::forward<FuncObject>(f), st=
d::forward<Args>(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 <class T1, class T2 =3D T1></div><div>constexpr auto l=
ess_ib(T1 const & t1, T2 const & t2) noexcept {</div><div> &n=
bsp; return implicitely_bindable(less<>(), t1, t2);</div><div>}</div>=
</div><div><br></div><div><br></div><div>2. Math functions from <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> template =
<class T></div><div> auto operator()(T && arg) c=
onst { return std::sqrt(std::forward<Arg>(arg)); }</div><div>};</div>=
<div><br></div><div>template <class T></div><div>constexpr auto sqrt_=
ib(T && arg) noexcept { return implicitely_bindable(sqrt_func(), st=
d::forward<Arg>(arg)); }</div><div><br></div><div><br></div><div><br>=
</div><div>3. Overload placeholders with all operators. </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> //With lambda</div><div> partition(begin(ve=
c), end(vec), [](int v) { return v < 5; });</div><div> //Wit=
h this proposal</div><div> partition(begin(vec), end(vec), less=
_ib(_1, 5));</div><div><br></div><div> //With lambda</div><div=
><div> transform(begin(vec), end(vec), begin(out), [](double v=
) { return sqrt(v) + pow(v, 5); });</div><div> //With this pro=
posal (overloaded placeholders + implicitely bindable</div><div> &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" 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 </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<int>); // This will cause fun=
ction pointer deduction, which is bad for inlining + I must say <int>=
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. =
</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 <class FuncObject, c=
lass... Args></div><div>constexpr auto implicitely_bindable(<wbr>FuncObj=
ect && f, Args &&... args) noexcept {</div><div> &nbs=
p; static_assert(std::is_class<<wbr>FuncObject>::value, "");</div><di=
v> return std::bind(std::forward<<wbr>FuncObject>(f), st=
d::forward<Args>(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 <class T1, class T2 =3D T1></div><div>constexpr auto l=
ess_ib(T1 const & t1, T2 const & t2) noexcept {</div><div> &n=
bsp; return implicitely_bindable(less<>(), t1, t2);</div><div>}</div>=
</div><div><br></div><div><br></div><div>2. Math functions from <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> template =
<class T></div><div> auto operator()(T && arg) c=
onst { return std::sqrt(std::forward<Arg>(<wbr>arg)); }</div><div>};<=
/div><div><br></div><div>template <class T></div><div>constexpr auto =
sqrt_ib(T && arg) noexcept { return implicitely_bindable(sqrt_<wbr>=
func(), std::forward<Arg>(arg)); }</div><div><br></div><div><br></div=
><div><br></div><div>3. Overload placeholders with all operators. </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> //With lambda</div><div> partitio=
n(begin(vec), end(vec), [](int v) { return v < 5; });</div><div> &=
nbsp;//With this proposal</div><div> partition(begin(vec), end(=
vec), less_ib(_1, 5));</div><div><br></div><div> //With lambda=
</div><div><div> transform(begin(vec), end(vec), begin(out), [=
](double v) { return sqrt(v) + pow(v, 5); });</div><div> //Wit=
h this proposal (overloaded placeholders + implicitely bindable</div><div>&=
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" 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<class T></di=
v><div class=3D""><span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span>auto operator()(T&& t) { return sqrt(forward<T>(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 < 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 <<a href=3D"mailto:germandiago@gmail.com" class=3D"">germandiago@=
gmail.com</a>> 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 </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<int>); // This will cause function pointer de=
duction, which is bad for inlining + I must say <int> 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. </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 <class FuncObject, class... Args></div><div cla=
ss=3D"">constexpr auto implicitely_bindable(<wbr class=3D"">FuncObject &=
;& f, Args &&... args) noexcept {</div><div class=3D""> &=
nbsp; static_assert(std::is_class<<wbr class=3D"">FuncObject>::value,=
"");</div><div class=3D""> return std::bind(std::forward<<=
wbr class=3D"">FuncObject>(f), std::forward<Args>(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 <class T=
1, class T2 =3D T1></div><div class=3D"">constexpr auto less_ib(T1 const=
& t1, T2 const & t2) noexcept {</div><div class=3D""> =
return implicitely_bindable(less<>(), 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 <cmath> 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""> template <class=
T></div><div class=3D""> auto operator()(T && arg)=
const { return std::sqrt(std::forward<Arg>(<wbr class=3D"">arg)); }<=
/div><div class=3D"">};</div><div class=3D""><br class=3D""></div><div clas=
s=3D"">template <class T></div><div class=3D"">constexpr auto sqrt_ib=
(T && arg) noexcept { return implicitely_bindable(sqrt_<wbr class=
=3D"">func(), std::forward<Arg>(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""> //With lambda</div><div class=3D""> &nbs=
p;partition(begin(vec), end(vec), [](int v) { return v < 5; });</div><di=
v class=3D""> //With this proposal</div><div class=3D""> =
partition(begin(vec), end(vec), less_ib(_1, 5));</div><div class=3D""=
><br class=3D""></div><div class=3D""> //With lambda</div><div=
class=3D""><div class=3D""> transform(begin(vec), end(vec), b=
egin(out), [](double v) { return sqrt(v) + pow(v, 5); });</div><div class=
=3D""> //With this proposal (overloaded placeholders + implici=
tely bindable</div><div class=3D""> 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"><implicit_bindable=
_objects.cpp></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" 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<class T></div><div><span style=3D"white-spa=
ce:pre"> </span>auto operator()(T&& t) { return sqrt(forward<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> </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 < 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> </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, &sqrt<int>); //But this is a func pointer, not good! =
;</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" 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--
.