Jump to content
  • Advertisement
Sign in to follow this  
Mizipzor

#define macros

This topic is 4006 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
#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
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!