Topic: Why function objects in <functional> doesn't use member templates?
Author: tslettebo@hotmail.com (Terje Sletteb?)
Date: Thu, 15 Jul 2004 22:37:23 +0000 (UTC) Raw View
AlbertoBarbati@libero.it (Alberto Barbati) wrote in message news:<OfHGc.39768$c_1.1252070@twister1.libero.it>...
Just to add to my previous post, this line:
std::transform(begin(array),end(array),begin(array),bind1st(plus(),10);
// Add 10 to each element
can of course be written as:
std::transform(begin(array),end(array),begin(array),_1+10); // Add
10 to each element
given that I used Boost.Lambda (BLL) elsewhere in the example. :)
However, for functors, such as plus, when using BLL, you need to
specify the return type explicitly:
std::transform(begin(array),end(array),begin(array),bind<int>(plus(),_1,10));
// Add 10 to each element
Maybe it could be an idea to let Boost.Lambda use result_of?
Regards,
Terje
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: tslettebo@hotmail.com (Terje Sletteb?)
Date: Fri, 16 Jul 2004 04:55:12 +0000 (UTC) Raw View
AlbertoBarbati@libero.it (Alberto Barbati) wrote in message news:<OfHGc.39768$c_1.1252070@twister1.libero.it>...
> Ganesh wrote:
> >
> > struct negate {
> > template <typename T> T operator() (const T &t) { return (-t);
> > }
> > };
> >
>
> In order to play nicely with binders, a functor need to be "adaptable"
> according to old SGI terminology. In practice, this means that it has to
> derive from std::unary_function<Arg, Result>. If you use member
> templates, you simply cannot have that.
Hm, using the result_of proposal
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html),
you can actually create functors that don't need to be adaptable.
The following is a complete example (using the latest version of the
Boost CVS), which compiles and runs on g++ 3.2:
--- Start code ---
#include <iostream>
#include <algorithm>
#include <boost/collection_traits/begin.hpp>
#include <boost/collection_traits/end.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/utility/result_of.hpp>
using namespace boost;
using namespace boost::lambda;
// Teach it about the return type of the plus functor, using
// boost::result_of. For compilers supporting typeof, this
// isn't necessary, as result_of should then be able to deduce
// the type, itself.
struct plus;
namespace boost {
template<>
struct result_of<plus(int,int)> { typedef int type; }; // int+int =
int
} // namespace boost
// New version of plus
struct plus
{
template<class P1,class P2>
typename result_of<plus(P1,P2)>::type
operator()(const P1 &p1,const P2 &p2) const { return p1+p2; }
};
// New version of bind1st
template<class F,class P1>
struct binder1st
{
binder1st(const F &f,const P1 &p1) : f(f),p1(p1) {}
template<class P2>
typename result_of<F(P1,P2)>::type
operator()(const P2 &p2) const { return f(p1,p2); }
private:
F f;
P1 p1;
};
template<class F,class P1>
binder1st<F,P1> bind1st(const F &f,const P1 &p1) { return
binder1st<F,P1>(f,p1); }
int main()
{
int array[10];
int count=0;
std::generate(begin(array),end(array),++var(count)); // Fill array
with 1..10
std::transform(begin(array),end(array),begin(array),bind1st(plus(),10));
// Add 10 to each element
std::for_each(begin(array),end(array),std::cout << _1 << ' '); //
Print the array elements
}
--- End code ---
Output: "11 12 13 14 15 16 17 18 19 20"
Using typeof, the specialisation of result_of wouldn't be necessary.
However, trying to use g++'s typeof didn't work in this case, it
crashed, so I used an explicit specialisation, instead.
Regards,
Terje
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Wed, 7 Jul 2004 00:26:33 +0000 (UTC) Raw View
Ganesh wrote:
>
> struct negate {
> template <typename T> T operator() (const T &t) { return (-t);
> }
> };
>
In order to play nicely with binders, a functor need to be "adaptable"
according to old SGI terminology. In practice, this means that it has to
derive from std::unary_function<Arg, Result>. If you use member
templates, you simply cannot have that.
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: sgganesh@gmail.com (Ganesh)
Date: Tue, 6 Jul 2004 16:36:23 +0000 (UTC) Raw View
The function objects (20.3) in <functional> like greater, negate are
templates. Hence we need to pass <T> explicitly while using them in
algorithms, as in the example 20.3.3:
[Example: If a C ++ program wants to have a by-element addition of two
vectors a and b containing double and put the result into a, it can
do:
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
end example]
Isn't that the use of function objects would have been simpler if
operator () were written as member templates?
For example, the call in previous example would look like:
transform(a.begin(), a.end(), a.begin(), negate());
Which is more convenient (atleast for me).
I don't see any significant technical difficulties for doing the same
(correct me if I am overlooking something obvious). For example, a
trivial implementation using member templates might be written as:
struct negate {
template <typename T> T operator() (const T &t) { return (-t);
}
};
-Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]