Macros at namespace scope: trailing semicolon?

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? IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments? -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Jul 14, 2005, at 12:15 PM, David Abrahams wrote:
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
Emacs indents things very, very poorly if there is not ';' after the macro invocation, so I say make the trailing semicolon mandatory. Doug

On Thu, 14 Jul 2005 13:15:50 -0400 David Abrahams <dave@boost-consulting.com> wrote:
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
I prefer requiring the semicolon, mainly for nice operation within syntax-aware editors. Also, anytime I see something without a semicolon, my first instinct is to start hunting for the reason...

David Abrahams <dave@boost-consulting.com> writes:
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
I find a lot of macros that end without semicolons wind up confusing my editor's code indenter (in this case, cc-mode for emacs.) When such macros appear I start to get weird formatting that I don't like. For that reason, I always try to make macros that take parameters able to end with semicolons. -- Chris

From: David Abrahams <dave@boost-consulting.com>
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
I prefer that such macros be written to require the client to supply the semicolon. It doesn't confuse auto-indentation logic, for one thing. For another, it *looks* like a function call, even if it isn't one, so completing the facade keeps it neat in the mind. If such macros (generally, not necessarily this one) include the semicolon, so the client needn't, some will add a semicolon anyway because it looks like a function call. Then, some compilers warn about the extra semicolon. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

David Abrahams writes:
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?
<lurk mode off> This is more-or-less what I was asking about several weeks back on the "boost-users" list (although at the time I didn't know how to require the semicolon - I do now, thanks to the feedback.) As others have pointed out, it's more convenient in many ways, and IMHO more "natural" to have the semicolon. <lurk mode on> ---------------------------------------------------------------------- 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)

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Dave Steffen
As others have pointed out, it's more convenient in many ways,
It's more convenient in exactly one way only: a particular *editor* has trouble properly automatically formatting code. The last thing we should be at all concerned about is automatic formatting in some editor.
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. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Dave Steffen
As others have pointed out, it's more convenient in many ways,
It's more convenient in exactly one way only: a particular *editor* has trouble properly automatically formatting code.
No, I pointed out several other practical considerations, not least of which is that if you make a mistake with the other convention, your compiler is unlikely to tell you about it and your code will be nonportable.
The last thing we should be at all concerned about is automatic formatting in some editor.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
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.
Sorry, _what_ means the macro only accomplishes *part* of its function?
Sometimes that's necessary; this isn't one of those cases. The viewpoint that must prevail is that macros are code writers.
That is my viewpoint, for sure. I'm also in favor of making them as easy to use and as foolproof as possible. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
It's more convenient in exactly one way only: a particular *editor* has trouble properly automatically formatting code.
No, I pointed out several other practical considerations, not least of which is that if you make a mistake with the other convention, your compiler is unlikely to tell you about it and your code will be nonportable.
Such a mistake is the result of a fundamentally flawed viewpoint. One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
The last thing we should be at all concerned about is automatic formatting in some editor.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
macro only accomplishes *part* of its function--it only generates *part* of the code.
Sorry, _what_ means the macro only accomplishes *part* of its function?
When a macro can be designed to encapsulate a standalone syntactic entity but doesn't. E.g. #define MACRO struct xyz { } MACRO; ...is no different from... #define MACRO struct xyz { MACRO }; It starts it, but it doesn't finish it. As I mention below, sometimes it isn't possible, but this isn't one of those cases.
Sometimes that's necessary; this isn't one of those cases. The viewpoint that must prevail is that macros are code writers.
That is my viewpoint, for sure. I'm also in favor of making them as easy to use and as foolproof as possible.
Making them foolproof can't be done without a perspective shift from the user, and adding or elliding the semicolon doesn't make it easier or harder to use. It just makes it look more like a function call--to some editors as well as users. The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
It's more convenient in exactly one way only: a particular *editor* has trouble properly automatically formatting code.
No, I pointed out several other practical considerations, not least of which is that if you make a mistake with the other convention, your compiler is unlikely to tell you about it and your code will be nonportable.
Such a mistake is the result of a fundamentally flawed viewpoint.
Wow, that's pretty strong language. I've made the mistake, and I just don't see how my viewpoint is "fundamentally flawed." I don't pretend macro invocations are function calls. I always view them as code generators. I'm just not always sure which code they're generating, and -- yes -- sometimes I write fast and the keystrokes `) ; Ret' just flow off my fingers without my brain having a chance to intervene.
One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
It depends whether you're the person at liberty to change the code. It sounds like you're saying: - Some naive users think macros are the same as functions - That causes them to make mistakes - Thererefore we should design all macros to forbid a trailing semicolon in order to discourage that misconception - And the following are non factors - That the rest of users have no illusions about the role of macros - How much easier it makes things when the macro requires the semicolon - That requiring the semicolon can keep a category of errors from creeping into code In other words, everything else in service of wiping out some people's silly misconceptions about what macros are. Have I got that right? For my part, I think my priorities are exactly inverted from yours.
The last thing we should be at all concerned about is automatic formatting in some editor.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
I _thought_ for a minute I understood what you meant by "from the point of view of other source code," but now I'm less sure. Seems to me "other source code" doesn't care about convenience and usability; only its author does.
macro only accomplishes *part* of its function--it only generates *part* of the code.
Sorry, _what_ means the macro only accomplishes *part* of its function?
When a macro can be designed to encapsulate a standalone syntactic entity but doesn't. E.g.
#define MACRO struct xyz { }
MACRO;
...is no different from...
#define MACRO struct xyz {
MACRO };
Well, of course it's different.
It starts it, but it doesn't finish it.
Ahem. From the C++ standard grammar summary: class-specifier: class-head { member-specification(opt) }
As I mention below, sometimes it isn't possible, but this isn't one of those cases.
It sure is.
Sometimes that's necessary; this isn't one of those cases. The viewpoint that must prevail is that macros are code writers.
That is my viewpoint, for sure. I'm also in favor of making them as easy to use and as foolproof as possible.
Making them foolproof can't be done without a perspective shift from the user,
No, that does an end run around the goal: at that point the user is no longer a fool. Disabusing people of foolishness is very, very hard, so when providing a library I adopt a "policy of engagement:" I try to design the library based on sound principles, but in such a way that the user can experience success before shedding his foolishness. I hope that one day the sound principles will rub off and begin to enlighten.
and adding or elliding the semicolon doesn't make it easier or harder to use.
I am only becoming more convinced to the contrary.
It just makes it look more like a function call--to some editors as well as users.
It doesn't "just" do that.
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time.
If that was my motivation, I'd agree. But in fact requiring the semicolon makes it easier and less error-prone even for people with a correct viewpoint on the role of macros. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
No, I pointed out several other practical considerations, not least of which is that if you make a mistake with the other convention, your compiler is unlikely to tell you about it and your code will be nonportable.
Such a mistake is the result of a fundamentally flawed viewpoint.
Wow, that's pretty strong language. I've made the mistake, and I just don't see how my viewpoint is "fundamentally flawed." I don't pretend macro invocations are function calls. I always view them as code generators. I'm just not always sure which code they're generating, and -- yes -- sometimes I write fast and the keystrokes `) ; Ret' just flow off my fingers without my brain having a chance to intervene.
...which is no different than any other syntactic error that one might make when typing, and is usually the easiest kind of error to fix. The intentionally strong language is about people that habitually expect that semicolons after macro invocations at namespace scope are supposed to be there.
One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
It depends whether you're the person at liberty to change the code.
...and you can't get those that are to fix it--which means that you're attempting to use source code on a compiler that it hasn't been tested on without the ability to modify it at all.
It sounds like you're saying:
- Some naive users think macros are the same as functions
I'm saying that *most* users, naive or otherwise, view (for example) a 'max' macro as returning the greater of two (or more, I suppose) arguments.
- That causes them to make mistakes
Indeed, except with what I said.
- Thererefore we should design all macros to forbid a trailing semicolon in order to discourage that misconception
No, we should design macros without this being relevant. Generally speaking, we should define them to be self-contained entities that produce self-contained syntactic constructs.
- And the following are non factors
- That the rest of users have no illusions about the role of macros
I'm not referring to someone that is so naive that he doesn't know the difference between a macro and a function. I'm referring to typical C++ programmers, including just about everyone involved in this conversion, that thinks that making macros look like underlying language syntax is a valid goal. It causes errors far more insidious that extra semicolons.
- How much easier it makes things when the macro requires the semicolon
How much easier does it make things? I'll that I've seen here is 1) editors don't indent properly because they can't handle it, and 2) extra semicolons aren't caught by some compilers making the code non-portable. I'm not saying these are absolute non-factors, I'm saying that neither is a strong enough argument to violate (what should be) the principle and therefore propogate the same problems that we've had with the preprocessor for years and years.
- That requiring the semicolon can keep a category of errors from creeping into code
Except that it isn't preventing some kind of insidious error. Instead, its a trivial error that is trivially fixed. I don't think that you can reasonably expect to use some source code with a compiler that it hasn't been tested on without having to change it at all. Extra semicolons are the least of your worries then.
In other words, everything else in service of wiping out some people's silly misconceptions about what macros are. Have I got that right?
I think you need to reread what I've repeatedly said, Dave, instead of make assertions based on what you infer. Your own positions are rarely less than heavy-handed. This isn't a piddly little case of some silly misconceptions. It is a pervasive viewpoint that is flawed, which leads to errors, and which leads to broad denouncement of the preprocessor. It is an erroneous perspective, not a misunderstanding of the differences between macros and functions.
For my part, I think my priorities are exactly inverted from yours.
Then make another Boost policy. My priorities revolve around making things as pure as possible given the environments that we have to deal with. If that is divergent with Boost's priorities, then consider it the end of my affiliation with Boost.
The last thing we should be at all concerned about is automatic formatting in some editor.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
I _thought_ for a minute I understood what you meant by "from the point of view of other source code," but now I'm less sure. Seems to me "other source code" doesn't care about convenience and usability; only its author does.
From the point of view of other source code in terms of the source code complexity and size of a use of a construct.
It starts it, but it doesn't finish it.
Ahem. From the C++ standard grammar summary:
class-specifier: class-head { member-specification(opt) }
...which is why I said "standalone". The above cannot stand alone in any meaningful way. It *has* to have more following it or it does not form a valid syntactic construct.
As I mention below, sometimes it isn't possible, but this isn't one of those cases.
It sure is.
No, it isn't. Of course the macro can include any necessary trailing semicolon. This isn't one of those cases that where a macro cannot fully (and reasonably) encapsulate the entire syntax.
That is my viewpoint, for sure. I'm also in favor of making them as easy to use and as foolproof as possible.
Making them foolproof can't be done without a perspective shift from the user,
No, that does an end run around the goal: at that point the user is no longer a fool.
No, it doesn't. I'm saying that macros cannot be designed to generally protect against misuse without users' viewpoints being different than what they typically are.
Disabusing people of foolishness is very, very hard, so when providing a library I adopt a "policy of engagement:" I try to design the library based on sound principles, but in such a way that the user can experience success before shedding his foolishness. I hope that one day the sound principles will rub off and begin to enlighten.
Except that in this case (the expression of a library feature), you're severly underestimating a sound principle by letting it be outweighed by the possibility of extra semicolons (which is quite possibly the easiest bug to fix of all time) and by automatic formatting of some editors that many people use (but many people don't).
and adding or elliding the semicolon doesn't make it easier or harder to use.
I am only becoming more convinced to the contrary.
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time.
If that was my motivation, I'd agree. But in fact requiring ^^^^^^^ This isn't a fact; it's your opinion. Most people that want to be able to add
Thanks for clarifying. the semicolon (AFAICT) just think it's more syntactically pleasing.
the semicolon makes it easier and less error-prone even for people with a correct viewpoint on the role of macros.

