472,954 Members | 1,692 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,954 software developers and data experts.

Passing the Functor-parameters in for_each() and transform()


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:al****@connect.to
http://mathforum.org/library/view/10978.html
news://news.gmane.org/gmane.comp.lang.c++.perfometer
=====================================


Jul 19 '05 #1
5 4621
<Alex Vinokur>
Might it make sense to have also algorithms for_each2() and transform2()
which pass Functor-parameters by non-const reference?

</>

Hi Alex, I seem to have run in the same problem as you did. Here is a little
program to show my point:

#include<iostream>
#include<algorithm>
#include<vector>

//global data base, holds the number base
const static char base=10;

//global data carry, needed after all
static char carry=0;

//struct CarryChar, functor for use in STL algorithm transform()
//Note how ::carry is used to address the global carry. Remove
//the :: and the local CarryChar.carry is used instead. But you
//cannot get the value AFTER the transform() algorithm, just when
//you need it most
struct CarryChar
{

//data member carry, holds the carry after addition
char carry;

//constructor
CarryChar():carry(0){::carry=0;}

//operator bool, Used once to see if there is a push_back needed
operator bool(){return::carry;}

//operator(), return sum of two characters, stores carry in carry
char operator()(const char a,const char b)
{
char c=a+b+::carry;
::carry=0;
if(c>=base){c-=base;::carry=1;}
return c;
}};

//struct LongInt, holds an expanding vector<char> and uses CarryChar
struct LongInt
{

// //data member carrychar. Functor

//data member v, vector of characters
vector<char>v;

//constructor
LongInt(char a){do v.push_back(a%base);while((a/=base)!=0);}

//operator +=, adds two LongInts and swaps the vectors
LongInt&operator+=(LongInt&a)
{
v.resize(a.v.size());
CarryChar carrychar;
transform(v.begin(),v.end(),a.v.begin(),v.begin(), carrychar);
//Here is where you need the value of carrychar.carry but it
//is outside your reach. You must use the global ::carry to
//achieve the desired result.
if(carrychar)v.push_back(1);
v.swap(a.v);
return*this;
}};

//operator<< outputs a LongInt object (to the screen)
ostream&operator<<(ostream&a,const LongInt&b)
{
copy(b.v.rbegin(),b.v.rend(),ostream_iterator<int> (a));
return a;
}

//main. Note how LongInt(0) is forced cout<< to produce 0,1,1,2,3,5,8,13...
int main()
{
LongInt a(0);
LongInt b(1);
cout<<a<<'\n';
for(int c=0;c<20;c++)cout<<(a+=b)<<'\n';
return 0;
}

Jul 19 '05 #2

"Agent Mulder" <mb*******************@home.nl> wrote in message news:bn**********@news2.tilbu1.nb.home.nl...
LongInt&operator+=(LongInt&a)
{
v.resize(a.v.size());
CarryChar carrychar;
transform(v.begin(),v.end(),a.v.begin(),v.begin(), carrychar);
//Here is where you need the value of carrychar.carry but it
//is outside your reach. You must use the global ::carry to
//achieve the desired result.
Exactly. This situation caused me to ask my question.
if(carrychar)v.push_back(1);
v.swap(a.v);
return*this;
}};

[snip]

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


