Alternatives to #define?

  • Thread starter Carl Ribbegaardh
  • Start date
C

Carl Ribbegaardh

What other c++ constructs can I use instead of #define for executing a
couple of functions?
Example:

#define DO_STUFF doThis(); doThat();

I'd guess that I can either use a template function, an inlined function or
an inlined static method.

//1
namespace MyUtils
{
template<>
void doStuff()
{
doThis();
doThat();
}
}

//2
namespace MyUtils
{
inline void doStuff()
{
doThis();
doThat();
}
}

//3
class MyUtils
{
public:
static inline void doStuff() const
{
doThis();
doThat();
}
}

I *believe* that the template version always is inlined, and that the other
2 versions is probably inlined.
Are theese approaches correct?
Which should be preferred?
Are there any other better way?

/Carl
 
J

John Harrison

Carl Ribbegaardh said:
What other c++ constructs can I use instead of #define for executing a
couple of functions?
Example:

#define DO_STUFF doThis(); doThat();

I'd guess that I can either use a template function, an inlined function or
an inlined static method.

//1
namespace MyUtils
{
template<>
void doStuff()
{
doThis();
doThat();
}
}

//2
namespace MyUtils
{
inline void doStuff()
{
doThis();
doThat();
}
}

//3
class MyUtils
{
public:
static inline void doStuff() const
{
doThis();
doThat();
}
}

I *believe* that the template version always is inlined, and that the other
2 versions is probably inlined.

No that is not true. I guess you are thinking of the exception that
templates have from the normal one definition rules for functions and
classes. But that's an entirely seperate issue.
Are theese approaches correct?

They are all correct.
Which should be preferred?

The second
Are there any other better way?

What's wrong with the second method? Why is it even an issue?

john
 
C

Carl Ribbegaardh

John Harrison said:
No that is not true. I guess you are thinking of the exception that
templates have from the normal one definition rules for functions and
classes. But that's an entirely seperate issue.


They are all correct.


The second


What's wrong with the second method? Why is it even an issue?

The issue is that I dont *know*.
I'm currently just guessing/believing. :)

So the 1st version isn't inlined? Why I thought it would be, is that I've
read lines like "templates are inlined by definition" but I might have
interpreted/read/remembered it wrong. Any elaboration on why or why not
would be much appreciated.

Thanks! :)
 
J

John Harrison

Carl Ribbegaardh said:
The issue is that I dont *know*.
I'm currently just guessing/believing. :)

Well method two is using one function to call two others. It's perfectly
common programming to solve a common problem. The other methods introduce
extra language features to create a more complex solution to a simple
problem.
So the 1st version isn't inlined? Why I thought it would be, is that I've
read lines like "templates are inlined by definition" but I might have
interpreted/read/remembered it wrong. Any elaboration on why or why not
would be much appreciated.

If you read that it was wrong. As I said I think you might have read that
template functions usually go in header files which makes them a little like
inline functions (which also usually go in header files), but this is for
technical issues to do with how templates are compiled. It has nothing to do
with whether the template function call itself is inlined.

john
 
R

Rolf Magnus

Carl said:
What other c++ constructs can I use instead of #define for executing a
couple of functions?
Example:

#define DO_STUFF doThis(); doThat();

I'd guess that I can either use a template function, an inlined
function or an inlined static method.

//1
namespace MyUtils
{
template<>
void doStuff()
{
doThis();
doThat();
}
}

What's that template good for? Actually, I don't think this is valid,
since it doesn't have any template parameters.
//2
namespace MyUtils
{
inline void doStuff()
{
doThis();
doThat();
}
}

//3
class MyUtils
{
public:
static inline void doStuff() const
{
doThis();
doThat();
}
}

That's incorrect. You cannot make a static member function const, as
that wouldn't make sense. Making a member function const means that it
can be called on const objects, but a static member function isn't
called on any object at all.
I *believe* that the template version always is inlined, and that the
other 2 versions is probably inlined.

No. The template might be inlined or it might not, just like any other
function.
 
R

Robbie Hatley

Carl Ribbegaardh said:
#define DO_STUFF doThis(); doThat();

I actually like that. Simple, direct, ALWAYS inlined.
namespace MyUtils
{
template<>
void doStuff()
{
doThis();
doThat();
}
}

