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 ]