473,748 Members | 9,416 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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_si ze);
y.resize(max_si ze);
vect_.resize(ma x_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_.begi n(), ioo.vect_.end() , ostream_iterato r<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****@c onnect.to
http://mathforum.org/library/view/10978.html
news://news.gmane.org/gmane.comp.lang.c++.perfometer
=============== =============== =======


Jul 19 '05 #1
5 4677
<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<iostre am>
#include<algori thm>
#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():car ry(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()(cons t 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%b ase);while((a/=base)!=0);}

//operator +=, adds two LongInts and swaps the vectors
LongInt&operato r+=(LongInt&a)
{
v.resize(a.v.si ze());
CarryChar carrychar;
transform(v.beg in(),v.end(),a. v.begin(),v.beg in(),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&operato r<<(ostream&a,c onst LongInt&b)
{
copy(b.v.rbegin (),b.v.rend(),o stream_iterator <int>(a));
return a;
}

//main. Note how LongInt(0) is forced cout<< to produce 0,1,1,2,3,5,8,1 3...
int main()
{
LongInt a(0);
LongInt b(1);
cout<<a<<'\n';
for(int c=0;c<20;c++)co ut<<(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&operato r+=(LongInt&a)
{
v.resize(a.v.si ze());
CarryChar carrychar;
transform(v.beg in(),v.end(),a. v.begin(),v.beg in(),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****@c onnect.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.nam e
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>::it erator,
vector<int>::it erator,
vector<int>::it erator,
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*****@metrow erks.com> wrote in message news:hi******** *************** ****@syrcnyrdrs-02-ge0.nyroc.rr.co m...
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****@c onnect.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
2166
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 instantiate in the following ways PQueue<int> pq1; PQueue<int, Functor> pq2; // where Functor is a name of user-defined class I also added another constructor to accept a function pointer so that
1
1418
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 populate_bounds(&bounds); // all bounds.first <= bounds.second
2
2398
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 precision class (I know such libraries already exist) and I wrote the following piece of code : template <typename T> class plus_with_carry { public: plus_with_carry(void) : carry(false) {};
8
1982
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. functor<bool (long, long)> myFunctor; myFunctor = AFunctionOfThatPrototype; To get that much is elementary because the template can just store a (bool)(long,long) as a member variable in functor<T>. Here is the problem:
4
2904
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)> myFunctor = SampleFunction; string result = myFunctor(7, true); Works great thanks to the help from this group. Here's the guts so far for two-arity:
2
3910
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 an object and a unary method creates a unary_function-defived functor bound to that object and method. Code is below. // Method-to-functor adapter template<class TClass, typename TArg, typename TRet>
12
1967
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 { ... double evaluate(){
2
2516
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 below). Or, rather, it works fine as long as my member functor is const. The problem comes when I wish to use it for a *non*-const functor (see listing 2 below): *** Start listing 1 *************************************************** // test1.cpp
4
4864
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 _Predicate::argument_type argument_type; typedef typename _Predicate::return_type return_type; _Predicate pred_;
5
2532
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 a multi-threaded application, naturally I want the call back functor to be created on a per thread basis. Suppose my thread is so defined template <typename servlet_type>
0
8984
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8823
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9363
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9312
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9238
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6793
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4864
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3300
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2206
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.