# #define macros

This topic is 3769 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi. I have a loop I use in many, many places in my code. Usually, I dont like define macros, so I have never used them, but this is one time I really think they could clean up the code. The loop calls a function on every class instance in a std::vector. It looks like this:
for (	std::vector<Box*>::iterator i = m_boxList.begin();
i != m_boxList.end(); i++ )
{
if ( *i )
{
(*i)->update();
}
}
}

The only part that changes between the places where I run the loop is the "update();". I want to define a macro that does this loop but lets me change the function. Like:
RUN_ON_ALL_BOXES->update();


##### Share on other sites
Did you consider using std::for_each or BOOST_FOREACH instead?

##### Share on other sites
Nope... I would have if I know about them.

/me goes to check

##### Share on other sites
#defines are evil in this case. You can't step through them in the debugger. If the thought for doing the for_each / BOOST_FOREACH is still too much, consider using a templated function:
template <class T>void update_foreach (T &list){  for (T::iterator i = list.begin (), end = list.end () ; i != end ; ++i)  {    if (*i)    {      (*i)->update();    }  }}void func (){  std::vector<Box*> list;  update_foreach (list);}

You could probably make the called function a template argument as well using pointer to member or some template trickery of some type.

Skizz

##### Share on other sites
std::for_each worked... a bit. Im not able to send arguments to the function, and I cant perform the if(*i) check. I havent checked into boost as I dont want to get that whole dependency just to shave of a couple of lines.

##### Share on other sites
Quote:
 Original post by SiCraneDid you consider using std::for_each or BOOST_FOREACH instead?

std::for_each worked... a bit. Im not able to send arguments to the function, and I cant perform the if(*i) check. I havent checked into boost as I dont want to get that whole dependency just to shave of a couple of lines.

Quote:
 Original post by Skizz#defines are evil in this case. You can't step through them in the debugger. If the thought for doing the for_each / BOOST_FOREACH is still too much, consider using a templated function:template void update_foreach (T &list){ for (T::iterator i = list.begin (), end = list.end () ; i != end ; ++i) { if (*i) { (*i)->update(); } }}void func (){ std::vector list; update_foreach (list);}You could probably make the called function a template argument as well using pointer to member or some template trickery of some type.Skizz

That looks real neat, now I just need to figure out a way to specify which function that is to be called.

##### Share on other sites
Quote:
 That looks real neat, now I just need to figure out a way to specify which function that is to be called.

Something like this:

template <class T, void(T::*func)(void)>void update_foreach (T &list,func f){  for (T::iterator i = list.begin (), end = list.end () ; i != end ; ++i)  {    if (*i)    {      (*i)->*f();    }  }}void func (){  std::vector<Box*> list;  update_foreach (list,&Box::update);}

Actually the code above is incorrect as T is a container not the type inside of the container. I suppose if I really needed this then the code would use a functor library as well.

[Edited by - dmail on November 1, 2007 12:02:39 PM]

##### Share on other sites
Quote:
 Original post by Mizipzorstd::for_each worked... a bit. Im not able to send arguments to the function, and I cant perform the if(*i) check.

That's what boost::bind and boost::lambda will do for you. The latter is... well... it's quite a library. boost::bind is too, I guess, but boost::bind doesn't try to make C++ into C++++.

Personally, I don't use std::for_each, or BOOST_FOREACH, or boost::lambda. I just write out the damn loop. It's verbose, yeah, but that's what VisualAssist is for. This is one of these areas where C++ is imperfect, and the solution to its imperfections is worse than the imperfections themselves.

##### Share on other sites
Quote:
Original post by Sneftel
Quote:
 Original post by Mizipzorstd::for_each worked... a bit. Im not able to send arguments to the function, and I cant perform the if(*i) check.

That's what boost::bind and boost::lambda will do for you. The latter is... well... it's quite a library. boost::bind is too, I guess, but boost::bind doesn't try to make C++ into C++++.

You could try just redoing the functions as functors:

// old// void Box::frobnicate(int x);// myBox.frobnicate(42);// for (std::vector<Box*>::iterator i = m_boxList.begin(); //      i != m_boxList.end(); i++ ) {//   if ( *i ) { (*i)->frobnicate(23); }// }// newstruct BoxFrobnicator {  int x;  BoxFrobnicator(int x) : x(x) {}  void operator()(Box* b) {    // if (b) { b->frobnicate(x); } or move the code here, depending  }};// If you have to use the functor for a single object, it's not that bad:BoxFrobnicator(42)(&myBox);// And it works great with std::for_each:std::for_each(m_boxList.begin(), m_boxList.end(), BoxFrobnicator(23); }