I tried compiling that, got "Error: non-template
used as template."
namespace MyUtils
{
inline void doStuff()
{
doThis();
doThat();
}
}

That works, and most C++ purists would recommend it,
but I think it sucks. Too complicated. KISS.
Use the macro instead.
class MyUtils
{
public:
static inline void doStuff() const
{
doThis();
doThat();
}
}

"error: static member function `static void MyUtils::doStuff()'
cannot have `const' method qualifier"

Why stir up trouble with complicated stuff when trying to
solve a simple problem? Usually the simpliest workable
solution is the best. Sometimes a macro is the thing that fits
that bill.


--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant
 
C

Carl Ribbegaardh

Robbie Hatley said:
I actually like that. Simple, direct, ALWAYS inlined.


I tried compiling that, got "Error: non-template
used as template."

Yes, I just wrote it in the news reader. Think of it as pseudo code ;)
That works, and most C++ purists would recommend it,
but I think it sucks. Too complicated. KISS.
Use the macro instead.


"error: static member function `static void MyUtils::doStuff()'
cannot have `const' method qualifier"

Yes, the const should probably go away. It's also just invented on the fly
to show roughly how I thought. Pseudo code ;)
Why stir up trouble with complicated stuff when trying to
solve a simple problem? Usually the simpliest workable
solution is the best. Sometimes a macro is the thing that fits
that bill.

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.

I'm just interested in learning different techniques of performing the same
task, just to improve my toolbox :)

Thanks!
/Carl
--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant










----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption
=---
 
M

Mark A. Gibbs

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
 
C

Carl Ribbegaardh

Mark A. Gibbs said:
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.


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.


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

Very enlightening post. I think that you might have mixed up who thought
what about macros and inline functions, but it really doesn't matter.
This was exactly the info about alternatives to macros I was looking for. :)
Thanks a lot!

/Carl
 
M

Mark A. Gibbs

Carl said:
Very enlightening post. I think that you might have mixed up who thought
what about macros and inline functions, but it really doesn't matter.
This was exactly the info about alternatives to macros I was looking for. :)

thank you, and don't worry, i was aware i was replying two steps removed
when i was harping about the dangers of macros. sorry if i gave the
impression otherwise.

mark
 
R

Robbie Hatley

Mark A. Gibbs said:
just use this.


this is probably the most bizarre thing i've read in a while.

Your reading must have been tame lately. :) Try Anne Rice.
it works, huh?:

for (int i = 0; i < 10; ++i)
STUFF

vs.

for (int i = 0; i < 10; ++i)
doStuff();

"kiss" that.

Well, that's technically correct, but you're losing
style points for no braces.

If you really needed to use such a macro in a
braceless loop like that, it COULD be done, though;
just make a slight correction to the macro definition:

#define DO_STUFF {doThis(); doThat();}

Then this will work:

for (int i = 0; i < 10; ++i)
DO_STUFF
... inline functions were largely created for the
explicit purpose of eliminating macros ...

Well, for giving programmers an option that will be
better than macros in many cases, at least.
But I wouldn't say "eliminate". Note that the C and
C++ standards committes have not removed macros from
the languages, nor do I think that'll happen.

I agree inline functions are better than macros in
most cases; but if I want to simply paste-in a block
of code in several (or many) places in a program,
I'll sometimes use a macro:

#define PASTE_HUGE_CODE_BLOCK_HERE \
first line of code\
second line of code\
third line of code\
(and so on, for many more lines)\
last line of code

#define PASTE_TINY_CODE_BLOCK_HERE b=7;

int func1(double d)
{
...
PASTE_HUGE_CODE_BLOCK_HERE
...
}

float func2(int a, char b)
{
...
#ifdef FLAG_17
PASTE_HUGE_CODE_BLOCK_HERE
#else
PASTE_TINY_CODE_BLOCK_HERE
#endif
...
}


It's really just a matter of using the preprocessor
as an automated compile-time text editor. As long as
one remembers that macros are not functions, but just
cut-n-pastes, the concept works.


--
Cheers,
Robbie Hatley
Tustin, CA, USA
email: lonewolfintj at pacbell dot net
web: home dot pacbell dot net slant earnur slant
 
A

Alf P. Steinbach

* Rolf Magnus:
#define DO_STUFF do { doThis(); doThat(); } while(false)

Unfortunately that may cause a warning with too "helpful" compilers
such as Visual C++.

Try instead

#define DO_STUFF for(;;){ doThis; doThat(); break; }
 
R

Rolf Magnus

Robbie Hatley said:
Well, that's technically correct, but you're losing
style points for no braces.

If you really needed to use such a macro in a
braceless loop like that, it COULD be done, though;
just make a slight correction to the macro definition:

#define DO_STUFF {doThis(); doThat();}

Then this will work:

for (int i = 0; i < 10; ++i)
DO_STUFF


If at all, I'd write the macro as:

#define DO_STUFF do { doThis(); doThat(); } while(false)

so that it can be used like a normal function in most cases. But I see
no benefit over an inline function, which would be simpler.
Well, for giving programmers an option that will be
better than macros in many cases, at least.
But I wouldn't say "eliminate". Note that the C and
C++ standards committes have not removed macros from
the languages, nor do I think that'll happen.

Of course not. It would make huge amounts of legacy code useless.
However, that doesn't mean that you should still use macros where an
inline function could be used.
I agree inline functions are better than macros in
most cases; but if I want to simply paste-in a block
of code in several (or many) places in a program,
I'll sometimes use a macro:

#define PASTE_HUGE_CODE_BLOCK_HERE \
first line of code\
second line of code\
third line of code\
(and so on, for many more lines)\
last line of code

I fail to see why you consider this to be more simple than:

inline void paste_huge_code_block_here()
{
first line of code
second line of code
third line of code
(and so on, for many more lines)
last line of code
}
#define PASTE_TINY_CODE_BLOCK_HERE b=7;

int func1(double d)
{
...
PASTE_HUGE_CODE_BLOCK_HERE
...
}

float func2(int a, char b)
{
...
#ifdef FLAG_17
PASTE_HUGE_CODE_BLOCK_HERE
#else
PASTE_TINY_CODE_BLOCK_HERE
#endif
...
}


It's really just a matter of using the preprocessor
as an automated compile-time text editor. As long as
one remembers that macros are not functions, but just
cut-n-pastes, the concept works.

That's the point. You have to remember, and take are. You don't have to
do that with inline functions.
 
R

Rolf Magnus

I meant:

#define DO_STUFF() do { doThis(); doThat(); } while(false)
How would that be in any way different to:


#define DO_STUFF { doThis(); doThat(); }


?

if (x) DO_STUFF(); else whatever();

This won't compile with the latter one.
 
R

Rolf Magnus

Alf said:
* Rolf Magnus:

Unfortunately that may cause a warning with too "helpful" compilers
such as Visual C++.

Try instead

#define DO_STUFF for(;;){ doThis; doThat(); break; }

Hmm, what would you gain with that for loop?
 
A

Alf P. Steinbach

* Rolf Magnus:
Hmm, what would you gain with that for loop?

See above.

And right, as you mention elsewhere, there should be empty arg list for
the macro.
 
R

Rob Williscroft

Alf P. Steinbach wrote in in
comp.lang.c++:
* Rolf Magnus:

Unfortunately that may cause a warning with too "helpful" compilers
such as Visual C++.

Yep VC++ has some distinctly un-useful warnings on by default.
I turn them off.
Try instead

#define DO_STUFF for(;;){ doThis; doThat(); break; }

if DO_STUFF;
else doThat();

The advantage of the "do .. while(false)" is it allows the
trailing semicolon, your version might as well be:

#define DO_STUFF { doThis; doThat(); }

Though in this case, I'd prefer:

#define DO_STUFF() ( doThis(), doThat() )

Rob.
 
A

Alf P. Steinbach

* Rob Williscroft:
Alf P. Steinbach wrote in in
comp.lang.c++:


Yep VC++ has some distinctly un-useful warnings on by default.
I turn them off.


if DO_STUFF;
else doThat();

The advantage of the "do .. while(false)" is it allows the
trailing semicolon, your version might as well be:

#define DO_STUFF { doThis; doThat(); }

Though in this case, I'd prefer:

#define DO_STUFF() ( doThis(), doThat() )

Right, sorry.

I've always used the do-while version, for exactly that reason,
and even preaching it to others.

Smartass, Alf. Smartass.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top