
"Paul Mensonides" <pmenso57@comcast.net> writes:
Which is fairly obvious in nearly all cases. For example:
MACRO()
int f(...) { ... }
To humans, yes. To editors, well, that's a hard problem.
It is a pain to keep having to go back through the code and re-hand-indent certain lines after auto-indenting a whole file or a region of it.
Why would you need to auto-indent a whole file?
A whole file "or region of it". I often find myself performing work on a range of lines. Sometimes I rename variables, they get too long, and I have to split the lines. This can be automated via editor macros. After a bunch of such changes, I re-indent the buffer to clean it up, strip out trailing whitespace, and so on. Sometimes you decide that a chunk of code needs to be moved/refactored into its own function, and the indentation level is no longer correct. So you re-indent the whole region with that new function. If it happens to use MACRO() in it, now you have to go through it and re-indent. I can list numerous reasons I'd re-indent multiple lines at once. If you're really interested in the rest let me know and I'll keep going. :)
The only good reason that I see is if some sort of code generator that doesn't cater to user readable (e.g. the preprocessor) produces a mass of code that needs reformatting. In that case, it only needs to be temporarily reformatted, and it doesn't matter if it isn't quite perfect.
I don't worry too much if the whole file is generated, since I probably wouldn't be editing it anyway, but instead would be editing the spec file that was used to generate it. Or perhaps I'd edit the generator itself.
In this case, it's in a statement list where you can have null statements, so it doesn't matter if you put it there or not--it doesn't effect the design of the macro.
Agreed. In some cases the macro can be written to where the trailing user-provided semicolon is optional (in terms of resulting behavior and semantics.) [snip]
However, I'd call this a poorly designed macro because it's misleading and error prone. My personal guidelines are:
1) when a macro is logically its own statement,
I'm asserting that this is never the case. The "logically" part above is a testament to the prevailing viewpoint. It isn't logically (and definitely not physically) a statement.
By using the word "logically", I meant that "X becomes Y" can quite reasonably be described as being Y. When you throw extra parenthesis after it and do other things to change how the preprocessor expands macros, then it blurs things up. But for the typical, standard usages of macros, this indistinction is not a problem. Then again, there are extremely few people who write macros anywhere near as complicated or ambitious as you do. The simple macros are easy to write correctly. I'm not talking about newbies who don't understand double evaluation, etc., either. I'm talking about competant programmers who don't use macros very often and when they do, apply the KISS principle. [snip]
then the user should provide the semicolon to aide in readability. This makes it clear that the macro is "done". Therefore, I'd write SOME_MACRO1 to have the user provide the semicolon. This requires that the macro actually be done and its effect doesn't spill into the following code.
No it doesn't. The semicolon means nothing to the preprocessor, and the macro can still effect the code that follows.
Ok, here I think we have a miscommunication by the ambiguities of English. I apologise. I meant for antecedent to which "this requires ..." referred was the author of the macro. The macro author must ensure that after the user-provided semicolon, the macro has no more effect on subsequent code. ("This requires that the macro ACTUALLY be done...") I certainly didn't mean that having the user provide a trailing semicolon somehow forces the preprocessor to be done expanding the macro.
2) when a macro is intended to modify the code that follows it, then it should not have visible trailing semicolons or they will mislead the user. It should be obvious from indentation that the macro is being applied as a prefix to the code that follows, rather than a self-contained statement.
A self-contained statement, BTW, would include the semicolon. Otherwise, I don't disagree with this part--mainly because putting the semicolon would be erroneous in nearly all cases.
Well, I'm glad to see we already are in half agreement. :)
It seems clear to me how the semicolon's presence (or lack thereof) can confuse maintence programmers,
Confuse maintenance programmers only if they have the flawed viewpoint that I've been ranting about for years now. Worst case scenario is that the maintenance programmer has to look up the documentation for the macro. Having to do that enough times can change the perspective enough that it isn't a problem anymore.
The typical problems: A) What documentation? B) Programmer apathy. C) "Aren't we supposed to avoid macros anyway? Why effort to study them in such detail if I'm supposed to feel guilty for using them anyway?" Clearly, writing the boost preprocessor library requires a much more strict view of what's going on, and macro purity is a must. But really, how many people in the world could even write the boost preprocessor library? Heck, how many actually understand it? Compared to the number of C++ programmers, the number is probably less than 1%. In most cases, for the majority of programmers, such strictness is unnecessary and adds very little, but does make code look weird, especially after the editor has indented it incorrectly. -- Chris