[Dev] STL for_each underwhelms me

M. Mueller (bhu5nji) dev@trilug.org
Mon, 11 Feb 2002 15:07:12 -0500


> What specifically do you want for_each to do for you?

I have a map of entries where the key is a transaction ID and the entries 
describe a socket connection and related query, timestamp, state, response, 
etc.  For each entry, do a non-blocking read on stream socket, check to see 
that the request is fully formed and if so, change the state to re-form the 
query and forward.  This is part of a proxy server.

I tried : for_each(xmap.begin(), xmap,end(), clientRead);

clientRead is a member of proxy server class object.

Heeding the compiler (gcc 3.0) error I changed to: 
or_each(xmap.begin(), xmap,end(), &classname::clientRead);

Still get "out of scope" error.

for_each likes functions, not methods, as far as I can tell.  I assume the 
compiler needs to be "tricked" into thinking the method is a function.

If that analysis is correct, then I have to wonder about writing "tricky" 
code.

>
> This page is a good synopsis of for_each which shows a stateful
> functor.
>   http://www.sgi.com/tech/stl/for_each.html

This example seems like it uses operator overloading to make for_each do 
something more complicated that it would otherwise be capable of.  This does 
not seem like a use of operator overloading "to allow a programmer to provide 
a more conventional and convenient notation for manipulating class objects".  
(Quote from 7.1 C++ by Stroustrup.)

The example seems to be a template.  So now it has the advantage of being 
generic.  On the other hand, the number of test cases needed has just gone up 
dramatically.  

--------------------------------------------------------------------------

template<class T> struct print : public unary_function<T, void>
{
  print(ostream& out) : os(out), count(0) {}
  void operator() (T x) { os << x << ' '; ++count; }
  ostream& os;
  int count;
};

int main()
{
  int A[] = {1, 4, 2, 8, 5, 7};
  const int N = sizeof(A) / sizeof(int);

  print<int> P = for_each(A, A + N, print<int>(cout));

// I find "print<int>" and "print<int>(cout)" difficult to read - I have no
// familiarity with "Z" and "Z(func)" being meaningful is other contexts.   
// When the '+' is overloaded for strings, I find string1 + string2 easy to 
// understand.

  cout << endl << P.count << " objects printed." << endl;
}

---------------------------------------------------------------------------
An alternative that seems quite a bit easier to understand.

int main()
{
  int A[] = {1, 4, 2, 8, 5, 7};
  const int N = sizeof(A) / sizeof(int);

  int count=0;
  for (int i=0; i < N; i++) 
	{
	cout << A[i] << ' ';
	count++;
	}
  cout << endl << count << " objects printed" << endl;
}


I can't help feeling that the operator overloading used with for_each is a 
sophisticated way to get more stuff into a unary function.  I have no problem 
with for_each as long as simple unary functions are used.  Introducing 
operator overloading to squeeze more functionality into the limits of the 
unary function results in complicated code.  Maybe the complicated code is 
more versatile, but that means there are more test cases to perform.  
Operator overloading with for_each also yields terse code, which is 
esthetically pleasing.   The esthetics are lost on myself after I've gazed at 
the well-crafted code for an hour and I am still not sure of what it does.

 I'm going to keep studying this operator overloading subject.  I havn't used 
it much.

Mike M.