just use this.
this is probably the most bizarre thing i've read in a while. it works,
huh?:
for (int i = 0; i < 10; ++i)
STUFF
vs.
for (int i = 0; i < 10; ++i)
doStuff();
"kiss" that.
But macros can be difficult to follow too. This example is very simplistic,
but for example logging macros and testing macros can be difficult to read
and maintain. But I do like how the compiler has an opportunity to remove
large parts of the code by switching a compiler flag.
inline functions were largely created for the explicit purpose of
eliminating macros.
#define DO_STUFF doThis(); doThat();
and
inline void doStuff()
{
doThis();
doThat();
}
should produce *exactly* the same output instructions under most
circumstances (of course, the compiler is free to ignore the inline
suggestion, and most do under certain circumstances). that's what they
were created for.
you want the power to be able to effectively turn that function off in
certain compile-time conditions (eg, removing it in a release build)? no
problem:
inline void doStuff()
{
#ifdef DEBUG
doThis();
doThat();
#endif
}
that will be a no-op on any compiler worth its salt if DEBUG is not
defined. need a parameter? piece of cake:
inline void doStuff(int param)
{
doThis(param);
doThat(param);
}
just try that with macros:
#define STUFF(x) doThis(x); doThat(x);
STUFF(++i); // uh oh!
also, what if you need a dummy/default variable for the call?
inline void doStuff()
{
int temp;
doThis(&temp);
doThat(temp);
}
works with the macro? well...
#define STUFF int temp; doThis(&temp); doThat(temp);
void foo()
{
STUFF
// some code
STUFF // bang!
}
incidently:
class MyUtils
{
public:
static void doStuff() // implicit inline
{
doThis();
doThat();
}
};
would work, and may be valid in certain instances. i was involved in a
lengthy debate about the merit of such a design pattern a while back. no
real conclusion was reached, but i believe that 99% of the time this
method is unnecessary and convoluted, and it's even occasionally
dangerous. however, you're the programmer, do what you will.
I'm just interested in learning different techniques of performing the same
task, just to improve my toolbox
bien sur. macros do have their place. and all the problems i presented
above with the macros *could* be fixed. but seriously, how can you think
inline funcitons are "too complicated" when you have to take so much
care with them? use them only when direct text substitution is desired.
_never_ use the preprocessor in place of c++ language constructs.
as far as i can think right now, inline functions (and inlined static
public class members of course) are about the only way to do what you
want. macros *can* do it, if you're careful, but are most definitely not
the best way to do it.
of course, regular non-inlined functions could do the same thing,
although possibly with additional overhead. i say this because often in
the rush to optimize, rationality goes out the window. after all, you're
already paying for the overhead *twice* with doThis() and doThat(). if
either function takes any practical length of time, the overhead in
calling doStuff() is pretty much marginalized.
also, an optimizing compiler would probably realize that setting up the
stack frame in doStuff is unnecessary, so the entire cost of the
function (not counting doThis() and doThat(), of course) comes down to
two jump instructions. that's two jump instructions, likely a call and a
ret on x86's, and possibly even less in special cases. is that too
expensive?
and that's assuming the compiler doesn't inline it anyway. stay away
from macro crap. trust your compiler... but use your profiler.
mark