• Advertisement
Sign in to follow this  

#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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
Did you consider using std::for_each or BOOST_FOREACH instead?

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Did 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 <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


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

Share this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Mizipzor
std::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 this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by Mizipzor
std::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); }
// }

// new
struct 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); }

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement