P
Paul Mensonides
Ioannis said:I think it is a matter of views. I did not say to remove macros from
the language but i do not consider the macros matter as a balanced
issue - that there are as many good uses as bad uses. Macros are not
to be used in daily application programming.
And that is a wrong assessment. Macros are not to be used when the use of
something else is better--and vice versa. Whether it is library code or
application code is irrelevant. You cannot simplify it that easily.
For example i program C++ applications for .NET and i see no need to
use macros. On the other hand you seem to work in libraries area and
you use macros daily to get the job done. So perhaps the "default"
for each one of us is different. I can understand the use of macros
in libraries, but still even in that case my "default" would not be
to use macros but only where i can't do work without them.
I agree that the good uses of macros appear more often in library code than in
application code. However, there is no universally clear distinction between
what should be library code and what should be application code. And even if
there was, good uses for macros in application code still appear often enough
that such a generalization is invalid. It isn't that I disagree with you
regarding the use of templates, constant variables, inline functions, etc.. I
disagree that those things even come close to encompassing the totality of macro
use--many of which you probably aren't aware of. In essence, the guideline that
you espouse is invalid because it is too broad and needs to be broken down into
constituent guidelines which actually *are* valid. Otherwise, you propogate the
status quo of prejudice-oriented programming which avoids the singlular problem
of macro name collision while simultaneously producing suboptimal code that
likely includes maintenance nightmares. Use macros when macros are the best
option to do a thing, otherwise don't--no prejudice involved, but it implies
that you actually have to *know* what is good or bad and why. There is nothing
wrong with that at all--it is the antithesis of laziness.
There are things one can do only with macros, and i would use macros
only to do those.
What about things that can be done much easier and much more efficiently in
terms of both run-time performance and maintenance?
Some quotes from TC++PL 3:
Page 10:
"The template facility was primarily designed to support statically
typed containers (such as lists, vectors, and maps) and to support
elegant and efficient use of such containers (generic programming). A
key aim was to reduce the use of macros and casts (explicit type
conversion)."
Yes, and for that purpose (and others) templates are great.
Page 14:
"1.6.1 Suggestions for C Programmers
The better one knows C, the harder it seems to be to avoid writing
C++ in C style, thereby losing some of the potential benefits of C++.
Please take a look at Appendix B, which describes the differences
between C and C++. Here are a few pointers to the areas in which C++
has better ways of doing something than C has:
[1] Macros are almost never necessary in C++.
Wrong, for a variety of reasons. The most ironic of them is that various C++
implementations differ far more radically than various C implementations.
Use const (§5.4) or enum
(§4.8) to define manifest constants,
Most of time, yes--unless it is needed by the preprocessor for a good reason.
In such a case, it should be mirrored:
#define LIBRARY_XYZ 10
namespace library {
const int xyz = LIBRARY_XYZ;
}
inline (§7.1.1) to avoid function
calling overhead,
Yes, except in very special cases where you actually *do* know better than the
compiler.
templates (Chapter 13) to specify families of
functions and types, and namespaces (§8.2) to avoid name clashes."
Namespaces don't avoid name clashes per se. They provide a means to structure
and classify names. That indirectly avoids name clashes by effectively
increasing the length of the relevant names. That's a minor point, however, and
otherwise I agree.
Page 160:
"7.8 Macros
Macros are very important in C but have far fewer uses in C++.
Along certain lines, yes. Along other lines, the exact opposite is true.
The
first rule about macros is: Don't use them unless you have to. Almost
every macro demonstrates a flaw in the programming language, in the
program, or in the programmer.
The "first rule about macros" is wrong. It should be, don't use them when there
is a superior alternative within the language proper--where "superior" means the
total set of all possible ways in which something can be superior or inferior
(some of which are subjective, some of which are not).
Many macros do indeed demonstrate flaws in the programming language--one of them
being the lack of power that macros have (compared to other macro mechanisms).
This also represents a broad class of language deficiencies that are never going
to change. Some will, yes, but otherwise, so what? Flaws in the program and in
the programmer obviously exist, and many times the use of macros demonstrates
that--as does the use of many combinations of language elements. In any case,
the above is true if "almost every macro" means almost every existing macro
currently in existence. The above is not true if "almost every macro" is
supposed to mean "almost every possible use of macros".
Because they rearrange the program
text before the compiler proper sees it, macros are also a major
problem for many programming tools.
First, macros do not rearrange the program "text", they rearrange the program's
preprocessing tokens within a translation unit. Second, that is the fundamental
reason why the preprocessor is such a powerful tool in certain types of
situations. That is what provides both the power and the danger of the
preprocessor, and consequently (as a generalization) where and when the use of
macros can be good.
So when you use macros, you
should expect inferior service from tools such as debuggers,
crossreference tools, and profilers.
Wrong, or at least, not specific enough. This is entirely dependant on how
macros are used and for what purpose.
If you must use macros, please
read the reference manual for your own implementation of the C++
preprocessor carefully and try not to be too clever. Also to warn
readers, follow the convention to name macros using lots of capital
letters."
Absolutely. In addition, you should always undefine macros that are used only
locally.
Page 161:
"Using macros, you can design your own private language. Even if you
prefer this ''enhanced language'' to plain C++, it will be
incomprehensible to most C++ programmers.
The reference here is making C++ look like, for example, Pascal. I'm definitely
not advocating doing that--along with the reason given, you'd be trading a
concise language for an extremely verbose one.
Furthermore, the C
preprocessor is a very simple macro processor. When you try to do
something non-trivial, you are likely to find it either impossible or
unnecessarily hard to do.
Which is why you have libraries that specialize in this sort of thing.
The const, inline, template, and namespace
mechanisms are intended as alternatives to many traditional uses of
preprocessor constructs.
And for many purposes, they are great alternatives. As I've said before, in
nearly all situations, these are better alternatives to their corresponding
macro formulations.
Page 163:
"7.9 Advice
[1] Be suspicious of non-const reference arguments; if you want the
function to modify its arguments, use pointers and value return
instead; §5.5. [2] Use const reference arguments when you need to
minimize copying of arguments; §5.5.
[3] Use const extensively and consistently; §7.2.
[4] Avoid macros; §7.8."
Which just illustrates Bjarne's well-known prejudice against macros resulting
from many of the traditional uses of them. So what?
Regards,
Paul Mensonides