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                       ]