|
Boost : |
From: Dave Steffen (dgsteffen_at_[hidden])
Date: 2005-07-14 20:31:42
Having commented on the "keeping editors happy" issue in a previous
message, let me comment on Paul's stronger argument
about... well... correcteness, I think.
Just to be sure we're on the same page: this discussion started with
David Abrahams writing
> I am defining a macro,
>
> BOOST_PARAMETER_KEYWORD(tag_namespace, name)
>
> that declares a keyword for the Parameter library. It has to be
> used at namespace scope. I have the option to define it so that
> correct usage requires a trailing semicolon, or so that the
> trailing semicolon is forbidden. Unfortunately I don't have the
> ability to make it optional. Which should I choose?
so I presume he's proposing something that would, in either a .h or
.cpp file, look approximately like this:
class MyClassDefinition {....};
void My_Function_Declaration;
BOOST_PARAMETER_KEYWORD( tag, name) // #1
inline void My_Fn_Definition ()
{
... many interesting statements ...
}
and the issue is, I think, whether a semicolon at the end of the macro
invocation in line 1 is mandatory or forbidden. Paul argues
strongly for forbidden, I argue strongly for mandatory.
Paul Mensonides writes:
> > -----Original Message-----
> > From: boost-bounces_at_[hidden]
> > [mailto:boost-bounces_at_[hidden]] On Behalf Of Dave Steffen
>
> > and IMHO more "natural" to have the semicolon.
>
> You couldn't have said it better. This is *precisely* why there
> shouldn't be a trailing semicolon. This mentality needs to be
> utterly broken--it is the primary reason that macro-related
> problems come up. Macros are not functions. Invocations are are
> not expressions, they are not statements, and they are not
> declarations. They are not part of the syntax model of C++ at all.
> If you get rid the preconception that they are (or should be), it
> is actually quite a bit _less_ natural to have the trailing
> semicolon. It means that the macro only accomplishes *part* of its
> function--it only generates *part* of the code. Sometimes that's
> necessary; this isn't one of those cases. The viewpoint that must
> prevail is that macros are code writers.
I agree that macros are code writers, no arguments there.
I also agree that macros are not part of the C++ syntax model at all.
No question. From the C++ point of view, macros are some sort of
alien life form that shows up, does something that's hopefully useful
and correct (but might not be), and then goes away, leaving a trail of
slime in its wake. In the presence of macros, don't go after the
cat. :-) :-)
They're so unpleasant that Bjarne "Our Founder" Stroustrup has always
encouraged minimizing the use of the preprocessor, restricting its use
to the #include thing, and IIRC would like to come up with a language
extension eliminating even that. (Isn't there a "modules" language
extension being discussed for C++0X?) A preprocessorless C++ would
certainly be A Good Thing (that may never happen, but that's a
different discussion).
That having been said, and my hyperbole aside (it's been a long
day... ahh, deadlines) we're stuck with 'em for now, and they're
turning out to be darned useful - e.g. Boost's own preprocessor
library, and the very cool FOREACH macro.
I would claim that while macros are indeed aliens that sometimes
display unpleasant behavior (e.g. unreadable error messages when
misused), one _can_ assign some sort of C++ syntactic meaning to their
use.
For example: the FOREACH macro is clearly meant to take the syntactic
place of "for (bim; bam; boom++)", and anywhere you can put that, you
can put an appropriate FOREACH. This is an good example of your
"macro only accomplishes *part* of its function--it only generates
*part* of the code", and you follow it with the rest. Some macros act
more-or-less like type declarations, as in David Abraham's example.
Some macros act like function signatures, as in the Boost unit test
library.
Now: I would argue strongly that, to the extent that a macro is
intented to be used in some syntactic C++ context, it should do its
best to fit in to that context. BOOST_PARAMETER_KEYWORD(tag_namespace,
name) should mandate a semicolon, just as function declarations and
class definitions do. BOOST_AUTO_UNIT_TEST( tc_name ), more-or-less a
function signature at the beginning of a free function definition,
should mandate being followed by a statement block. (Maybe you can
declare, and not define, an auto unit test, but you probably don't
want to.) Irregular syntax is hard on the brain, and we've got enough
of that already. :-)
Yes: "Macros are not functions. Invocations are are not expressions,
they are not statements, and they are not declarations." But they are
going to sit side-by-side with our expressions, statements, and
declarations. I think you want to intentionally design macros _not_
to conform to the syntax of their intended use, so that anyone who
uses them sees, loud and clear, WARNING: ALIEN MACRO INVOCATION. THIS
IS NOT C++. DO NOT GO AFTER SHIP'S CAT.
I don't think that helps. I don't think it is useful to intentionally
build libraries where, from the user's point of view, some things obey
C++ grammar and some things arbitrarily don't. Yes, those that don't
obey the usual syntax make me think "Ah yes, that's a macro, am I
using it correctly?" But we already do that because of the
ALL_CAPS_MACRO convention, which flags things that C++ programmers
quickly learn to approach with caution. And if the correct syntax is
unclear ("Do I follow this macro with a semicolon, statement block, or
mystic runes?"), isn't it more likely we'll screw it up?
[Maybe the analogy I'm after is that, if the aliens are going to be in
and amongst our precious functions, classes, and statements... we
should try to make them feel welcome, so they don't get angry. :-) ]
----------------------------------------------------------------------
Dave Steffen, Ph.D. "There are two ways to write error-free
Software Engineer IV programs; only the third one works."
Numerica Corporation
ph (970) 419-8343 x27 "Pie are not square. Pie are round.
fax (970) 223-6797 Cornbread are square"
dgsteffen_at_[hidden] ... anon (usenet)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk