
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@lists.boost.org [mailto:boost-bounces@lists.boost.org] 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@numerica.us ... anon (usenet)