Topic: Passing functor-parameters in for_each() and transform()


Author: alexvn@bigfoot.com ("Alex Vinokur")
Date: Fri, 7 Nov 2003 06:38:26 +0000 (UTC)
Raw View
Functor-parameters in the for_each() and transform() algorithms are passed by value.

Might it make sense to have also algorithms for_each2() and transform2()
  which pass Functor-parameters by non-const reference?


Here is some program which demonstrates probable necessity
  in such forms of for_each() and transform().


====== C++ code : File foo.cpp : BEGIN ======

#include <vector>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;

#define MAX_VALUE(x,y)  ((x) > (y) ? (x) : (y))

class Foo
{
friend ostream& operator<< (ostream& os, const Foo& ioo);

  private :
    int         sum_;
    vector<int> vect_;

  public :
    Foo (vector<int> x, vector<int> y) : sum_ (0)
    {
      const unsigned max_size = MAX_VALUE (x.size (), y.size ());

      x.resize(max_size);
      y.resize(max_size);
      vect_.resize(max_size);

      // ------ transform ------
      transform (x.begin(), x.end(), y.begin(), vect_.begin(), *this);
      cout << "sum_ = " << sum_ << "  (after transform)" << endl;
      cout << (*this) << endl;
      // It seems that it is impossible to change sum_ through transform because
      // 1) Foo copy constructor is called;
      // 2) transform() doesn't return Functor-object
      // -----------------------

      // ------ for-each -------
      for_each (vect_.begin(), vect_.end(), *this);
      cout << "sum_ = " << sum_ << "  (after for_each-1)" << endl;
      cout << (*this) << endl;
      // sum_ is not changed because
      // 1) Foo copy constructor is called;
      // 2) Foo value returned is not used
      // -----------------------

      // ------ for-each -------
      *this = for_each (vect_.begin(), vect_.end(), *this);
      cout << "sum_ = " << sum_ << "  (after for_each-2)" << endl;
      cout << (*this) << endl;
      // sum_ is changed because
      // * Foo value returned is used to change *this
      // -----------------------

      // ------ for-each -------
      *this = for_each (vect_.begin(), vect_.end(), *this);
      cout << "sum_ = " << sum_ << "  (after for_each-3)" << endl;
      cout << (*this) << endl;
      // sum_ is changed because
      // * Foo value returned is used to change *this
      // -----------------------

    }

    int operator() (int n1, int n2)
    {
      sum_ += n1;
      sum_ += n2;
      return (n1 + n2);
    }

    void operator() (int n)
    {
      sum_ += n;
    }


};


ostream& operator<< (ostream& os, const Foo& ioo)
{
ostringstream oss;
  oss << "{ vect_ = ";
  copy (ioo.vect_.begin(), ioo.vect_.end(), ostream_iterator<int> (oss, " "));
  return os << oss.str() << "}" << endl;
}


int main ()
{
const int a1[] = {1, 2, 3, 4, 5};
const int a2[] = {10, 20, 30, 40, 50, 60, 70};
const vector<int> v1 (a1, a1 + sizeof(a1)/sizeof(*a1));
const vector<int> v2 (a2, a2 + sizeof(a2)/sizeof(*a2));

  { Foo (v1, v2);}

  return 0;
}

====== C++ code : File foo.cpp : END ========



====== Compilation & Run : BEGIN ======

$ g++ -v
[---omitted---]
gcc version 3.3.1 (cygming special)

$ g++ foo.cpp

$ a
sum_ = 0  (after transform)       // sum_ not changed
{ vect_ = 11 22 33 44 55 60 70 }

sum_ = 0  (after for_each-1)      // sum_ not changed
{ vect_ = 11 22 33 44 55 60 70 }

sum_ = 295  (after for_each-2)    // sum_ changed
{ vect_ = 11 22 33 44 55 60 70 }

sum_ = 590  (after for_each-3)    // sum_ changed
{ vect_ = 11 22 33 44 55 60 70 }

====== Compilation & Run : END ========

--
 =====================================
   Alex Vinokur
     mailto:alexvn@connect.to
     http://mathforum.org/library/view/10978.html
     news://news.gmane.org/gmane.comp.lang.c++.perfometer
   =====================================




---
[ 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: andreytarasevich@hotmail.com (Andrey Tarasevich)
Date: Sun, 9 Nov 2003 19:01:20 +0000 (UTC)
Raw View
Alex Vinokur wrote:
> ...
> Functor-parameters in the for_each() and transform() algorithms are passed by value.
>
> Might it make sense to have also algorithms for_each2() and transform2()
>   which pass Functor-parameters by non-const reference?
> ...

You can work around this limitation by using explicit specification of
template arguments, although everyone will probably agree that this
method cannot be referred to as "elegant"

...
  transform<vector<int>::iterator,
            vector<int>::iterator,
            vector<int>::iterator,
            Foo&>(x.begin(), x.end(), y.begin(), vect_.begin(), *this);
...
  for_each<vector<int>::iterator,
           Foo&>(vect_.begin(), vect_.end(), *this);
...

--
Best regards,
Andrey Tarasevich

---
[ 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: drpizza@anti-flash.co.uk ("DrPizza")
Date: Mon, 10 Nov 2003 10:38:08 +0000 (UTC)
Raw View
""Alex Vinokur"" <alexvn@bigfoot.com> wrote in message
news:bo8jui$19aso0$1@ID-79865.news.uni-berlin.de...
>
> Functor-parameters in the for_each() and transform() algorithms are passed
by value.
>
> Might it make sense to have also algorithms for_each2() and transform2()
>   which pass Functor-parameters by non-const reference?
>
>
> Here is some program which demonstrates probable necessity
>   in such forms of for_each() and transform().

It is right and proper that transform() doesn't take it by reference; that's
not what transform is for.

for_each appears to have no need to take it by reference because it returns a
copy.


--
Now Playing:  Mark'Oh - Fade To Grey (Original Radio Verison)


char a[99999],*p=a;main(c,V)char**V;{char*v=c>0?1[V]:V;if(c)for(;(c=*v)&&93^
c;p+=!(62^c)-!(60^c),*p+=!(43^c)-!(45^c),44^c||read(0,p,1),46^c||putchar(*p)
,91^c||(v=*p?main(-1,v+1),v-1:main(0,v)),++v);else for(;c+=!(91^*v)-!(93^*v)
;++v);return v;} /* drpizza@battleaxe.net    brainf*** program as argv[1] */


---
[ 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                       ]