Except that in this case (the expression of a library feature), you're severly underestimating a sound principle by letting it be outweighed by the
As I mentioned before, I don't think either way is perfect, and I don't even know which one I like more. However, I would like to make a couple of points, FWIW: "Paul Mensonides" <pmenso57@comcast.net> wrote possibility
of extra semicolons (which is quite possibly the easiest bug to fix of all time)
I also think that extra semicolons is not a major problem, even if only because most users (about 99%, I think) don't really care about portability.
and by automatic formatting of some editors that many people use (but many people don't).
I don't think it is correct to say that many C++ programmers don't use Visual C++, for example. It was already mentioned on this list at some point that most people do, maybe as a secondary compiler. And, In Visual Studio it is quite annoying to deal with constructs that do not adhere to the C++ syntax.
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint.
And this viewpoint is that a macro invocation is a function call? I am not sure about Dave's case, but I am more concerned about the case when a macro expands into a number of template specializations. So, when I am saying: REGISTER_TYPE(x) it is actually: GENERATE_RELEVANT_TEMPLATE_SPECIALIZATIONS_FOR_TYPE(x) Do you think requiring a semicolon would be incorrect here? Regards, Arkadiy

Arkadiy Vertleyb wrote:
As I mentioned before, I don't think either way is perfect, and I don't even know which one I like more. However, I would like to make a couple of points, FWIW:
"Paul Mensonides" <pmenso57@comcast.net> wrote
Except that in this case (the expression of a library feature), you're
severly
underestimating a sound principle by letting it be outweighed by the
possibility
of extra semicolons (which is quite possibly the easiest bug to fix of all
time)
I also think that extra semicolons is not a major problem, even if only because most users (about 99%, I think) don't really care about portability.
To me the whole portability discussion is missing one crucial point. Portability is not only about being able to easily fix errors. It's also about teams/people on different platforms working together. You really don't want them to break each others code regularly, because this has a tendency to create bad feelings. Things that are non-diagnosable on one of the platforms make this really hard. Just my 2ct Thomas

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Arkadiy Vertleyb
and by automatic formatting of some editors that many people use (but many people don't).
I don't think it is correct to say that many C++ programmers don't use Visual C++, for example. It was already mentioned on this list at some point that most people do, maybe as a secondary compiler. And, In Visual Studio it is quite annoying to deal with constructs that do not adhere to the C++ syntax.
BTW, I use the VC++ IDE, but I rarely compile anything with VC++. I use it mainly for project management and editing. You're right, it does a horrible job at syntax highlighting and parentheses matching, but I use it precisely because it does not automatically indent code in a way that I can't correct without it constantly changing it back.
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint.
And this viewpoint is that a macro invocation is a function call?
No, that a macro invocation is a kind of unit of work similar to a function call. For example, #define max(a, b) ((a) < (b) ? (b) : (a)) ... max(x, y) ... Most programmers view this invocation as a macro that returns the greater of two arguments. That viewpoint is wrong, and is what leads, in this scenario, to multiple evaluation problems. What the macro does is expand to the expression ((a) ... ).
I am not sure about Dave's case, but I am more concerned about the case when a macro expands into a number of template specializations. So, when I am saying:
REGISTER_TYPE(x)
it is actually:
GENERATE_RELEVANT_TEMPLATE_SPECIALIZATIONS_FOR_TYPE(x)
Do you think requiring a semicolon would be incorrect here?
For example: #define MAKE() \ struct abc { }; \ struct xyz { } \ /**/ MAKE(); I find adding the first semicolon after 'abc', but not adding the second semicolon after 'xyz' to be an abomination. I find that worse that the case of single struct definition (e.g.) because now the macro definition is inconsistant within itself. Despite that, I still think that in the single definition case the macro should include the trailing semicolon--unless you intentionally want to allow users to define variables (or types through 'typedef MACRO() x;') Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
No, I pointed out several other practical considerations, not least of which is that if you make a mistake with the other convention, your compiler is unlikely to tell you about it and your code will be nonportable.
Such a mistake is the result of a fundamentally flawed viewpoint.
Wow, that's pretty strong language. I've made the mistake, and I just don't see how my viewpoint is "fundamentally flawed." I don't pretend macro invocations are function calls. I always view them as code generators. I'm just not always sure which code they're generating, and -- yes -- sometimes I write fast and the keystrokes `) ; Ret' just flow off my fingers without my brain having a chance to intervene.
...which is no different than any other syntactic error that one might make when typing, and is usually the easiest kind of error to fix.
It is different in that many compilers won't detect it.
The intentionally strong language is about people that habitually expect that semicolons after macro invocations at namespace scope are supposed to be there.
Well, some part of my brain obviously expects that habitually.
One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
It depends whether you're the person at liberty to change the code.
...and you can't get those that are to fix it--which means that you're attempting to use source code on a compiler that it hasn't been tested on without the ability to modify it at all.
I'm just trying to say that modifying the code is much easier for some people than for others. If you're the author, it's usually trivial, but all sorts of restrictions get in the way for other people, to varying degrees.
It sounds like you're saying:
- Some naive users think macros are the same as functions
I'm saying that *most* users, naive or otherwise, view (for example) a 'max' macro as returning the greater of two (or more, I suppose) arguments.
I see where you're coming from.
- That causes them to make mistakes
Indeed, except with what I said.
Huh?
- Thererefore we should design all macros to forbid a trailing semicolon in order to discourage that misconception
No, we should design macros without this being relevant. Generally speaking, we should define them to be self-contained entities that produce self-contained syntactic constructs.
Okay, that's a more refined point-of-view.
- And the following are non factors
- That the rest of users have no illusions about the role of macros
I'm not referring to someone that is so naive that he doesn't know the difference between a macro and a function. I'm referring to typical C++ programmers, including just about everyone involved in this conversion, that thinks that making macros look like underlying language syntax is a valid goal.
I understand you to have two objections to that point of view, which can be summarized as - It leads some people to think that max(a,b) is a function call - it is self-perpetuating. I understand the first objection, but to buy into the 2nd one I have to accept that it's an invalid goal before I can believe the reasons you give for it being invalid. So far that looks like a leap of faith.
It causes errors far more insidious that extra semicolons.
What sort of insidious errors do you think I make because of that point of view?
- How much easier it makes things when the macro requires the semicolon
How much easier does it make things? I'll that I've seen here is 1) editors don't indent properly because they can't handle it, and 2) extra semicolons aren't caught by some compilers making the code non-portable.
and 3) many people find it "more natural." We have had reports in this thread that the semicolon sometimes comes up automatically, and not seeing the semicolon causes people some "cognitive dissonance."
I'm not saying these are absolute non-factors, I'm saying that neither is a strong enough argument to violate (what should be) the principle and therefore propogate the same problems that we've had with the preprocessor for years and years.
Somehow I have trouble seeing a tiny design choice like this one as the cause of those problems.
- That requiring the semicolon can keep a category of errors from creeping into code
Except that it isn't preventing some kind of insidious error. Instead, its a trivial error that is trivially fixed. I don't think that you can reasonably expect to use some source code with a compiler that it hasn't been tested on without having to change it at all. Extra semicolons are the least of your worries then.
Somehow, I do have that expectation though.
In other words, everything else in service of wiping out some people's silly misconceptions about what macros are. Have I got that right?
I think you need to reread what I've repeatedly said, Dave, instead of make assertions based on what you infer.
I'm asking for clarification based on my understanding of what you've repeatedly said. If I haven't got it right, just tell me so.
Your own positions are rarely less than heavy-handed. This isn't a piddly little case of some silly misconceptions. It is a pervasive viewpoint that is flawed, which leads to errors, and which leads to broad denouncement of the preprocessor. It is an erroneous perspective, not a misunderstanding of the differences between macros and functions.
For my part, I think my priorities are exactly inverted from yours.
Then make another Boost policy.
Now _that_ would be heavy-handed :)
My priorities revolve around making things as pure as possible given the environments that we have to deal with. If that is divergent with Boost's priorities, then consider it the end of my affiliation with Boost.
Wow. I don't know what to say. I don't know about the priorities of the rest of Boost, but I guess purity is a lower priority for me than some other things.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
I _thought_ for a minute I understood what you meant by "from the point of view of other source code," but now I'm less sure. Seems to me "other source code" doesn't care about convenience and usability; only its author does.
From the point of view of other source code in terms of the source code complexity and size of a use of a construct.
Sorry, I don't understand yet.
It starts it, but it doesn't finish it.
Ahem. From the C++ standard grammar summary:
class-specifier: class-head { member-specification(opt) }
...which is why I said "standalone". The above cannot stand alone in any meaningful way. It *has* to have more following it or it does not form a valid syntactic construct.
I see. Well, I still maintain that #define MACRO struct xyz { MACRO }; is a different category of beast.
As I mention below, sometimes it isn't possible, but this isn't one of those cases.
It sure is.
No, it isn't.
Now that I understand what you meant by "standalone", I agree that it isn't.
That is my viewpoint, for sure. aI'm also in favor of making them as easy to use and as foolproof as possible.
Making them foolproof can't be done without a perspective : shift from the user,
No, that does an end run around the goal: at that point the user is no longer a fool.
No, it doesn't. I'm saying that macros cannot be designed to generally protect against misuse without users' viewpoints being different than what they typically are.
Agreed.
Disabusing people of foolishness is very, very hard, so when providing a library I adopt a "policy of engagement:" I try to design the library based on sound principles, but in such a way that the user can experience success before shedding his foolishness. I hope that one day the sound principles will rub off and begin to enlighten.
Except that in this case (the expression of a library feature), you're severly underestimating a sound principle by letting it be outweighed by the possibility of extra semicolons (which is quite possibly the easiest bug to fix of all time) and by automatic formatting of some editors that many people use (but many people don't).
Yeah, so far that's how the balance tilts for me. I understand your point of view better now, but still am not persuaded to raise my estimation of the importance of that principle.
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time.
If that was my motivation, I'd agree. But in fact requiring ^^^^^^^ This isn't a fact; it's your opinion. Most people that want to be able to add the semicolon (AFAICT) just think it's more syntactically pleasing.
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
the semicolon makes it easier and less error-prone even for people with a correct viewpoint on the role of macros.
-- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
...which is no different than any other syntactic error that one might make when typing, and is usually the easiest kind of error to fix.
It is different in that many compilers won't detect it.
But it is a triviality. I understand the problem, but I fail to see how the problem is anything but slight, especially given the cirumstances where it could become significant. In those circumstances, the likelihood of this being the showstopper is extremely low.
The intentionally strong language is about people that habitually expect that semicolons after macro invocations at namespace scope are supposed to be there.
Well, some part of my brain obviously expects that habitually.
Then you're perspective needs to change so that it doesn't. I except that you in particular don't have any serious problems with the issues that I'm harping on, but that's probably because of your familiarity with preprocessor metaprogramming. This isn't about preprocessor metaprogramming per se, but about macros in general (obviously, any macro is a metaprogramming construct, but I think that you understand the distinction that I'm making).
One which I don't think we should accommodate. Worst case scenario is that someone makes the mistake and it has to be trivially fixed in a port. Fixing a "semicolon not allowed here" error is hardly difficult.
It depends whether you're the person at liberty to change the code.
...and you can't get those that are to fix it--which means that you're attempting to use source code on a compiler that it hasn't been tested on without the ability to modify it at all.
I'm just trying to say that modifying the code is much easier for some people than for others. If you're the author, it's usually trivial, but all sorts of restrictions get in the way for other people, to varying degrees.
I know, but you're projecting this problem into a circumstance where there are so many potential problems that the likelihood of this being the one thing that prevents reuse is extremely low. That circumstance (to reiterate) is attempting to use source code on a compiler that the code hasn't been tested on without the ability to modify it in any way.
It sounds like you're saying:
- Some naive users think macros are the same as functions
I'm saying that *most* users, naive or otherwise, view (for example) a 'max' macro as returning the greater of two (or more, I suppose) arguments.
I see where you're coming from.
To try to be a little more clear, "...as returning, for all intensive purposes, the greater of two arguments." That is, not confusing it with a function, but confusing a syntactic effect with a semantic one.
- That causes them to make mistakes
Indeed, except with what I said.
Huh?
Confusing syntactic effect with semantic effect causes mistakes.
- Thererefore we should design all macros to forbid a trailing semicolon in order to discourage that misconception
No, we should design macros without this being relevant. Generally speaking, we should define them to be self-contained entities that produce self-contained syntactic constructs.
Okay, that's a more refined point-of-view.
I'm definitely not saying that we should intentionally design macros to *not* look like functions. I'm saying that we should not intentionally design macros *to* look like functions.
I'm not referring to someone that is so naive that he doesn't know the difference between a macro and a function. I'm referring to typical C++ programmers, including just about everyone involved in this conversion, that thinks that making macros look like underlying language syntax is a valid goal.
I understand you to have two objections to that point of view, which can be summarized as
- It leads some people to think that max(a,b) is a function call
Not a function call, a semantic effect.
- it is self-perpetuating.
I understand the first objection, but to buy into the 2nd one I have to accept that it's an invalid goal before I can believe the reasons you give for it being invalid. So far that looks like a leap of faith.
It is an invalid goal because it intentionally blurs the distinction between syntactic and semantic effects. A lack of formal distinction leads to macro-related bugs that are the main reasons for the antipathy towards the preprocessor. I.e. it's unsafe, etc..
It causes errors far more insidious that extra semicolons.
What sort of insidious errors do you think I make because of that point of view?
Not you specifically, C and C++ programmers in general. One such mistake is multiple evaluation with side-effects (or even without them).
- How much easier it makes things when the macro requires the semicolon
How much easier does it make things? I'll that I've seen here is 1) editors don't indent properly because they can't handle it, and 2) extra semicolons aren't caught by some compilers making the code non-portable.
and 3) many people find it "more natural."
Which is the part that I most disagree with.
We have had reports in this thread that the semicolon sometimes comes up automatically, and not seeing the semicolon causes people some "cognitive dissonance."
Where "cognitive dissonance" means "having to view things from a superior and more technically correct perspective."
I'm not saying these are absolute non-factors, I'm saying that neither is a strong enough argument to violate (what should be) the principle and therefore propogate the same problems that we've had with the preprocessor for years and years.
Somehow I have trouble seeing a tiny design choice like this one as the cause of those problems.
It propogates the laudability of explicitly designing macros to look like syntactic entities. E.g. "Boost does it, therefore it must be good."
- That requiring the semicolon can keep a category of
errors from
creeping into code
Except that it isn't preventing some kind of insidious error. Instead, its a trivial error that is trivially fixed. I don't think that you can reasonably expect to use some source code with a compiler that it hasn't been tested on without having to change it at all. Extra semicolons are the least of your worries then.
Somehow, I do have that expectation though.
I seriously doubt any non-trivial piece of source code that contains no workarounds for a particular compiler and has not been tested on that compiler can be used "out-of-the-box" on that compiler--at least, not with C++. If we ever approximate the ideal of having portable C++ (meaning nearly all compilers approximate the standard very very closely) then this issue shouldn't come up because compilers would flag it as an error. Until that point, I don't think it's realistic to have that expectation.
Your own positions are rarely less than heavy-handed. This isn't a piddly little case of some silly misconceptions. It is a pervasive viewpoint that is flawed, which leads to errors, and which leads to broad denouncement of the preprocessor. It is an erroneous perspective, not a misunderstanding of the differences between macros and functions.
For my part, I think my priorities are exactly inverted from yours.
Then make another Boost policy.
Now _that_ would be heavy-handed :)
Yet we have some of those policies already. One example is tabs in source files. It is a total non-issue except in one situation: using tabs in the middle of a line of code rather than to indent it.
My priorities revolve around making things as pure as possible given the environments that we have to deal with. If that is divergent with Boost's priorities, then consider it the end of my affiliation with Boost.
Wow. I don't know what to say.
I don't know about the priorities of the rest of Boost, but I guess purity is a lower priority for me than some other things.
My conception of Boost, and the basis for my involvement (for whatever its worth), is that Boost isn't just about providing tools to get the job done. It's about providing tools--written the right way--to get the job done the right way to the greatest extent possible given the compilers and platforms that we have to deal with. If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Convenience, usability, and the chance of not making a trivial unintentional error are important factors in the design of any component.
Convenience and usability from the point of view of other source code, not how that source code is written.
I _thought_ for a minute I understood what you meant by "from the point of view of other source code," but now I'm less sure. Seems to me "other source code" doesn't care about convenience and usability; only its author does.
From the point of view of other source code in terms of the source code complexity and size of a use of a construct.
Sorry, I don't understand yet.
It is certainly in terms of the convenience and usability of the author, but in terms of the complexity required for a use of a construct to be understood by the author and the terseness or verbosity of the expression of that construct by the author. Having no semicolon doesn't make it significantly less convenient nor does it increase complexity. Rather, it merely requires a programmer's perspective to be a little different--but not in a way that is difficult to grasp.
I see. Well, I still maintain that
#define MACRO struct xyz {
MACRO };
is a different category of beast.
Not from my perspective. In both cases, a standalone entity is started, but not finished--for no good reason. The only difference is that MACRO }; is obviously different from any normal C++ syntactic construct. If I *had* to choose between intentionally designing macros to not look like underlying syntactic constructs and intentionally designing macros to look like underlying syntactic constructs, I'd choose the former, but both a flawed constraints. Doing either, IMO, is bad design.
Except that in this case (the expression of a library feature), you're severly underestimating a sound principle by letting it be outweighed by the possibility of extra semicolons (which is quite possibly the easiest bug to fix of all time) and by automatic formatting of some editors that many people use (but many people don't).
Yeah, so far that's how the balance tilts for me. I understand your point of view better now, but still am not persuaded to raise my estimation of the importance of that principle.
The effect in this one particular instance is trivial. The effect of this being a generally agreed upon "best practice" is. This particular case is just one small addition to the mountain of bad code produced by the so-called "best practice".
The problem that I have is not so much with catering to editors (though I am against that in principle), but with catering to an incorrect viewpoint. The harm in doing so far outweighs extraneous issues like source code formatting over time.
If that was my motivation, I'd agree. But in fact requiring ^^^^^^^ This isn't a fact; it's your opinion. Most people that want to be able to add the semicolon (AFAICT) just think it's more syntactically pleasing.
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
If the preprocessor had more of an ability to manipulate syntax or was part of the syntax (as in Lisp or Scheme), then we could do this. But it doesn't, and all this does is make it look like the macro is something that it is not. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
Now _that_ would be heavy-handed :)
Yet we have some of those policies already. One example is tabs in source files. It is a total non-issue except in one situation: using tabs in the middle of a line of code rather than to indent it.
Actually, no. IIRC it's a GNU convention to use 8-space tabs and indent in multiples of 4 spaces, so lines start with a sequence of zero or more tabs and successive levels of indentation end either with a tab or with 4 spaces. When I change my tab width to anything other than 8-space tabs, nothing looks right. If I change to 3-space tabs I can even get the indentation to invert. Now, you can tell me "I meant to rule that case out too," but it just goes to show that it is a nontrivial thing to create a policy that actually works. I really don't want to get into an argument about whether the Boost tab policy is wrong or right... like many other things I've been discussing today, the Boost policy (ca. 1998) is in place for practical reasons. If someone could find a simple and proven policy that allows tabs at the beginning of a line and is easy for everyone to follow without silly misinterpretations, I'd be fine with it. We didn't have time -- or maybe enough smarts -- or maybe enough people who cared enough about being able to use tabs -- back then, to figure out how to be maximally permissive without causing problems. We wanted to get about the business of building Boost, and that policy is what we ended up with.
My priorities revolve around making things as pure as possible given the environments that we have to deal with. If that is divergent with Boost's priorities, then consider it the end of my affiliation with Boost.
Wow. I don't know what to say.
I don't know about the priorities of the rest of Boost, but I guess purity is a lower priority for me than some other things.
My conception of Boost, and the basis for my involvement (for whatever its worth), is that Boost isn't just about providing tools to get the job done. It's about providing tools--written the right way--to get the job done the right way to the greatest extent possible given the compilers and platforms that we have to deal with.
Right. But, people of goodwill and reasonable intelligence can disagree about how to evaluate "the right way." It's not an absolute.
If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Are you being intentionally insulting? FWIW, one of the main reasons I brought this issue up was that I was hoping you'd convince me that the reasons to do it your way were important enough to outweigh the reasons to go the other way.
It is certainly in terms of the convenience and usability of the author, but in terms of the complexity required for a use of a construct to be understood by the author and the terseness or verbosity of the expression of that construct by the author. Having no semicolon doesn't make it significantly less convenient nor does it increase complexity. Rather, it merely requires a programmer's perspective to be a little different--but not in a way that is difficult to grasp.
Trivial things do add up.
I see. Well, I still maintain that
#define MACRO struct xyz {
MACRO };
is a different category of beast.
Not from my perspective. In both cases, a standalone entity is started, but not finished--for no good reason.
That last part is debatable, but aside from that what you say is true. OTOH, the case above does not complete any syntactic entity at all, whereas the struct declaration without the trailing semicolon does. Of course, the thing I want to do completes one standalone and one non-standalone syntactic entity, so maybe it's in another category still.
The only difference is that MACRO }; is obviously different from any normal C++ syntactic construct.
If I *had* to choose between intentionally designing macros to not look like underlying syntactic constructs and intentionally designing macros to look like underlying syntactic constructs, I'd choose the former, but both a flawed constraints. Doing either, IMO, is bad design.
Well, I don't view myself as doing either one, FWIW. "Looking like underlying syntax" is not a design criterion for me.
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
If the preprocessor had more of an ability to manipulate syntax or was part of the syntax (as in Lisp or Scheme), then we could do this.
Do what? Are you saying we can't syntactic pleasantness into account because the PP can't manipulate syntax?
But it doesn't, and all this does is make it look like the macro is something that it is not.
Still looks like a code-generating macro to me, with or without the semicolon. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
Now _that_ would be heavy-handed :)
Yet we have some of those policies already. One example is tabs in source files. It is a total non-issue except in one situation: using tabs in the middle of a line of code rather than to indent it.
Actually, no. IIRC it's a GNU convention to use 8-space tabs and indent in multiples of 4 spaces, so lines start with a sequence of zero or more tabs and successive levels of indentation end either with a tab or with 4 spaces. When I change my tab width to anything other than 8-space tabs, nothing looks right. If I change to 3-space tabs I can even get the indentation to invert. Now, you can tell me "I meant to rule that case out too," but it just goes to show that it is a nontrivial thing to create a policy that actually works.
In this case it is trivial. Use tabs xor spaces to indent (and only to indent).
I really don't want to get into an argument about whether the Boost tab policy is wrong or right... like many other things I've been discussing today, the Boost policy (ca. 1998) is in place for practical reasons. If someone could find a simple and proven policy that allows tabs at the beginning of a line and is easy for everyone to follow without silly misinterpretations, I'd be fine with it. We didn't have time -- or maybe enough smarts -- or maybe enough people who cared enough about being able to use tabs -- back then, to figure out how to be maximally permissive without causing problems. We wanted to get about the business of building Boost, and that policy is what we ended up with.
I don't want to get into this argument either. I mention it because I think it is a heavy-handed policy. It is a ban on something that can cause problems, but doesn't have to cause problems. For my part, it doesn't matter much because I write preprocessor code differently than regular code. I always use spaces to indent preprocessor code, but never in my other work. Otherwise it makes writing code require an editor capable of treating sequences of some number of spaces as tabular indentation.
My conception of Boost, and the basis for my involvement (for whatever its worth), is that Boost isn't just about providing tools to get the job done. It's about providing tools--written the right way--to get the job done the right way to the greatest extent possible given the compilers and platforms that we have to deal with.
Right. But, people of goodwill and reasonable intelligence can disagree about how to evaluate "the right way." It's not an absolute.
Actually, the right way nearly always *is* an absolute; it's just that none of us are smart enough to always know what that right way is. I generally don't even bother taking sides unless I've given a subject a great deal of thought--even if I have an opinion. This is one case that I've been thinking about for years. Specifically, the root causes of the antipathy for the preprocessor.
If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Are you being intentionally insulting?
No, I'm saying what I think. I honestly think it is ridiculous for Boost to worry about editor compatibility. We have enough difficulty with just compiler compatibility.
FWIW, one of the main reasons I brought this issue up was that I was hoping you'd convince me that the reasons to do it your way were important enough to outweigh the reasons to go the other way.
I know.
It is certainly in terms of the convenience and usability of the author, but in terms of the complexity required for a use of a construct to be understood by the author and the terseness or verbosity of the expression of that construct by the author. Having no semicolon doesn't make it significantly less convenient nor does it increase complexity. Rather, it merely requires a programmer's perspective to be a little different--but not in a way that is difficult to grasp.
Trivial things do add up.
They can add up. Sometimes they are trivial enough that they approach zero overhead in comparison with the alternative. I think that this is one of those cases. The concepts aren't difficult to understand.
Not from my perspective. In both cases, a standalone entity is started, but not finished--for no good reason.
That last part is debatable, but aside from that what you say is true. OTOH, the case above does not complete any syntactic entity at all, whereas the struct declaration without the trailing semicolon does.
I'm referring to a syntactic entity that doesn't require addition syntax to be valid C++. Obviously, take that with a grain of salt. I don't mean that macros should provide the surrounding function if they produce an expression statement.
The only difference is that MACRO }; is obviously different from any normal C++ syntactic construct.
If I *had* to choose between intentionally designing macros to not look like underlying syntactic constructs and intentionally designing macros to look like underlying syntactic constructs, I'd choose the former, but both a flawed constraints. Doing either, IMO, is bad design.
Well, I don't view myself as doing either one, FWIW. "Looking like underlying syntax" is not a design criterion for me.
It appears to me that it is (a design criterion for you) by proxy. You've given the argument that "many people think it looks more natural", which is another way of saying "looking like the underlying syntax". If an editor has problems with a construct, then a workaround should be applied for that editor (or family of editors), but not globally. You can take your macro (which, for the sake of argument, includes the semicolon) and wrap it in another macro: // library code: #define MACRO(id) struct id { }; // normal client code: MACRO(xyz) // client with editor problems library code... namespace empty { }; #define MACRO_II(id) MACRO(id) using namespace ::empty // client with editor problems code... MACRO_II(xyz);
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
If the preprocessor had more of an ability to manipulate syntax or was part of the syntax (as in Lisp or Scheme), then we could do this.
Do what? Are you saying we can't syntactic pleasantness into account because the PP can't manipulate syntax?
I'm saying that we can't make PP syntax as syntactically pleasing as the underlying language syntax (e.g. a healthy distribution of operators, keywords, etc.). If we could manipulate the syntax, then we could make it that syntactically pleasing.
But it doesn't, and all this does is make it look like the macro is something that it is not.
Still looks like a code-generating macro to me, with or without the semicolon.
I agree, but I also think it looks like a macro that's supposed to act as a syntactic entity. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
it is a nontrivial thing to create a policy that actually works.
In this case it is trivial. Use tabs xor spaces to indent (and only to indent).
So, no spaces anywhere else on the line? Try again.
We wanted to get about the business of building Boost, and that policy is what we ended up with.
I don't want to get into this argument either. I mention it because I think it is a heavy-handed policy. It is a ban on something that can cause problems, but doesn't have to cause problems.
Sorta like the design choice we're debating right now?
For my part, it doesn't matter much because I write preprocessor code differently than regular code. I always use spaces to indent preprocessor code, but never in my other work. Otherwise it makes writing code require an editor capable of treating sequences of some number of spaces as tabular indentation.
Your editor can't do that?
My conception of Boost, and the basis for my involvement (for whatever its worth), is that Boost isn't just about providing tools to get the job done. It's about providing tools--written the right way--to get the job done the right way to the greatest extent possible given the compilers and platforms that we have to deal with.
Right. But, people of goodwill and reasonable intelligence can disagree about how to evaluate "the right way." It's not an absolute.
Actually, the right way nearly always *is* an absolute;
I said that *how to evaluate* "the right way" isn't absolute. I believe that, and as a result people can come to different conclusions.
it's just that none of us are smart enough to always know what that right way is. I generally don't even bother taking sides unless I've given a subject a great deal of thought--even if I have an opinion. This is one case that I've been thinking about for years. Specifically, the root causes of the antipathy for the preprocessor.
Yes, and that is a more important issue to you than to some other people. A person's system of values will affect how he evaluates "the right way."
If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Are you being intentionally insulting?
No, I'm saying what I think. I honestly think it is ridiculous for Boost to worry about editor compatibility. We have enough difficulty with just compiler compatibility.
It's not the same class of problem at all. For one thing, it's much less critical: when a compiler is incompatible with some code, the code simply doesn't work. There's not much to worry about if you've found a way to do it that's compatible with all known editors and causes problems for none.
Well, I don't view myself as doing either one, FWIW. "Looking like underlying syntax" is not a design criterion for me.
It appears to me that it is (a design criterion for you) by proxy.
No. I'm sorry to be blunt, but "by proxy" or otherwise, it isn't a design criterion for me. Accessibility and comfort for my users is the criterion. I don't really care *why* they're more comfortable.
You've given the argument that "many people think it looks more natural",
Yes.
which is another way of saying "looking like the underlying syntax".
I'm not sure of that, but I really don't care.
If an editor has problems with a construct, then a workaround should be applied for that editor (or family of editors), but not globally. You can take your macro (which, for the sake of argument, includes the semicolon) and wrap it in another macro:
// library code:
#define MACRO(id) struct id { };
// normal client code:
MACRO(xyz)
// client with editor problems library code...
namespace empty { };
#define MACRO_II(id) MACRO(id) using namespace ::empty
// client with editor problems code...
MACRO_II(xyz);
I'm really surprised you'd suggest that. The impurity of that workaround is enormous compared with that of the workaround that adds a semicolon when the macro starts without on.
Don't underestimate how much easier it gets for people to read and write code when it's syntactically pleasing.
If the preprocessor had more of an ability to manipulate syntax or was part of the syntax (as in Lisp or Scheme), then we could do this.
Do what? Are you saying we can't syntactic pleasantness into account because the PP can't manipulate syntax?
I'm saying that we can't make PP syntax as syntactically pleasing as the underlying language syntax (e.g. a healthy distribution of operators, keywords, etc.). If we could manipulate the syntax, then we could make it that syntactically pleasing.
I didn't say we could make it "that syntactically pleasing." I'm saying syntactic pleasantness counts, and we do have the power to make choices on that basis in the design of macros.
But it doesn't, and all this does is make it look like the macro is something that it is not.
Still looks like a code-generating macro to me, with or without the semicolon.
I agree, but I also think it looks like a macro that's supposed to act as a syntactic entity.
Only if you misjudge the motivations of the author. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
it is a nontrivial thing to create a policy that actually works.
In this case it is trivial. Use tabs xor spaces to indent (and only to indent).
So, no spaces anywhere else on the line? Try again.
It doesn't address non-indentation whitespace, and even if it did, it would still be trivial.
We wanted to get about the business of building Boost, and that policy is what we ended up with.
I don't want to get into this argument either. I mention it because I think it is a heavy-handed policy. It is a ban on something that can cause problems, but doesn't have to cause problems.
Sorta like the design choice we're debating right now?
It is nothing like what we're debating. Adding a semicolon after a macro invocation is conceptually broken.
For my part, it doesn't matter much because I write preprocessor code differently than regular code. I always use spaces to indent preprocessor code, but never in my other work. Otherwise it makes writing code require an editor capable of treating sequences of some number of spaces as tabular indentation.
Your editor can't do that?
Not all of my editors can do that. There are times that I'll open something as simple as notepad to edit something because it is faster.
Right. But, people of goodwill and reasonable intelligence can disagree about how to evaluate "the right way." It's not an absolute.
Actually, the right way nearly always *is* an absolute;
I said that *how to evaluate* "the right way" isn't absolute. I believe that, and as a result people can come to different conclusions.
Okay.
it's just that none of us are smart enough to always know what that right way is. I generally don't even bother taking sides unless I've given a subject a great deal of thought--even if I have an opinion. This is one case that I've been thinking about for years. Specifically, the root causes of the antipathy for the preprocessor.
Yes, and that is a more important issue to you than to some other people. A person's system of values will affect how he evaluates "the right way."
Indeed.
If that isn't part of it, I have no interest in sticking around. Catering to editors in the face of purity is taking "compilers and platforms that we have to deal with" to the point of being asinine.
Are you being intentionally insulting?
No, I'm saying what I think. I honestly think it is ridiculous for Boost to worry about editor compatibility. We have enough difficulty with just compiler compatibility.
It's not the same class of problem at all. For one thing, it's much less critical: when a compiler is incompatible with some code, the code simply doesn't work. There's not much to worry about if you've found a way to do it that's compatible with all known editors and causes problems for none.
Except that it is a workaround for an editor, but there is nothing in the source code that indicates that it is a workaround at all. It is an unnecessary design alteration, and the design is not as conceptually well-founded as the original.
If an editor has problems with a construct, then a workaround should be applied for that editor (or family of editors), but not globally. You can take your macro (which, for the sake of argument, includes the semicolon) and wrap it in another macro:
// library code:
#define MACRO(id) struct id { };
// normal client code:
MACRO(xyz)
// client with editor problems library code...
namespace empty { };
Except without this ^^^ semicolon, of course.
#define MACRO_II(id) MACRO(id) using namespace ::empty
// client with editor problems code...
MACRO_II(xyz);
I'm really surprised you'd suggest that. The impurity of that workaround is enormous compared with that of the workaround that adds a semicolon when the macro starts without on.
Except that the impurity wouldn't be in Boost, and even if it was, it would clearly be a workaround instead of an alternate design.
I agree, but I also think it looks like a macro that's supposed to act as a syntactic entity.
Only if you misjudge the motivations of the author.
Not really. My judgement is clear. It is either a workaround for an editor (or editors), a way to please users by making it look like a regular statement, or both. Despite what you say, frankly or otherwise, the last is the motivation. It's a transitive situation. If your motivation is to do what users want, but their motivation is X, then the motivation for a design is X. You aren't buffered by the indirection. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
I agree, but I also think it looks like a macro that's supposed to act as a syntactic entity.
Only if you misjudge the motivations of the author.
Not really. My judgement is clear. It is either a workaround for an editor (or editors), a way to please users by making it look like a regular statement, or both. Despite what you say, frankly or otherwise, the last is the motivation. It's a transitive situation. If your motivation is to do what users want, but their motivation is X, then the motivation for a design is X. You aren't buffered by the indirection.
No. If I make knives and my motivation is to make knives that please my customers, and some customer likes a particular design feature because it makes the knife an effective murder weapon, that doesn't mean that the feature is motivated by murder. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
If I make knives and my motivation is to make knives that please my customers, and some customer likes a particular design feature because it makes the knife an effective murder weapon, that doesn't mean that the feature is motivated by murder.
If you want to please your customers, *knowing* what their motivations are, then the motivations are transitive. You're right--if a particular customer likes it for bad reasons, and that user is representative of only a tiny minority, then that's one thing, but if it is one of the predominant motivations, then it's another, and then you *are* responsible though possibly not as responsible to the same degree. To continue with analogies... If your neighbor comes over and asks to borrow a knife but doesn't reveal his intentions and then kills his wife with it, you're not at fault, but if he comes over and asks to borrow a knife so he can kill his wife, and you give it to him, then you are *at minimum* partially at fault. In the United States, at least, it'd be called an "accessory to murder". Despite my disagreement regarding the editor issue, that motivation is significantly less damaging than the "looks more natural" motivation. I wouldn't be so utterly turned off (putting it lightly) by the workaround, if it weren't for the other getting such a high degree of credence. Beyond that, there is nothing in the source to indicate that it *is* a workaround, leading to users thinking that the technique of making it look more inline with the underlying syntax is condoned by Boost--an entity with some authority on good coding practice, regardless of Boost's actual intent. This is a motivation known to be [at least one of] the predominant motivations in the user base based on the sampling that we've had here (and elsewhere)--which is very likely to be a good generalization across the rest of the user base. From a workaround point-of-view only, which is the only thing that is even in the ballpark of a good perspective, IMO, it's a question of whether a design workaround should be explicit--I think it should be. It isn't hard to provide a separate workaround, either in Boost or locally by users of these editors (that are purportedly smart, but aren't smart enough to handle a language with dynamic syntax). It doesn't even have to be on a per macro basis. It could be: MACRO(xyz) SEMICOLON; I agree that that is ugly, but in light of it being an explicit workaround and in light of the fact that users can define a macro to make it look better if they wish (just maybe while doing so they wonder why Boost didn't do it), it is worth the less-than-ideal syntax. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
boost-bounces@lists.boost.org wrote:
If I make knives and my motivation is to make knives that please my customers, and some customer likes a particular design feature because it makes the knife an effective murder weapon, that doesn't mean that the feature is motivated by murder.
If you want to please your customers, *knowing* what their motivations are, then the motivations are transitive.
No, my motivations are mine, and their motivations are theirs. I refuse to accept -- and you have no right to claim -- that someone else's motivations become mine. Motivation is a personal phenomenon like intention and emotion. The motivated person is the ultimate authority. Anyway, this is getting quite silly. For me this is a technical issue, not a moral one, and I really don't want to get drawn further into a philisophical discussion of responsibility. I don't care all that much whether the semicolon is included in the macro, and since I am feeling overwhelmed and somewhat attacked I think I'll probably do nothing. But -- sincerely -- thank you anyway for going to the trouble to respond to my query and make your thoughts on the issue clear. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
If you want to please your customers, *knowing* what their motivations are, then the motivations are transitive.
No, my motivations are mine, and their motivations are theirs. I refuse to accept -- and you have no right to claim
I most certainly do.
-- that someone else's motivations become mine. Motivation is a personal phenomenon like intention and emotion. The motivated person is the ultimate authority.
It is for me (or anyone else) to judge and make decisions based on what I believe to be the your or anyone else's motivations. I believe what I said, and you can believe that its an irrelevant philosophical point of view, but is certainly my prerogative to apply and make statements of what I believe.
Anyway, this is getting quite silly. For me this is a technical issue, not a moral one, and I really don't want to get drawn further into a philisophical discussion of responsibility. I don't care all that much whether the semicolon is included in the macro, and since I am feeling overwhelmed and somewhat attacked I think I'll probably do nothing.
You feel attacked?
Ooooooo Kaaaaaay.
I don't find this amusing; I find it insulting--even though it wasn't directed at me.
In other words, everything else in service of wiping out some people's silly misconceptions about what macros are. Have I got that right?
I find this insulting and inflammatory. The last sentence doesn't undo the what I perceive to be the tone of the first.
Ahem.
I find this insulting as well.
I am only becoming more convinced to the contrary.
Given the context of this statement, I find this snide.
So, no spaces anywhere else on the line? Try again. ^^^^^^^^^
Again, I find this insulting, especially because you know full well that it is easily fixable. Of course some policies can be difficult to create; this is not an example of one of those policies and is illustrative of nothing.
But -- sincerely -- thank you anyway for going to the trouble to respond to my query and make your thoughts on the issue clear.
Here I believe that you may be sincere, but mostly that you're trying to smooth the waters. At this point, I just find this to be a placating non-resolution to a personality clash that creeps up time and time again. I could chalk up all of these to misinterpretation, but it has happened so damn often with you that I'm wary of it from the start, and I simply won't believe you if you say it wasn't intentional. So, you feel attacked? That isn't surprising at all, given that comments like these--along with a significant history of comments that I find to be either snide, insulting, inflammatory, condescending, or arrogant--can instantly piss me off. I know that I'm not perfect, and I know that many of things that I say in frustration are less than civil. But with you, it isn't frustration, it's a reaction to this kind of thing happening nearly single every time, and each time I get to the boiling point sooner. I tire of it.

"Paul Mensonides" <pmenso57@comcast.net> writes:
Anyway, this is getting quite silly. For me this is a technical issue, not a moral one, and I really don't want to get drawn further into a philisophical discussion of responsibility. I don't care all that much whether the semicolon is included in the macro, and since I am feeling overwhelmed and somewhat attacked I think I'll probably do nothing.
You feel attacked?
Indeed. Most especially by the message I'm responding to.
Ooooooo Kaaaaaay.
I don't find this amusing; I find it insulting--even though it wasn't directed at me.
I'm really very sorry. I do hope that Lucas understood it as it was intended (bewilderment at how to connect the reply to my question) and was not insulted.
In other words, everything else in service of wiping out some people's silly misconceptions about what macros are. Have I got that right?
I find this insulting and inflammatory. The last sentence doesn't undo the what I perceive to be the tone of the first.
I'm very sorry. It was probably a mistake to use an assert-then-question formulation for what should have been a plain question.
Ahem.
I find this insulting as well.
I'm very sorry that it bothered you. I will remember in the future that you find "ahem" to be insulting and will avoid using it. It certainly was not intended as an insult.
I am only becoming more convinced to the contrary.
Given the context of this statement, I find this snide.
Wow, I'm truly sorry that you thought that was snide. It wasn't intended to convey anything other than the un-embellished content of its words: that my disagreement with the foregoing statement was growing.
So, no spaces anywhere else on the line? Try again. ^^^^^^^^^
Again, I find this insulting, especially because you know full well that it is easily fixable.
Well, y'see: no I don't. That was, in fact, my point.
Of course some policies can be difficult to create; this is not an example of one of those policies
Then it should be fairly easy for you to write the text of a less heavy-handed policy that leaves no room for confusion and is easy to follow.
and is illustrative of nothing.
I understand your opinion. I hope it's clear that I think it does illustrate something.
But -- sincerely -- thank you anyway for going to the trouble to respond to my query and make your thoughts on the issue clear.
Here I believe that you may be sincere, but mostly that you're trying to smooth the waters.
Not that there's anything wrong with smoothing the waters, I hope. I was trying to bring the discussion to a peaceful conclusion, because I'm out of time and, clearly, we're both becoming upset. I don't think it serves either of us or Boost as a whole to continue.
At this point, I just find this to be a placating non-resolution to a personality clash that creeps up time and time again.
In that case, I think we should agree not to engage one another in these forums. There's no reason everyone else should have to suffer because of the way our personalities turned out to interact. What do you say? -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
Not that there's anything wrong with smoothing the waters, I hope.
Not in and of itself, no.
I was trying to bring the discussion to a peaceful conclusion, because I'm out of time and, clearly, we're both becoming upset. I don't think it serves either of us or Boost as a whole to continue.
It doesn't.
At this point, I just find this to be a placating non-resolution to a personality clash that creeps up time and time again.
In that case, I think we should agree not to engage one another in these forums. There's no reason everyone else should have to suffer because of the way our personalities turned out to interact. What do you say?
Fine. Regards, Paul Mensonides

David Abrahams wrote:
FWIW, one of the main reasons I brought this issue up was that I was hoping you'd convince me that the reasons to do it your way were important enough to outweigh the reasons to go the other way.
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion. Right?

"Peter Dimov" <pdimov@mmltd.net> writes:
David Abrahams wrote:
FWIW, one of the main reasons I brought this issue up was that I was hoping you'd convince me that the reasons to do it your way were important enough to outweigh the reasons to go the other way.
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
Right?
I agree; that's the first argument I find truly compelling. All the other ones, including the arguments I started with, seem a bit weak by comparison. Thank you. I am still hesitating though, because the macros in question aren't really an abstraction: the library is designed to be usable without the macros (in case you don't like them or whatever), and the library documents exactly what they generate. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams <dave@boost-consulting.com> writes:
"Peter Dimov" <pdimov@mmltd.net> writes:
David Abrahams wrote:
FWIW, one of the main reasons I brought this issue up was that I was hoping you'd convince me that the reasons to do it your way were important enough to outweigh the reasons to go the other way.
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
Right?
I agree; that's the first argument I find truly compelling. All the other ones, including the arguments I started with, seem a bit weak by comparison.
Thank you.
I am still hesitating though, because the macros in question aren't really an abstraction: the library is designed to be usable without the macros (in case you don't like them or whatever), and the library documents exactly what they generate.
Having given this further thought, I don't think it matters that they're not an a very strong abstraction. It still might make sense to change the library in the future in a way that's compatible with the "normal" usage of the old macro. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Paul Mensonides makes several interesting points "...against just about anything that attempts to make a macro invocation look more like regular code" (his words). I'd like to first take up what I might call the "convenience" argument. Paul writes:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Dave Steffen
As others have pointed out, it's more convenient in many ways,
It's more convenient in exactly one way only: a particular *editor* has trouble properly automatically formatting code. The last thing we should be at all concerned about is automatic formatting in some editor.
I would point out, first, that it probably isn't "a particular" editor, or "some" editor, but probably _most_ or even _all_ editors. I'm a member of the One True Church of Emacs; but I'd bet that those heathens^h^h^h^h^h^h^h fine people in the First Unified Church of vi, or any other even fancier IDE, will have the same problems. I'd also argue that editor convenience is not an unimportant issue. My code editor is what I look at all day. It's probably what most of us look at all day. Auto indentation and syntax highlighting are not necessary for the preservation of life and limb, freedom, justice, and the pursuit of happiness, but they _do_ go a long way to keeping me happy and sane. This is not a definitive argument in favor of syntactically pleasing semicolons; I'll try to make a better argument in another posting. I just wanted to point out that keeping our editors happy will tend to keep Boost users happy, and that it's not a trivial consideration. ---------------------------------------------------------------------- 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)

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Dave Steffen
I would point out, first, that it probably isn't "a particular" editor, or "some" editor, but probably _most_ or even _all_ editors. I'm a member of the One True Church of Emacs; but I'd bet that those heathens^h^h^h^h^h^h^h fine people in the First Unified Church of vi, or any other even fancier IDE, will have the same problems.
So, the solution is to propogate the norm--which, BTW, is responsible for countless macro-related bugs over the years? How about we do it the right way, and have users of Emacs and vi fix their editors formatting algorithms?
I'd also argue that editor convenience is not an unimportant issue. My code editor is what I look at all day. It's probably what most of us look at all day. Auto indentation and syntax highlighting are not necessary for the preservation of life and limb, freedom, justice, and the pursuit of happiness, but they _do_ go a long way to keeping me happy and sane.
It takes very little effort to manually format the code that you write, and any decent C++ programmer should be able to read the code formatted according to another's preferences--without reformatting it. I don't have a problem with tools like these, BTW. I have a problem with altering the purity of a code base when it isn't absolutely necessary. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
It takes very little effort to manually format the code that you write, and any
I agree, but from that point on, you then have to remember to not re-indent a region of code from the editor. Sprinkling such problems throughout code simply adds to the burdon of maintaining code. 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.
decent C++ programmer should be able to read the code formatted according to another's preferences--without reformatting it.
I can read the following code, but it says the wrong thing to anyone who doesn't have familiarity with the internals of the macro. Assuming that SOME_MACRO1 is really a stand-alone statement and has its semicolon provided by the macro: statement1; SOME_MACRO1() // misleading lack of visible semicolon statement2; // (this auto-indented by editor) statement3; This is more than a problem of just indenting statement2. It also gives the impression that SOME_MACRO1's expansion somehow bleeds into statement2. A bad macro written the other extreme: #define SOME_MACRO(X) if(X) int main() { SOME_MACRO2(5); // misleading semicolon statement2; } 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, 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. 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.
I don't have a problem with tools like these, BTW. I have a problem with altering the purity of a code base when it isn't absolutely necessary.
I consider myself somewhat of a language purist, but fail to see how a semicolon affects "purity" in any way. It's a seperator. It seems clear to me how the semicolon's presence (or lack thereof) can confuse maintence programmers, cause code to be formatted in a misleading way, and consequently impress a wrong mental view to people reading the code what is happening, however. -- Chris

Chris Uzdavinis <chris@uzdavinis.com> writes:
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, 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.
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.
I like your guidelines, but I think your language is a little problematic, and might reflect the thinking that Paul objects to. IOW, a macro is not a statement. Instead, a macro expansion might _generate_ a statement. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams <dave@boost-consulting.com> writes:
I like your guidelines, but I think your language is a little problematic, and might reflect the thinking that Paul objects to.
Thanks. Perhaps it does reflect his concern, but that wasn't the intent. I understand the differences, yet do not find them as profoundly important as he does.
IOW, a macro is not a statement. Instead, a macro expansion might _generate_ a statement.
Yes, I could have used better wording, but I was trying to keep the description nice and short. (It was much longer before I pared it down. Maybe I cut too much.) -- Chris

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Chris Uzdavinis
"Paul Mensonides" <pmenso57@comcast.net> writes:
It takes very little effort to manually format the code that you write, and any
I agree, but from that point on, you then have to remember to not re-indent a region of code from the editor.
Which is fairly obvious in nearly all cases. For example: MACRO() int f(...) { ... }
Sprinkling such problems throughout code simply adds to the burdon of maintaining code. 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? 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.
decent C++ programmer should be able to read the code formatted according to another's preferences--without reformatting it.
I can read the following code, but it says the wrong thing to anyone who doesn't have familiarity with the internals of the macro. Assuming that SOME_MACRO1 is really a stand-alone statement and has its semicolon provided by the macro:
statement1; SOME_MACRO1() // misleading lack of visible semicolon statement2; // (this auto-indented by editor) statement3;
This is more than a problem of just indenting statement2. It also gives the impression that SOME_MACRO1's expansion somehow bleeds into statement2.
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. When it affects the design of the macro, that's when I start to have a real problem, because it means that the designer purposely made it that way.
A bad macro written the other extreme:
#define SOME_MACRO(X) if(X)
int main() { SOME_MACRO2(5); // misleading semicolon statement2; }
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. It is a macro that expands to some code. That code might form a complete statement. There is a significant distinction in perspective. That distinction doesn't always manifest itself at a semantic level, but it sometimes does, and that is the root of the problem. When it does, it can create insidious errors that are far more difficult to fix.
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.
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.
I don't have a problem with tools like these, BTW. I have a problem with altering the purity of a code base when it isn't absolutely necessary.
I consider myself somewhat of a language purist, but fail to see how a semicolon affects "purity" in any way. It's a seperator.
It is a separator in the syntax of the underlying language. It is not a separator to the preprocessor.
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. Regards, Paul Mensonides

"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

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Chris Uzdavinis
Which is fairly obvious in nearly all cases. For example:
MACRO()
int f(...) { ... }
To humans, yes. To editors, well, that's a hard problem.
Not if editors can see through macro expansions, but I was referring to re-indenting by hand.
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.
I don't think that is an onerous task to split a line that is too long manually. Also, in addition to reading code, one of the main purposes of indentation is to keep track of where you are when writing code. If you format code as you go along, there is no need to re-indent the buffer. Likewise, removing trailing whitespace can be done without any formatting changes.
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.
This is what plain old block identing is for. You don't need a code formatter to do this.
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.
That's true, but you might be reading it to verify what the generator is doing.
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.
I understand that, and that's what I'm disagreeing with. There is a different degree of indirection that is important.
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.
I totally disagree. In fact, (if you're referring to something like full scale preprocessor metaprogramming) I'd go so far as to say the opposite. In that case, any indistinction is far less of a problem than it is with "standard usages of macros". Preprocessor metaprogramming is so obviously different than normal code that it hardly matters. It is the normal, relatively simple, uses that can cause the most damage.
Then again, there are extremely few people who write macros anywhere near as complicated or ambitious as you do.
And I'm not referring to those kinds of macros either.
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.
Neither adding or nor elliding trailing semicolons makes things simpler to comprehend for the user. I don't think that KISS applies. For the designer of a macro, in many cases making the macro "semicolon-able" makes the macro definition more complex.
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.
Okay. In any case, for nearly all macros, the closing parenthesis of the invocation signals that it doesn't effect trailing code. You have to either be using complex metaprogramming macros, or really bend over backwards to contrive a situation where it doesn't. For a macro to effect trailing code, the trailing code has to be either a parenthetic expression--as in macro(...) (trailing-code) --or it has to have a mismatched right parentheses, such as: macro(...) trailing-code) Off the top of my head, there is no other way that the macro invocation can mess with trailing code.
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?
We can't protect people from laziness or wanton stupidity, nor should we really try.
B) Programmer apathy.
IMO, it isn't worth my time to try to keep people that don't care from screwing things up. In the face of apathy, it doesn't matter what we do.
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?"
My answers are "no" and "it isn't necessary to study macros in detail for most uses of macros." It merely requires a perspective shift when using macros.
Clearly, writing the boost preprocessor library requires a much more strict view of what's going on, and macro purity is a must.
Well, I'm not really referring to this kind of macro use.
But really, how many people in the world could even write the boost preprocessor library?
Probably quite a few now, but certainly less than 1%. I think Aleksey and Dave know enough about it that they could do it if they had sufficient motivation. Plus, there are a variety of people that have given ideas that show that they have the capability or could gain the capability quickly. OTOH, I'd say about one other person could write Chaos, and that's Vesa, though some others would eventually get there.
Heck, how many actually understand it?
In this case, quite a few. If you take away all the workarounds, the library is not that complex. Chaos (which doesn't contain any workarounds) *is* complex.
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.
Despite all this, I haven't been referring to preprocessor metaprogramming at all. Complicated preprocessor metaprogramming requires knowledge and consistancy across a whole slew of issues, and strictness to those principles is a must. But those principles are different than the one I'm referring to here. To preprocessor metaprogramming (as in authoring preprocessor metaprogramming constructs) this one doesn't even come up because you're never really dealing with anything as concrete as specific underlying language syntax. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> writes:
To humans, yes. To editors, well, that's a hard problem.
Not if editors can see through macro expansions, but I was referring to re-indenting by hand.
True, but that would require an editor to also be a project manager, or at least to be able to parse and understand (correctly) a makefile. Otherwise, it wouldn't know what preprocessor macros are defined or not from the command line, wouldn't know include paths, etc. That is hard enough to implement, but even harder to get fast enough to be acceptible.
I don't think that is an onerous task to split a line that is too long manually.
Well, I was thinking that if a variable name gets longer, it would likely be changed in all places it's used, and for that a search/replace may be applied. Then a followup indentation might be more convenient.
Also, in addition to reading code, one of the main purposes of indentation is to keep track of where you are when writing code. If you format code as you go along, there is no need to re-indent the buffer.
That's assuming no automated editing techniques are being used (editor macros, search/replace, IDE functionality to auto-refactor code into its own function, etc.)
Likewise, removing trailing whitespace can be done without any formatting changes.
True, but re-indenting is a convenient way to get all this done at once en masse, if you so prefer. (Well, it seems you don't prefer, but I do.)
This is what plain old block identing is for. You don't need a code formatter to do this.
It may make lines too long, and so you may wish to split a line, etc.
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.
That's true, but you might be reading it to verify what the generator is doing.
You're right. I've written a few code generators and spent a lot of time making them format generated code cleanly, for precisely that reason. It also makes it easier to figure out precisely what's going on or how to use the code if you sometimes take a peek.
By using the word "logically", I meant that "X becomes Y" can quite reasonably be described as being Y.
I understand that, and that's what I'm disagreeing with. There is a different degree of indirection that is important.
Ok, I'm willing to listen and try to be open minded. What is it that I'm missing? Please consider this simple example: void log(char const * msg, char const * file, int lineno); #define LOG(X) log((X), __FILE, __LINE__) I have a few questions for you because I am kind of stubborn but if I feel convinced I'm wrong I'm willing to change. 1) Do you think that the LOG() macro should contain a trailing semicolon? 2) I'm pretty sure you'll say #1, but which of the following examples do you prefer? int foo() { LOG("NO SEMICOLON HERE?") // 1 stuff(); LOG("OR does this seem better?"); // 2 more_stuff(); } 3) Do you see harm if the macro does not contain the trailing semicolon? If so, what harm is it? Specifically, how does usage #2 above re-enforce bad understanding of macros? (Or am I misconstruing the nature of your objection?) 4) What is the important degree of indirection that I would be missing by talking about the usage of the LOG macro as a call to the log function? I understand that I could call it "a macro that expands to a call to the log function" but I don't think that anyone would be more enlightened by that. Other than being more detailed about what's really happening, it's not clear to me what important mistake is being made that bothers you. If our coding convention states that macros are uppercase, then we already know it's a macro, so simply repeating that is unnecessary, IMHO.
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.
I totally disagree. In fact, (if you're referring to something like full scale preprocessor metaprogramming) I'd go so far as to say the opposite. In that case, any indistinction is far less of a problem than it is with "standard usages of macros". Preprocessor metaprogramming is so obviously different than normal code that it hardly matters. It is the normal, relatively simple, uses that can cause the most damage.
Could you apply this to my LOG macro above, to put it into a concrete example of what's so bad? ... (snip a lot of interesting commentary) ... -- Chris

Chris Uzdavinis wrote:
Chris Uzdavinis <chris@uzdavinis.com> writes:
Please consider this simple example: ... #define LOG(X) log((X), __FILE, __LINE__)
Oops. The typo on __FILE was an accident, and I hope it won't be a distraction from the example I was trying to make.
This is not a namespace-level macro. It expands to an expression. An expression macro must not contain a trailing semicolon because it can be used in contexts where a semicolon is illegal: static int dummy = LOG(something), 1;

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Chris Uzdavinis
Not if editors can see through macro expansions, but I was referring to re-indenting by hand.
True, but that would require an editor to also be a project manager, or at least to be able to parse and understand (correctly) a makefile.
Basically it would have to be given a set of #include paths and a set of predefined macros. For this purpose, it needs nothing more than that, but also nothing less.
Otherwise, it wouldn't know what preprocessor macros are defined or not from the command line, wouldn't know include paths, etc. That is hard enough to implement, but even harder to get fast enough to be acceptible.
I don't think that last is necessarily true. Preprocessors can be quite fast, even with complex metaprogramming somewhere in an included header. It also doesn't have to do it constantly.
I don't think that is an onerous task to split a line that is too long manually.
Well, I was thinking that if a variable name gets longer, it would likely be changed in all places it's used, and for that a search/replace may be applied. Then a followup indentation might be more convenient.
I agree that it is more convenient (provided that it does what you want), but I don't think its terribly hard to format code by hand as you go along--even in the face of maintenance like you're referring to above.
True, but re-indenting is a convenient way to get all this done at once en masse, if you so prefer. (Well, it seems you don't prefer, but I do.)
I don't prefer it because I haven't seen a editor that can do a good enough job with code that I write--lack of macro expansion being one of the major reasons.
That's true, but you might be reading it to verify what the generator is doing.
You're right. I've written a few code generators and spent a lot of time making them format generated code cleanly, for precisely that reason. It also makes it easier to figure out precisely what's going on or how to use the code if you sometimes take a peek.
Yes, but in this case, the formatting doesn't have to be perfect.
By using the word "logically", I meant that "X becomes Y" can quite reasonably be described as being Y.
I understand that, and that's what I'm disagreeing with. There is a different degree of indirection that is important.
Ok, I'm willing to listen and try to be open minded. What is it that I'm missing? Please consider this simple example:
void log(char const * msg, char const * file, int lineno);
#define LOG(X) log((X), __FILE, __LINE__)
I have a few questions for you because I am kind of stubborn but if I feel convinced I'm wrong I'm willing to change.
1) Do you think that the LOG() macro should contain a trailing semicolon?
No, unless it is supposed to be expand to an entire statement. That could well be the case, however, because of sequence points.
2) I'm pretty sure you'll say #1, but which of the following examples do you prefer?
int foo() { LOG("NO SEMICOLON HERE?") // 1 stuff();
LOG("OR does this seem better?"); // 2 more_stuff(); }
The first one, because I see the second one having an unnatural syntax that is alien to the preprocessor. I.e. it is an attempted interleaving between the syntax of the preprocessor and the syntax of the underlying language. More fundamentally, I see preprocessing as a top-to-bottom execution path that writes the source code of a program. I don't see something like... int foo() { f(); MACRO(); // with or without the semicolon // --doesn't matter for the point I'm making g(); } ...as calling 'f', then doing whatever 'MACRO' does, then calling 'g'. I see the preprocessor effect as a separate transformation that includes *all* of the source code, and results in *all* of the transformed source code. In other words, in the above, I see all of the above translated to... int foo() { f(); h(); // or whatever g(); } ...and then I look at what it does at runtime (or compile-time after preprocessing). As an example, this is a bit of code that I wrote recently for an arbitrary-precision natural class I needed. It is using a Duff's Device (slightly modified because there is no zero-iterations case): template<class T, T radix> bool operator<(natural<T, radix> x, natural<T, radix> y) { unsigned long a = x.size(), b = y.size(); if (a == b) { typename natural<T, radix>::const_iterator i = x.begin(), j = y.begin(); unsigned long n = (a + 7) / 8; #define _ \ if (*i != *j) { \ return *i < *j; \ } \ ++i, ++j; \ /**/ switch (a % 8) { case 0: do { _ case 7: _ case 6: _ case 5: _ case 4: _ case 3: _ case 2: _ case 1: _ } while (--n); } #undef _ return false; } else { return a < b; } } Now, when I look at this, I don't see the macro '_' as a statement (or a placeholder for a statement), I see it as a substitution for a common token pattern to be placed where ever I need to put it. I.e. its a shorthand for me writing it eight times and making the Duff's Device less explicit. My perspective is entirely that this substitution takes place before the underlying syntax even exists, which is the only way that the perception can be the generalized across all possible macros. Say that I decide that I want to generalize the entire Duff's Device itself--it is, after all, a pattern of code, and then apply it here. In that case, macros would write the entire thing, and it gets further and further away from something that can be viewed as a syntactic entity of the underlying language. The thing is, I don't see a difference between the first way and the second way as far as macros are concerned. I.e. macros are pure code generators, nothing more and nothing less, from the simplest cases to the most complex. This may be a bad example, and I'm probably not explaining my point of view clearly at all. I guess my point of view fundamentally revolves around my conception of macros being totally distinct from the underlying language, in terms of how they work, what that work is, and _when_ they do it.
3) Do you see harm if the macro does not contain the trailing semicolon? If so, what harm is it? Specifically, how does usage #2 above re-enforce bad understanding of macros? (Or am I misconstruing the nature of your objection?)
It isn't a misunderstanding of macros per se, it's a perspective difference. The unit of work that macros perform is some code generation. The unit of work that a function call does is a runtime effect. (Likewise, the unit of work that a structure declaration does is on, for example, the symbol table.) I.e. the difference between 'max' and 'MAX' isn't multiple evaluation, it's that 'max' returns the greater of its arguments while 'MAX' returns some parametized code. I don't think there's a misunderstanding that the macro is doing a token substitution, but I think that many people view them as "doing the same thing for all intensive purposes". This merging between different types of work is what leads to subtle errors. Obviously, 'max' is a old-hat example, but is one that should never have been an issue because people never should have mentally merged two distinct types of work. Most other macro-related problems stem from this kind of blurring. So, the harm that it does is to purposely help maintain that illusion.
4) What is the important degree of indirection that I would be missing by talking about the usage of the LOG macro as a call to the log function? I understand that I could call it "a macro that expands to a call to the log function" but I don't think that anyone would be more enlightened by that. Other than being more detailed about what's really happening, it's not clear to me what important mistake is being made that bothers you.
The mistake isn't necessarily in this particular example, its in the mentality that it fosters which leads to problems in less simplistic scenarios.
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.
I totally disagree. In fact, (if you're referring to something like full scale preprocessor metaprogramming) I'd go so far as to say the opposite. In that case, any indistinction is far less of a problem than it is with "standard usages of macros". Preprocessor metaprogramming is so obviously different than normal code that it hardly matters. It is the normal, relatively simple, uses that can cause the most damage.
Could you apply this to my LOG macro above, to put it into a concrete example of what's so bad?
As above, it isn't this in isolation. If the effect was only on how this macro is defined and how it is used correctly, it hardly matters. It is more like the broader scenario of how macros in general are defined and how they are used correctly. I.e. there is a universal way that macros behave that is a property of all macros, rather than "this macro has these properties" and "this macro has these properties". When you blur the distinction between macros and underlying language elements, you start getting issues like "this macro is like a function call except x, y, and z". It is starting with the wrong thing and adding caveats to it, rather than starting with the right thing and adding allowances to it. Regards, Paul Mensonides

From: "Paul Mensonides" <pmenso57@comcast.net>
I don't think there's a misunderstanding that the macro is doing a token substitution, but I think that many people view them as "doing the same thing for all intensive purposes". This merging between different types of work is
In case you care, s/intensive/intents and/. I saw you write this a couple of times and thought it might be a real misunderstanding rather than a late night/tired/frustrated/whatever mistake. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
I don't think there's a misunderstanding that the macro is doing a token substitution, but I think that many people view them as "doing the same thing for all intensive purposes". This merging between different types of work is
In case you care, s/intensive/intents and/. I saw you write this a couple of times and thought it might be a real misunderstanding rather than a late night/tired/frustrated/whatever mistake.
I meant "for all intents and purposes". Thanks for pointing it out, it didn't seem right when I wrote it, but I was in a hurry, and it was about 3:00 AM. Regards, Paul Mensonides

On Fri, 15 Jul 2005 02:31:54 -0700 "Paul Mensonides" <pmenso57@comcast.net> wrote:
So, the solution is to propogate the norm--which, BTW, is responsible for countless macro-related bugs over the years? How about we do it the right way, and have users of Emacs and vi fix their editors formatting algorithms?
More important than an editor is the writer and 1maintainer of the code. If something is supposed to expand to a complete statement, then it should require a semicolon, because that is the normal protocol for statements. If the macro does not expand to a full statement then it should not require the semicolon... something else will follow anyway. This provides editors and people with a good idea of a high level understanding of what kind of code is being generated by the macro.
It takes very little effort to manually format the code that you write, and any decent C++ programmer should be able to read the code formatted according to another's preferences--without reformatting it. I don't have a problem with tools like these, BTW. I have a problem with altering the purity of a code base when it isn't absolutely necessary.
However, you are advocating the same thing, but on the other side. From my reading of your posts, you are advocating no semicolon at all, because having one may propogate certain beliefs and ideas about preprocessor programming. I think a better alternative is a model of practice which states when one should be used and when one should not be used. Neither extreme is valid (always require, always forbid).

Much like Jody Hagins, I think, I agree with all of your points, except that I place great value on automatic indentation and formatting, and a even a single macro invocation that the editor cannot indent properly makes the automatic indentation largely useless for the file. The most obvious way for these tools to properly handle macro invocations is for them to know to what the macro will expand. But this requires that the tool parse all of the necessary macro definitions. The necessary macro definitions include all those defined in the file on which the tool is operating as well as all those defined on files included by the file on which the tool is operating. Finding these definitions alone would require that the tool do a very significant amount of work, which would well take more time than users of the tool would like to wait. There is also the problem that some of the files that the tool needs to read may have syntax errors, and even in this case it is important that the tool can still format the code, particularly code that is far away from the syntax error, reasonably well. Furthermore, this necessary set of macro definitions may also include macros defined in other files that are not included by the file that is being formatted (but will eventually be read by the preprocessor before it sees the contents of the file being formatted), or even macros that have not yet been written. Clearly this approach is not feasible. The current solution is for the macro invocation itself to provide sufficient information, in the form of the absence or presence of a semicolon, for the tool to properly format the code. An alternative, which avoids the pitfalls of using a semicolon for this purpose, is for the macro name itself to include the necessary information, by conforming to some convention. It is probably sufficient to distinguish between only two types of macros: 1. ones that produce compete declarations and/or statement 2. ones that do not produce complete declarations or statements, and therefore must be used as a part of some other statement or declaration One possible convention would be to suffix with an underscore the names of macros that are in the first category. With the assumption that macros have uppercase names, automatic formatting tools could easily be modified to identify macro invocations and indent them appropriately. -- Jeremy Maitin-Shepard

Dave Steffen wrote:
I would point out, first, that it probably isn't "a particular" editor, or "some" editor, but probably _most_ or even _all_ editors. I'm a member of the One True Church of Emacs; but I'd bet that those heathens^h^h^h^h^h^h^h fine people in the First Unified Church of vi, or any other even fancier IDE, will have the same problems.
There it is again, propaganda. Everybody knows there is _no_ fancier IDE than vi ;-).
I'd also argue that editor convenience is not an unimportant issue. My code editor is what I look at all day. It's probably what most of us look at all day. Auto indentation and syntax highlighting are not necessary for the preservation of life and limb, freedom, justice, and the pursuit of happiness, but they _do_ go a long way to keeping me happy and sane.
AFAICS the point this discussion revolves around is not whether somebody is wrong or right it's all about how we value these arguments in everyday life. While I think that on a technical basis Paul is right, I value automatic code indentation much higher than all the arguments in favour of not requiring the semicolon. Yes it is more pure but in my experience it causes way more trouble in practice then it does any good by educating programmers about the nature of macros. And yes it is sad to tailor your coding style to arguably insufficient tools but at the end of day there is no perfect tool and we need to get a job done in the best possible way given the circumstances. As a sidenote I kind of doubt that making there usage looking syntactically diffferent from function calls will educate users about the way they work. To me doing away with the usual "macros are evil" attitude" sounds like a lot more promising approach to me. Thomas

From: Thomas Witt <witt@acm.org>
AFAICS the point this discussion revolves around is not whether somebody is wrong or right it's all about how we value these arguments in everyday life.
That sounds right.
While I think that on a technical basis Paul is right, I value automatic code indentation much higher than all the arguments in favour of not requiring the semicolon. Yes it is more pure but in my experience it causes way more trouble in practice then it does any good by educating programmers about the nature of macros. And yes it is sad to tailor your coding style to arguably insufficient tools but at the end of day there is no perfect tool and we need to get a job done in the best possible way given the circumstances.
As a sidenote I kind of doubt that making there usage looking syntactically diffferent from function calls will educate users about the way they work. To me doing away with the usual "macros are evil" attitude" sounds like a lot more promising approach to me.
I was thinking similarly. First, Paul contends you can fix code indenters, but how? Really, when an editor sees a line that has no statement ending token, it has to assume it continues the previous line. After all, whitespace can appear throughout C++ code. I see no way for an indenter to "Do the Right Thing(TM)" in this case. Second, adding or omitting a semicolon will *not* change a programmer's understanding of the preprocessor. I know many programmers who will simply add a semicolon or not as the compiler and indenter dicate. They won't give it any more thought than that. Thus, requiring that all macros be complete entities that *never* require semicolons is a purist position that offers only consistency, but at what cost? Code will be indented oddly, which can lead to misinterpretation, and habit will constantly interfere. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
As a sidenote I kind of doubt that making there usage looking syntactically diffferent from function calls will educate users about the way they work. To me doing away with the usual "macros are evil" attitude" sounds like a lot more promising approach to me.
I was thinking similarly.
First, Paul contends you can fix code indenters, but how? Really, when an editor sees a line that has no statement ending token, it has to assume it continues the previous line.
Any kind of tool that does analysis on C or C++ code, even if only at a syntactic level, has to be able to see through macro expansion. This is a result of the syntax not being static. I.e. the syntax is not represented by the source code, but is derived from the source code by a preprocessor.
After all, whitespace can appear throughout C++ code. I see no way for an indenter to "Do the Right Thing(TM)" in this case.
It has to be able to do macro expansion, it's that simple. Whether or not that easy to integrate is another story, but it isn't impossible. Anything less just means it is an robust, but generic, editor, rather than a robust C++ editor.
Second, adding or omitting a semicolon will *not* change a programmer's understanding of the preprocessor. I know many programmers who will simply add a semicolon or not as the compiler and indenter dicate. They won't give it any more thought than that.
I have a serious problem catering to people that don't care also. I don't have a problem with making them work a little as a result of the apathy. Regards, Paul Mensonides

From: "Paul Mensonides" <pmenso57@comcast.net>
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
First, Paul contends you can fix code indenters, but how? Really, when an editor sees a line that has no statement ending token, it has to assume it continues the previous line.
Any kind of tool that does analysis on C or C++ code, even if only at a syntactic level, has to be able to see through macro expansion. This is a
Nope. See below.
result of the syntax not being static. I.e. the syntax is not represented by the source code, but is derived from the source code by a preprocessor.
After all, whitespace can appear throughout C++ code. I see no way for an indenter to "Do the Right Thing(TM)" in this case.
It has to be able to do macro expansion, it's that simple. Whether or not that easy to integrate is another story, but it isn't impossible. Anything less just means it is an robust, but generic, editor, rather than a robust C++ editor.
It is impossible. There is no way for an editor to know the manifest constants, predefined or otherwise, on which the preprocessor will act to determine which code will be in effect when compiling. Thus, the editor cannot determine the definition of the macro with any accuracy or consistency, so it cannot ascertain the syntactic effect of the macro invocation. There are but two choices for the editor: ignore the macro invocation and indent based upon the code preceding it, or treat the macro as an expression and not a statement. Well, I suppose there's a third choice, but that entails keeping a database of user overrides. However, that is untenable as changes introduced into a VCS can completely disconnect the override data from the text of the file. Thus, by your definition, there cannot be a "robust C++ editor" unless we eliminate the preprocessor.
Second, adding or omitting a semicolon will *not* change a programmer's understanding of the preprocessor. I know many programmers who will simply add a semicolon or not as the compiler and indenter dicate. They won't give it any more thought than that.
I have a serious problem catering to people that don't care also. I don't have a problem with making them work a little as a result of the apathy.
Life's tough that way sometimes. Seriously, absolute purity in any endeavor usually serves no goal but to alienate most. This case isn't that extreme, I'll grant. However, with sufficient annoyance, one can turn away large numbers of C++ programmers generally, and Boost users specifically. Having said all of that, I find the following compelling: From: "Peter Dimov" <pdimov@mmltd.net>
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
I have, in fact, seen situations where this arose. One has to visit many files to remove trailing semicolons if one uses a compiler that complains about the extras. On that basis, I am convinced that semicolons should be kept within the macro. Indeed, I plan to follow that approach in my own code henceforth, despite the formatting trouble it will cause. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
Having said all of that, I find the following compelling:
From: "Peter Dimov" <pdimov@mmltd.net>
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
I have, in fact, seen situations where this arose. One has to visit many files to remove trailing semicolons if one uses a compiler that complains about the extras.
On that basis, I am convinced that semicolons should be kept within the macro. Indeed, I plan to follow that approach in my own code henceforth, despite the formatting trouble it will cause.
It doesn't seem untenable to suggest having editor indentation logic special-case a commented-out semicolon to be treated as a real semicolon. The code colorizer could even color the comment the same way as it colors a real semicolon, too. statement(); MACRO() //; statement2(); Hmm. -- Chris

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
Any kind of tool that does analysis on C or C++ code, even if only at a syntactic level, has to be able to see through macro expansion. This is a
Nope. See below.
Anything less just means it is an robust, but generic, editor, rather than a robust C++ editor.
It is impossible. There is no way for an editor to know the manifest constants, predefined or otherwise, on which the preprocessor will act to determine which code will be in effect when compiling. Thus, the editor cannot determine the definition of the macro with any accuracy or consistency, so it cannot ascertain the syntactic effect of the macro invocation.
The editor can't automatically determine command line arguments or macros predefined by the compiler (or compiler) to be used, that's true. Those would have to be supplied, but the rest can be done. Some environments already do it with varying degrees of success for other reasons. I have seen it done where it is fast enough. I've yet to see it done where it was good enough though, but I do think it's possible.
There are but two choices for the editor: ignore the macro invocation and indent based upon the code preceding it, or treat the macro as an expression and not a statement. Well, I suppose there's a third choice, but that entails keeping a database of user overrides. However, that is untenable as changes introduced into a VCS can completely disconnect the override data from the text of the file.
The third option is to use an explicit workaround in the code that uses the macro.
Thus, by your definition, there cannot be a "robust C++ editor" unless we eliminate the preprocessor.
No, there can be, it's just that some of it has to come from a configuration file.
I have a serious problem catering to people that don't care also. I don't have a problem with making them work a little as a result of the apathy.
Life's tough that way sometimes. Seriously, absolute purity in any endeavor usually serves no goal but to alienate most.
This is a case where purity, in this small way, can be achieved without breaking code on a bunch of compilers. The syntax of C or C++ is dynamic, because of the preprocessor, and that's just the way it is. An editor that cannot handle that is deficient when macros come into play. Such editors may or may not be worth fixing, but as they are now, that is a deficiency. This deficiency can be worked around in two places: 1) in the library, thus subjecting all users regardless of the editor they use to the workaround, or 2) in the user code (or a user library) of those users that use these particular editors. I don't have a problem with workarounds--well, I do, but I realize that they are a necessary evil--but I do have a potential problem with the location of some workarounds and how explicit (or not) that they are.
This case isn't that extreme, I'll grant. However, with sufficient annoyance, one can turn away large numbers of C++ programmers generally, and Boost users specifically.
I find it unlikely that this particular thing would be the one thing to tip the balance away from someone using Boost, and I think you'd agree with that. Otherwise, I agree with what you're saying here, but the tradeoff isn't worth it. I don't have a problem with Boost providing the tools to apply the workaround (i.e. BOOST_SEMICOLON) locally. I don't even have a problem with Boost headers that define the types of macros we're talking about here #include'ing that definition--just to make it as easy as possible for the user to apply it. The main difference is that the library source contains the pure form, and any workarounds are explicit.
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
I have, in fact, seen situations where this arose. One has to visit many files to remove trailing semicolons if one uses a compiler that complains about the extras.
On that basis, I am convinced that semicolons should be kept within the macro. Indeed, I plan to follow that approach in my own code henceforth, despite the formatting trouble it will cause.
To be the devil's advocate, it isn't very hard to keep a "namespace-scope macro" requiring a semicolon in the face of change, if being able to add a semicolon is a priority for you. Regards, Paul Mensonides

From: "Paul Mensonides" <pmenso57@comcast.net>
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
It is impossible. There is no way for an editor to know the manifest constants, predefined or otherwise, on which the preprocessor will act to determine which code will be in effect when compiling. Thus, the editor cannot determine the definition of the macro with any accuracy or consistency, so it cannot ascertain the syntactic effect of the macro invocation.
The editor can't automatically determine command line arguments or macros predefined by the compiler (or compiler) to be used, that's true. Those would have to be supplied, but the rest can be done. Some environments already do it with varying degrees of success for other reasons. I have seen it done where it is fast enough. I've yet to see it done where it was good enough though, but I do think it's possible.
The predefined manifest constants can be described in a configuration file, but the command line arguments, which are often generated from a variety of tools (make files, IDEs, etc.), would be fragile at best. IOW, you could start with none, then have your build system generate a file with everything defined on the command line--per source file--and your editor could be on the lookout for changes to that file. Unfortunately, that would mean that automatic formatting would change over time and the coupling among build system and editor is very tight. That doesn't seem viable.
There are but two choices for the editor: ignore the macro invocation and indent based upon the code preceding it, or treat the macro as an expression and not a statement. Well, I suppose there's a third choice, but that entails keeping a database of user overrides. However, that is untenable as changes introduced into a VCS can completely disconnect the override data from the text of the file.
The third option is to use an explicit workaround in the code that uses the macro.
Right. A special comment token has been suggested. That would work, but it would require changes to the formatting code.
This case isn't that extreme, I'll grant. However, with sufficient annoyance, one can turn away large numbers of C++ programmers generally, and Boost users specifically.
I find it unlikely that this particular thing would be the one thing to tip the balance away from someone using Boost, and I think you'd agree with that.
Yes.
Otherwise, I agree with what you're saying here, but the tradeoff isn't worth it. I don't have a problem with Boost providing the tools to apply the workaround (i.e. BOOST_SEMICOLON) locally. I don't even have a problem with Boost headers that define the types of macros we're talking about here #include'ing that definition--just to make it as easy as possible for the user to apply it. The main difference is that the library source contains the pure form, and any workarounds are explicit.
I think that's a reasonable approach. BOOST_SEMICOLON does seem like a workable solution. It satisfies the need for a semicolon where one is needed to keep editors happy and it keeps the semicolon in/out issue away from all other macros.
If you let people add a semicolon after the macro, how can you change the macro later in a way that doesn't tolerate a trailing semicolon? The expansion of the macro is an implementation detail; the interface shouldn't depend on a particular expansion.
I have, in fact, seen situations where this arose. One has to visit many files to remove trailing semicolons if one uses a compiler that complains about the extras.
On that basis, I am convinced that semicolons should be kept within the macro. Indeed, I plan to follow that approach in my own code henceforth, despite the formatting trouble it will cause.
To be the devil's advocate, it isn't very hard to keep a "namespace-scope macro" requiring a semicolon in the face of change, if being able to add a semicolon is a priority for you.
I suppose you're right, but that just adds ugliness to a macro in order to make it so that clients can continue to add a semicolon. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Rob Stewart
From: "Paul Mensonides" <pmenso57@comcast.net>
The predefined manifest constants can be described in a configuration file, but the command line arguments, which are often generated from a variety of tools (make files, IDEs, etc.), would be fragile at best. IOW, you could start with none, then have your build system generate a file with everything defined on the command line--per source file--and your editor could be on the lookout for changes to that file. Unfortunately, that would mean that automatic formatting would change over time and the coupling among build system and editor is very tight. That doesn't seem viable.
Note that the formatting would only change if a macro definition expanded into a significantly different syntactic entity based on the definition of another macro. In that case, the source code at the point of use is saying two (or more) different things syntactically, and formatting would be inherently ambiguous. #if CONSTANT #define MACRO 1 #else #define MACRO 2 #endif In either case, it doesn't really matter what the value of 'CONSTANT' is, because it doesn't change the external syntactic effect of 'MACRO' which is likely to be the scenario in nearly all cases. BTW, I realize that this is not a simple problem for an editor, but I still think that it can be done reasonably well for the purposes of formatting code.
Otherwise, I agree with what you're saying here, but the tradeoff isn't worth it. I don't have a problem with Boost providing the tools to apply the workaround (i.e. BOOST_SEMICOLON) locally. I don't even have a problem with Boost headers that define the types of macros we're talking about here #include'ing that definition--just to make it as easy as possible for the user to apply it. The main difference is that the library source contains the pure form, and any workarounds are explicit.
I think that's a reasonable approach. BOOST_SEMICOLON does seem like a workable solution. It satisfies the need for a semicolon where one is needed to keep editors happy and it keeps the semicolon in/out issue away from all other macros.
Well, here's a BOOST_SEMICOLON definition, in case anyone is interested (no #include-guard required): // <boost/semicolon.hpp> namespace boost { namespace empty { } } #define BOOST_SEMICOLON \ using namespace ::boost::empty \ /**/ It doesn't introduce any names into the scope where it is used, and it can be used any number of times in the same scope. It can be used at namespace and function scope, though it is not necessary at function scope. It *can't* be used in class scope, but it isn't necessary there either. Regards, Paul Mensonides

Hey Folks, Coming back to this topic after several months... Paul Mensonides writes:
Well, here's a BOOST_SEMICOLON definition, in case anyone is interested (no #include-guard required):
// <boost/semicolon.hpp>
namespace boost { namespace empty { } }
#define BOOST_SEMICOLON \ using namespace ::boost::empty \ /**/
It doesn't introduce any names into the scope where it is used, and it can be used any number of times in the same scope. It can be used at namespace and function scope, though it is not necessary at function scope. It *can't* be used in class scope, but it isn't necessary there either.
It turns out that, in some places where we've got heavy macro programming going on, this didn't work; I kept getting "expected nested-name-specifier before 'namespace' " sorts of errors. It turns out that #define BOOST_SEMICOLON typedef int semicolon_allowed_after_this makes GCC 3.4 happier; I don't understand the grammar issues involved. ... just a report from the trenches. :-) ------------------------------------------------------------------------ Dave Steffen, Ph.D. On a paper submitted by a physicist colleague: Software Engineer IV Numerica Corporation "This isn't right. This isn't even wrong." ph (970) 419-8343 x27 fax (970) 223-6797 -- Wolfgang Pauli dgsteffen@numerica.us

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thomas Witt Sent: Friday, July 15, 2005 8:59 AM To: boost@lists.boost.org Subject: Re: [boost] Macros at namespace scope: trailing semicolon?
Dave Steffen wrote:
I would point out, first, that it probably isn't "a particular" editor, or "some" editor, but probably _most_ or even _all_ editors. I'm a member of the One True Church of Emacs; but I'd bet
that those
heathens^h^h^h^h^h^h^h fine people in the First Unified Church of vi, or any other even fancier IDE, will have the same problems.
There it is again, propaganda. Everybody knows there is _no_ fancier IDE than vi ;-).
Well, I guess I don't belong to any Church then, because I'd rather use a simple plain text editor than either one precisely because they are both underpowered without significant customization by me which would require more of my time than just formatting by hand.
I'd also argue that editor convenience is not an unimportant issue. My code editor is what I look at all day. It's probably what most of us look at all day. Auto indentation and syntax highlighting are not necessary for the preservation of life and limb, freedom, justice, and the pursuit of happiness, but they _do_ go a long way to keeping me happy and sane.
AFAICS the point this discussion revolves around is not whether somebody is wrong or right it's all about how we value these arguments in everyday life.
While I think that on a technical basis Paul is right, I value automatic code indentation much higher than all the arguments in favour of not requiring the semicolon.
But I don't. You can define another macro that that encapsulates the macro and allows you to put the semicolon--a workaround for the editor. I can also write another macro, but in my case, it's a de-workaround. I have to live with the lack of purity that exists because a particular editor that I don't use has trouble automatically formatting it. To me, that's a showstopper, I'd design my own library to solve the problem before reusing the library--even though that might take me a significant amount of time.
As a sidenote I kind of doubt that making there usage looking syntactically diffferent from function calls will educate users about the way they work. To me doing away with the usual "macros are evil" attitude" sounds like a lot more promising approach to me.
You can't do away with that attitude without addressing where the attitude comes from. This is one of those places that derives the attitude. Regards, Paul Mensonides

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)

Dave Steffen <dgsteffen@numerica.us> writes:
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 ... }
Precisely speaking, see http://wwww.boost-consulting.com/boost/libs/parameter/test/basics.hpp http://wwww.boost-consulting.com/boost/boost/parameter/keyword.hpp
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.
I guess it depends whether you consider the preprocessor to be part of C++ :-) -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
I also agree that macros are not part of the C++ syntax model at all. No question.
I guess it depends whether you consider the preprocessor to be part of C++ :-)
Well, the preprocessor has it's own syntax, which is distinct from the underlying language syntax. Both are syntaxes (sp?) of C++, but I said the "C++ syntax model" I was referring to the latter. One of the dinstinctly interesting parts about the preprocessor's syntax is that it isn't static. It is dynamically created during evaluation. I.e. it cannot be constructed into an AST from source and then evaluated later. Regards, Paul Mensonides

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Dave Steffen
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. :-) :-)
I disagree with just about all of this except the first two sentences. There is nothing wrong with macros. There is something wrong with trying to make macros look like non-macros.
They're so unpleasant that Bjarne "Our Founder" Stroustrup has always encouraged minimizing the use of the preprocessor,
And Bjarne is wrong, IMO. How much the preprocessor should be used is entirely dictated by whether preprocessor use is a better solution than the alternatives. It isn't even a case of "last resort".
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 would be a terrible thing. Having a standard source code manipulation tool that is above the syntax of the language is incredibly useful.
I would claim that while macros are indeed aliens that sometimes display unpleasant behavior (e.g. unreadable error messages when misused),
Trivially fixed by preprocessing in a separate pass--which is something you can't do with templates.
one _can_ assign some sort of C++ syntactic meaning to their use.
But we shouldn't. We should assign syntactic meaning to what they result in. FOREACH is not a looping construct. It is a looping construct *writer*, and that is exactly how it should be viewed. The point being, what a macro expands to should always be a fundamental part of the interface of a macro. The "return value" of a macro is code.
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.
This is an example of where it is necessary, or, at least, superior to do so. Not because of the resulting syntax, but because of the caveats in the syntax if it was the other way (e.g. you'd have to encode open commas).
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.
I couldn't disagree with this mentality more. A macro should *never* be designed to "fit into some syntactic C++ context". It may be defined to fit into some C++ _semantic_ context, but only the result of a macro should be defined to fit into a syntactic context. The concept of macros as an underlying C++ syntactic construct is pure evil.
BOOST_PARAMETER_KEYWORD(tag_namespace, name) should mandate a semicolon, just as function declarations and class definitions do.
Function definitions don't, and not all member functions should be implicitly marked as inline by being defined inside a class definition.
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.
No, they sit side-by-side, create, and interleave 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 have a problem with several prevailing viewpoints. One of them is that macros are evil. The reason that this is a prevailing viewpoint is precisely because people keep trying to make them fit into the syntax model, instead viewing them as a separate syntax model that is overlaid. Nearly all macro-related problems stem from this attempted facade.
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.
It isn't arbitrary. Some things are written in the language understood by the preprocessor. All constructs written in that language should be assumed by users *not* to fit into the C++ grammar.
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?
That is what documentation is for, which is no different than any other construct. The syntax of a function call (a real function call) says almost nothing about how the function can be used and what it does. It only shows how a function call can be syntactically formed. The rest is the semantic effect of the function. With a macro, what the invocation results in is the semantic effect of the macro--which should be documented if the macro is an interface. I.e. the semantic effect of a macro *is* the syntactic effect on the program, and it should be documented from that viewpoint. The semantic intention of the resulting code should also be documented (obviously). Regards, Paul Mensonides

"David Abrahams" <dave@boost-consulting.com> wrote
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
We have a similar problem in typeof, and at this point semicolon is not required. This leads to all the problems with the editor that you mentioned, and, if the user does supply the (second) semicolon, some compilers emit warnings, so I am by no means happy with the situation. However, if the semicolon is required, and the user doesn't supply it, the compiler will produce an error message, which will expose implementation details of this macro, and most likely be of little help. So, the choice is actually between two evels, and I am not really sure which one is less evel. Also, I think, this problem is very generic, and once it's decided which style is prefferrable, it may be a good idea to turn it into a guideline, so that it is consistent between the Boost libraries. Regards, Arkadiy

Arkadiy Vertleyb wrote:
Also, I think, this problem is very generic, and once it's decided which style is prefferrable, it may be a good idea to turn it into a guideline, so that it is consistent between the Boost libraries.
I agree. I have a macro BOOST_IOSTREAMS_PIPABLE which currently doesn't use a trailing semicolon. If we can agree ASAP on a convention, I'll make sure it's satisfied. Jonathan

"Arkadiy Vertleyb" <vertleyb@hotmail.com> wrote
We have a similar problem in typeof, and at this point semicolon is not required.
Surely Typeof is used in situations where semicolon not allowed: template<typename TL, typename TR> point<BOOST_TYPEOF_TPL(TL() + TR())> operator +( point<TL> const & lhs, vect<TR> const& rhs); Other situation is comma: int a,b; etc regards Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
"Arkadiy Vertleyb" <vertleyb@hotmail.com> wrote
We have a similar problem in typeof, and at this point semicolon is not required.
Surely Typeof is used in situations where semicolon not allowed:
template<typename TL, typename TR> point<BOOST_TYPEOF_TPL(TL() + TR())> operator +( point<TL> const & lhs, vect<TR> const& rhs);
No, what I actually mean is: BOOST_TYPEOF_REGISTER_TYPE(...) BOOST_TYPEOF_REGISTER_TEMPLATE(...) Regards, Arkadiy

"Arkadiy Vertleyb" <vertleyb@hotmail.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
Surely Typeof is used in situations where semicolon not allowed:
template<typename TL, typename TR> point<BOOST_TYPEOF_TPL(TL() + TR())> operator +( point<TL> const & lhs, vect<TR> const& rhs);
No, what I actually mean is:
BOOST_TYPEOF_REGISTER_TYPE(...) BOOST_TYPEOF_REGISTER_TEMPLATE(...)
Oops soory. However this identifies a point which I dont think has been made in this discussion. A generic macro is just a shapeless blob standing in for some text. Therefore I dont see it is possible to make general rules such as to whether a trailing semicolon is included. There is simply not enough definition. One would have to classify the *class* of macro rigorously (probably via the grammar) first. eg is this macro representing a typeid, an assignment-expression etc. Isnt this really what we are discussing ... fitting a macro into the grammar of the language? Identify the *class* of macro in the grammar to identify whether it is possible to use a particular macro in situations where a semicolon is not required, or whether the semicolon is always necessary, hence rightfully included as part of the macro. regards Andy Little

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andy Little
Oops soory. However this identifies a point which I dont think has been made in this discussion. A generic macro is just a shapeless blob standing in for some text. Therefore I dont see it is possible to make general rules such as to whether a trailing semicolon is included. There is simply not enough definition. One would have to classify the *class* of macro rigorously (probably via the grammar) first. eg is this macro representing a typeid, an assignment-expression etc. Isnt this really what we are discussing ... fitting a macro into the grammar of the language? Identify the *class* of macro in the grammar to identify whether it is possible to use a particular macro in situations where a semicolon is not required, or whether the semicolon is always necessary, hence rightfully included as part of the macro.
I wouldn't mind this approach. In fact, I kind of like it. It puts the appropriate emphasis on a macro's syntactic effect. But I don't think that it will help the various problems that people have (like extra semicolons) or editor issues. For example, if a macro expands to a function definition, then there shouldn't be a semicolon, which puts us squarely back in the situation we have now. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> wrote in message news:200507151937.j6FJbJ3e008997@milliways.osl.iu.edu...
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andy Little
Oops soory. However this identifies a point which I dont think has been made in this discussion. A generic macro is just a shapeless blob standing in for some text. Therefore I dont see it is possible to make general rules such as to whether a trailing semicolon is included. There is simply not enough definition. One would have to classify the *class* of macro rigorously (probably via the grammar) first. eg is this macro representing a typeid, an assignment-expression etc. Isnt this really what we are discussing ... fitting a macro into the grammar of the language? Identify the *class* of macro in the grammar to identify whether it is possible to use a particular macro in situations where a semicolon is not required, or whether the semicolon is always necessary, hence rightfully included as part of the macro.
I wouldn't mind this approach. In fact, I kind of like it. It puts the appropriate emphasis on a macro's syntactic effect. But I don't think that it will help the various problems that people have (like extra semicolons) or editor issues. For example, if a macro expands to a function definition, then there shouldn't be a semicolon, which puts us squarely back in the situation we have now.
Not sure I understand this. The two macros should be classed separately, consulting the grammar for the correct useage. I'm guessing that David Abrahams macro expands to a simple-declaration in the grammar( if the semi-colon is included, else it would be incomplete grammatically), therefore it should include the semicolon, which is the only mandatory part incidentally. However the macro as function-definition is grammatically complete without it. Of course with this approach macros would ideaaly be complete grammar entities, which is much neater than trailing semicolons IMO. FWIW my vote is to include the semicolon in the macro. It conceptually separates macros from standard code. Its less typing. OTOH A quick look through the boost libraries suggests that most do require user to supply semicolon. e.g Concept check, mpl.. regards Andy little

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Andy Little
I wouldn't mind this approach. In fact, I kind of like it. It puts the appropriate emphasis on a macro's syntactic effect. But I don't think that it will help the various problems that people have (like extra semicolons) or editor issues. For example, if a macro expands to a function definition, then there shouldn't be a semicolon, which puts us squarely back in the situation we have now.
Not sure I understand this. The two macros should be classed separately, consulting the grammar for the correct useage.
The problem is that users wouldn't be able to put a semicolon after this... #define MACRO() void f() { } MACRO(); // error ...which is the same situation, regardless of what MACRO expands to, that we have now. Some people think that its more natural to put the semicolon, and some have editor problems without the semicolon.
I'm guessing that David Abrahams macro expands to a simple-declaration in the grammar( if the semi-colon is included, else it would be incomplete grammatically), therefore it should include the semicolon, which is the only mandatory part incidentally. However the macro as function-definition is grammatically complete without it. Of course with this approach macros would ideaaly be complete grammar entities, which is much neater than trailing semicolons IMO.
Even without the semicolon, you can still match a structure declaration (without a semicolon) to a grammar production. It just isn't a more-or-less standalone grammar production. I do like this approach, though. It gives a rigorous syntactic meaning where there isn't one inherently. One thing that concerns me, however, is that not all macro expansions match a single grammar production (e.g. a class definition with an out-of-line member function definition after it), and defining a macro in terms of a lower-level grammar production implies that it can be used like that grammar production. For example, #define MAKE(id) struct id { } MAKE(abc) xyz; In most cases, I don't think that allowing this is the intention (though sometimes it is), so I think you'd have to stipulate that the matched grammar production is as high-level as possible yet still achieve the basic intent. Regards, Paul Mensonides

Andy Little wrote:
"Arkadiy Vertleyb" <vertleyb@hotmail.com> wrote
We have a similar problem in typeof, and at this point semicolon is not required.
Surely Typeof is used in situations where semicolon not allowed:
template<typename TL, typename TR> point<BOOST_TYPEOF_TPL(TL() + TR())> operator +( point<TL> const & lhs, vect<TR> const& rhs);
I think he's talking about type registration. Jonathan

"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
We have a similar problem in typeof, and at this point semicolon is not required. This leads to all the problems with the editor that you mentioned, and, if the user does supply the (second) semicolon, some compilers emit warnings, so I am by no means happy with the situation.
However, if the semicolon is required, and the user doesn't supply it, the compiler will produce an error message, which will expose implementation details of this macro, and most likely be of little help.
Actually, that seems much better to me than the alternative: if the macro supplies the semicolon, and the user mistakenly supplies an extra semicolon, many compilers *don't* warn/error, which means that the user doesn't find out her code is nonportable until it breaks on some other compiler or set of compiler options.
So, the choice is actually between two evels, and I am not really sure which one is less evel.
Also, I think, this problem is very generic, and once it's decided which style is prefferrable, it may be a good idea to turn it into a guideline, so that it is consistent between the Boost libraries.
Yeah. My only hesitation is that Paul Mensonides as been a vocal opponent of requiring the semicolon in many contexts. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: "Arkadiy Vertleyb" <vertleyb@hotmail.com>
"David Abrahams" <dave@boost-consulting.com> wrote
I am defining a macro,
BOOST_PARAMETER_KEYWORD(tag_namespace, name) [snip] will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
We have a similar problem in typeof, and at this point semicolon is not required. This leads to all the problems with the editor that you mentioned, and, if the user does supply the (second) semicolon, some compilers emit warnings, so I am by no means happy with the situation.
Yep.
However, if the semicolon is required, and the user doesn't supply it, the compiler will produce an error message, which will expose implementation details of this macro, and most likely be of little help.
That error message will alert the user to having misused the macro. A glance at the documentation will reveal that a semicolon is required. It really doesn't require that the user dig into the implementation details to learn that a semicolon is needed.
So, the choice is actually between two evels, and I am not really sure which one is less evel.
I don't see it as choosing the lesser of two evils.
Also, I think, this problem is very generic, and once it's decided which style is prefferrable, it may be a good idea to turn it into a guideline, so that it is consistent between the Boost libraries.
Agreed. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"David Abrahams" <dave@boost-consulting.com> wrote
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
One more option (probably an overkill): #ifdef (BOOST_USE_TRAILING_SEMICOLON) # define BOOST_TRAILING_SEMICOLON ; #else # define BOOST_TRAILING_SEMICOLON #endif Now end all your macro definitions with BOOST_TRAILING_SEMICOLON instead of ';', and the user can change the style with just one [un]define. Regards, Arkadiy

Arkadiy Vertleyb wrote:
One more option (probably an overkill):
#ifdef (BOOST_USE_TRAILING_SEMICOLON) # define BOOST_TRAILING_SEMICOLON ; #else # define BOOST_TRAILING_SEMICOLON #endif
Now end all your macro definitions with BOOST_TRAILING_SEMICOLON instead of ';', and the user can change the style with just one [un]define.
This would mean that in every code example using one of these macros, you'd have to add a note about BOOST_TRAILING_SEMICOLON. Jonathan

"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
"David Abrahams" <dave@boost-consulting.com> wrote
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
One more option (probably an overkill):
#ifdef (BOOST_USE_TRAILING_SEMICOLON) # define BOOST_TRAILING_SEMICOLON ; #else # define BOOST_TRAILING_SEMICOLON #endif
Now end all your macro definitions with BOOST_TRAILING_SEMICOLON instead of ';', and the user can change the style with just one [un]define.
Very scary. That would break any (Boost) libraries that happen to use the opposite convention. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
I'm against just about anything that attempts to make a macro invocation look more like regular code. This is nothing but a workaround for an editor (of all things). The macro invocation is not a declaration, it does not fit into the syntax model of C++, and it should not be made to look like it does--regardless of what it expands to. Regards, Paul Mensonides

"Paul Mensonides" <pmenso57@comcast.net> wrote in message
I'm against just about anything that attempts to make a macro invocation look more like regular code. This is nothing but a workaround for an editor (of all things).
So what's wrong with a workaround for an editor?
The macro invocation is not a declaration, it does not fit into the syntax model of C++, and it should not be made to look like it does--regardless of what it expands to.
Aren't most macros used to expand into a legal c++ code fragment ([meta]function call, class/template definition, etc.)? As such, why shouldn't they be designed to fit nicely into the c++ syntax? Otherwise macros are inconvenient to use, and this is just one more argument for those who claim macros should be avoided at any cost. Regards, Arkadiy

"Paul Mensonides" <pmenso57@comcast.net> writes:
I'm against just about anything that attempts to make a macro invocation look more like regular code. This is nothing but a workaround for an editor (of all things). The macro invocation is not a declaration, it does not fit into the syntax model of C++, and it should not be made to look like it does--regardless of what it expands to.
I understand your reasoning, but this argument on principle seems to be outweighed by too many practical considerations. Can you argue against any of those? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
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?
The former. Require the user to put a trailing semi-colon. Lines like: SOME_MACRO(parameter, anotherparameter) look ugly, and are confusing since a C++ programmer will always end a similar-looking function call with a semi-colon.

Hi "David Abrahams" <dave@boost-consulting.com> wrote in message news:ueka1s3zt.fsf@boost-consulting.com...
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?
The normal use for marcros do not requiere you to place an extra semicolon. Macros are not function calls and should be treated different. The fact that some people do not like macros and they think they polute the code, they have two choices, you can embrase the use of macros, or just live with them as macros are not going to be removed from the standard. \TM
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
-- Dave Abrahams Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Lucas Galfaso" <lgalfaso@gmail.com> writes:
Hi "David Abrahams" <dave@boost-consulting.com> wrote in message news:ueka1s3zt.fsf@boost-consulting.com...
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?
The normal use for marcros do not requiere you to place an extra semicolon. Macros are not function calls and should be treated different. The fact that some people do not like macros and they think they polute the code, they have two choices, you can embrase the use of macros, or just live with them as macros are not going to be removed from the standard.
Ooooooo Kaaaaaay. But nothing you wrote above addresses the question I asked. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u7jfsn4wq.fsf@boost-consulting.com...
"Lucas Galfaso" <lgalfaso@gmail.com> writes:
Hi "David Abrahams" <dave@boost-consulting.com> wrote in message news:ueka1s3zt.fsf@boost-consulting.com...
I am defining a macro,
BOOST_PARAMETER_KEYWORD(tag_namespace, name)
Ooooooo Kaaaaaay. But nothing you wrote above addresses the question I asked.
It is simple, a semicolon is not the normal use of macros, and should not be necessary to complete what they address.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

David Abrahams <dave@boost-consulting.com> writes:
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
OK, here's a argument against: requiring the semicolon makes it impossible to define a macro that expands to nothing. For instance, if we required the semicolon in BOOST_MPL_AUX_LAMBDA_SUPPORT: template< typename T, typename U = int > struct f { typedef T type[sizeof(U)]; BOOST_MPL_AUX_LAMBDA_SUPPORT(2, f, (T,U)); ^^ }; then for comforming compilers we would have to come up with something like #define BOOST_MPL_AUX_LAMBDA_SUPPORT( arity, name, args ) \ typedef BOOST_PP_CAT( ugly_ugly_hack, __LINE__ ) \ /**/ and hope that user will never have a class member named 'ugly_ugly_hackNN'. Besides being conceptually unclean and theoretically conflict-prone, this would also have an unpleasant effect of not being able to get a "clean" version of the code by simply preprocessing the file under a proper configuration (the MPL way to generate "ideal" versions of the preprocessed headers for conforming compilers). -- Aleksey Gurtovoy MetaCommunications Engineering

Aleksey Gurtovoy <agurtovoy@meta-comm.com> writes:
David Abrahams <dave@boost-consulting.com> writes:
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?
IMO there's no chance of confusing it with a function call, since a function call would be illegal in the context in which it's used, and people are naturally more likely to add a semicolon without thinking about it, and if I design the macro so that a semicolon is required it will interact more smoothly with editors and pretty-printers. So I can't see any good reason not to require the semicolon. Arguments?
OK, here's a argument against: requiring the semicolon makes it impossible to define a macro that expands to nothing.
Okay, that's a valid argument when the macro is just being used as a workaround, but in this case it's a convenience macro to stand in for a couple of declarations. If you use it, you want it to have an effect everywhere. In any case, I see that particular case as being taken care of by the "where possible" clause. If the author decides that the macro (plus whatever trailing semicolon) has to be able to expand to nothing, requiring a trailing semicolon is obviously not practical. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Does the macro's name describe what the macro generates (e.g. BOOST_XYZ_EXPRESSION) or does the macro's name describe a purpose (e.g. BOOST_REGISTER_XYZ)? Name describes expansion : semicolon must not be added by the user Name describes purpose : semicolon must be added by the user It indirectly depends on the design of the particular library: If you want the user to look at the macro as part of the interface use "purpose naming" (imperative) and have the user supply a semicolon. If you want the user to look at the macro as a code generator (e.g. convenience-shortcuts with a documented alternative that could be written manually) use "expansion naming" (noun/perfect) and put the semicolon inside the macro. Regards, Tobias

Tobias Schwinger <tschwinger@neoscientists.org> writes:
Does the macro's name describe what the macro generates (e.g. BOOST_XYZ_EXPRESSION) or does the macro's name describe a purpose (e.g. BOOST_REGISTER_XYZ)?
Name describes expansion : semicolon must not be added by the user Name describes purpose : semicolon must be added by the user
It indirectly depends on the design of the particular library:
If you want the user to look at the macro as part of the interface use "purpose naming" (imperative) and have the user supply a semicolon.
If you want the user to look at the macro as a code generator (e.g. convenience-shortcuts with a documented alternative that could be written manually) use "expansion naming" (noun/perfect) and put the semicolon inside the macro.
IIRC someone else proposed a policy that Paul M. agreed with -- at least conditionally -- but I can't find it in the archives. Can somebody point me to it? Since Paul is a PP expert it makes sense to give anything he agrees with a second look. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams
IIRC someone else proposed a policy that Paul M. agreed with -- at least conditionally -- but I can't find it in the archives. Can somebody point me to it? Since Paul is a PP expert it makes sense to give anything he agrees with a second look.
The policy was (in cases where it makes any sense) for macros to be given a strict syntactic definition in terms a direct correspondence with a C++ grammar production. The reason that I find this attractive is that it gives a rigourous syntactic definition to something that doesn't have one based upon its syntactic representation to the preprocessor. The main problem is that it wouldn't solve any of the problems here. The secondary problem is that there is a significant difference between... struct abc { void f() { } }; ...and... struct abc { void f(); }; void abc::f() { } ...in terms of production depth. A direct match to a production for the former is much more refined than a direct match for the latter. A tertiary problem, which is directly related to this discussion, is what heuristic to apply to choose the production, because you can obviously directly match a production to both... struct abc { } ..and... struct abc { }; My opinion is that it should be decided based on whether there is an intended external point of variability. I.e. if this is not intended typedef MACRO(abc) xyz; then the semicolon is not an external point of grammatical variability, and 'MACRO' should match the production that doesn't allow for this variability. (In other words, it should include its own semicolon, and we're back to square one.) The lesser the depth, the more restrictive in terms of external variability, which would be the kind of abstract definition needed if a macro *was* an abstraction rather than a simple shorthand way to say something, thus allowing it to change more easily over time. Regards, Paul Mensonides

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?
Just in case you're counting votes: require user to type semi-colon. I've always done this in my macros, not due to editors, but as it feels most natural. Darren

On 7/16/05, Darren Cook <darren@dcook.org> wrote:
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?
Just in case you're counting votes: require user to type semi-colon. I've always done this in my macros, not due to editors, but as it feels most natural.
I second that.
Darren _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Cory Nelson http://www.int64.org
participants (19)
-
Aleksey Gurtovoy
-
Andy Little
-
Arkadiy Vertleyb
-
Chris Uzdavinis
-
Cory Nelson
-
Darren Cook
-
Dave Steffen
-
David Abrahams
-
Doug Gregor
-
Edward Diener
-
Jeremy Maitin-Shepard
-
Jody Hagins
-
Jonathan Turkanis
-
Lucas Galfaso
-
Paul Mensonides
-
Peter Dimov
-
Rob Stewart
-
Thomas Witt
-
Tobias Schwinger