Jul 19 '05 #3
"Alex Vinokur" <al****@bigfoot.com> writes:
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().
<snip>
class Foo
{
friend ostream& operator<< (ostream& os, const Foo& ioo);

private :
int sum_;
<snip>
int operator() (int n1, int n2)
{
sum_ += n1;
sum_ += n2;
return (n1 + n2);
}

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


Hm. Rather than suggest dangerous versions of for_each() and
transform(), why not rather declare sum_ as mutable, allowing it
to be changed even when the Foo object was declared as const?

--
Micah J. Cowan
mi***@cowan.name
Jul 19 '05 #4
In article <bn*************@ID-79865.news.uni-berlin.de>,
"Alex Vinokur" <al****@bigfoot.com> 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?
Another solution is to explictly specify the template arguments to the
algorithms. In this way you can transform the call-by-value into a
call-by-reference. For example:

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


....

sum_ = 295 (after transform)
{ vect_ = 11 22 33 44 55 60 70 }

Unfortunately the above code isn't portable. Metrowerks CodeWarrior is
the only product which has publicly stated this code is guaranteed to
work (as a conforming extension to the standard).

A defect report was submitted years ago on this issue:

http://anubis.dkuug.dk/jtc1/sc22/wg2...active.html#92

The consensus of the lwg is to make code such as that shown above
illegal. The state of a stateful function object does not have to be
respected. Although issue 92 is not yet set in stone, just last week
the issue was moved one step closer to being official. It will become
official (DR status) this October unless someone not only makes a lot of
noise, but is also successful at convincing others that this issue is
not being settled correctly.

Years ago I argued for the state of stateful function objects to be
respected. But I was unsuccessful in convincing others to my viewpoint.
So I settled for just allowing my own customers this behavior.

If you feel that you would like to see this behavior standardized, you
will need to go to comp.std.c++ and speak long and eloquently. You
should reference issue 92 directly, and you might also reference an
excellent article written by Klaus Kreft and Angelika Langer.

http://www.cuj.com/documents/s=8000/cujcexp1812langer/

Otherwise you can build the extra level of indirection into the functor
you pass. For example you could create a FooRef class that takes a Foo
and stores a pointer to it.

-Howard
Jul 19 '05 #5

"Howard Hinnant" <hi*****@metrowerks.com> wrote in message news:hi***************************@syrcnyrdrs-02-ge0.nyroc.rr.com...
In article <bn*************@ID-79865.news.uni-berlin.de>,
"Alex Vinokur" <al****@bigfoot.com> 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?

[snip]
If you feel that you would like to see this behavior standardized, you
will need to go to comp.std.c++ and speak long and eloquently.


[snip]

I have sent my original posting to comp.std.c++ .
--
=====================================
Alex Vinokur
mailto:al****@connect.to
http://mathforum.org/library/view/10978.html
news://news.gmane.org/gmane.comp.lang.c++.perfometer
=====================================


Jul 19 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: CoolPint | last post by:
I have implemented a generic priority queue below and tested it works fine, but I have one small problem I cannot understand. I have type parameter F which determines the priority so that users can...
1
by: Steven T. Hatton | last post by:
If I do: typedef vector<size_t> v_T; pair<v_T, v_T> b_T; b_T bounds(v_T(n), v_T(n)); // if that doesn't work // std::make_pair(v_T(n), v_T(n)); b_T diff_v(n); void...
2
by: Charles-Antoine Giuliani | last post by:
Is it possible to overload multiple times operator() ? For example for using one or two arguments ? My visual c++ does not seem to like it : I was trying to implement an arbitrary integer...
8
by: daniel.w.gelder | last post by:
Hello, I have been trying to write a functor template for a week now and I'm just having tons of trouble because I don't understand an issue that I guess is pretty basic to this task. ...
4
by: daniel.w.gelder | last post by:
I wrote a template class that takes a function prototype and lets you store and call a C-level function, like this: inline string SampleFunction(int, bool) {..} functor<string (int, bool)>...
2
by: zzorozz | last post by:
I often find that I need to pass a non-static method as a call-back instead of a functor or a function. The problem with that is the implicit 'this' parameter. So I created an adaptor that given...
12
by: aaragon | last post by:
Hi everyone, I'm trying to provide some external functionality to a class through a functor object defined by the user. The concept is as follows: template <class Functor> class ClassA {...
2
by: Lionel B | last post by:
I have a function which takes a functor argument. I which to call it for a functor which is actually a class member; this works fine, using the mem_fun_ref and bind1st functions (see listing 1...
4
by: Lycan. Mao.. | last post by:
Hello, I'm trying to write a function adapter object, but it fails with the above information. Can you help me. template <typename _Predicate> struct Unary_negate { typedef typename...
5
by: Fei Liu | last post by:
Hello, I have a situation where I need to design a library for multi-thread application, each thread does some work in a client supplied std::ptr_fun(free_function) or a functor. Now since it's...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.