3

In C++, many developers (perhaps even most of us) dislike macros and try to avoid them in favor of proper language constructs. And - it seems the language tends to be encouarging this as well. Gradually, we've been able to get rid of macro use in a lot of cases:

  • Type polymorphism -> template programming
  • Conditional compilation -> compile-time evaluation of template parameters, SFINAE, etc.
  • #include guards -> #pragma once for some compilers, although I guess you can't trust that; soon we should have C++17 Modules and import instead of include.

My question is - what's left? What kinds of macro use are completely unavoidable, or very painful to avoid? The main examples I can think of is:

  • Using filenames, line numbers and function/method names:

    #define LOG(whatever, ...) log(__FUNCTION__, __FILE__, __LINE__, whatever, VA_ARGS)
    
  • Syntactic sugar for taking a block of code as an "argument", e.g.

    AT_SCOPE_EXIT { release_resource(); }
    

    in Andrei Alexandrescu's ScopeGuard (or check out the video). Although I guess we don't really need to use the terse macro-using pseudo-syntax for that.

  • Perhaps certain kinds of Boost voodoo?
  • Backwards compatibility?

What other significant uses of macros am I missing? (No super-specific corner cases please.)

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 9
    "`#include` guards -> `#pragma once`" -- **NO**, for {bleep}'s sake! One is standard C++. The other is *implementation defined behaviour* (as everything `#pragma`, by definition). – DevSolar Nov 18 '15 at 13:19
  • 1
    What about [`__TIME__` and `__DATE__`](http://stackoverflow.com/a/24561244/2422013)? – AStopher Nov 18 '15 at 13:20
  • 2
    It seems extremely opinion based to say "In C++, we dislike macros and try to avoid them" this opinion is somewhat popular but by no means universal. I dont think this question can have a reasonable answer in its current form. – Vality Nov 18 '15 at 13:24
  • Why too broad? This is a good question – Dean Nov 18 '15 at 13:27
  • 3
    @Dean Because there's no one answer. The question is basically an opinion based "What do you use macros for in C++?" with an opinion-based framing indicating that we should probably try avoiding them. – nhgrif Nov 18 '15 at 13:28
  • @nhgrif: Well, perhaps there's no one _penultimate_ answer but one can certainly cover most of the ground with one answer. Plus, remember that "one answer" is not a requirement. Innumerable questions of the type "how can I do X" have multiple answers (without being opinion-based). – einpoklum Nov 18 '15 at 13:37
  • @DevSolar: Edited as per your comment. Thanks for that. I always have both the include guard and the pragma so I never learned what the difference is. – einpoklum Nov 18 '15 at 13:39
  • @Vality: I thought this was the concensus, but edited to take your comment into consideration. – einpoklum Nov 18 '15 at 13:41
  • 1
    Having an unending list of answers doesn't make the question opinion-based. It makes it too broad. There's nothing wrong with a question having more than one answer. But that's not what this is. I'm tossing aside opinion-based for now and just addressing too broad. Your question has problems that the help center highlights, particularly in this section: http://i.imgur.com/QwOvX3J.png – nhgrif Nov 18 '15 at 13:42
  • @nhgrif: I don't believe this question would result in an endless, or even very long, list of use cases. I've edited the last line to make that request even more explicit, although I think people are intelligent enough to understand what I mean. Please have a bit more trust in the SO userbase etc... – einpoklum Nov 18 '15 at 13:46
  • @einpoklum: `#pragma` is for compilers to allow clients a standard-compliant way to access compiler-specific functionality. `#pragma once` was introduced *well back*, by Microsoft. Back then their preprocessor had to actually *read* and *process* the header file again to find it's been header-guarded, but didn't have to with `once`. This has long since (since 199x...) been optimized into making no difference. The other "benefit" was that it was "safer", in case you used a header guard string twice. (However, `once` can break as well, just more subtly.) So... use header guards. ;-) – DevSolar Nov 18 '15 at 13:52
  • @DevSolar If they're standard conforming they still have to (pre)process the entire file, there's nothing that requires what seem to be a include guard to cover the entire file. If they've optimized and still are standard conforming I wonder just what they did before (or if they've done something overly smart here). – skyking Nov 18 '15 at 14:01
  • 2
    @skyking: You'll have to ask Microsoft, or better, the GCC maintainters (as GCC also implemented `#pragma once`, and are somewhat more forthcoming with information on internals). I'd guess they detect the "typical" header guard pattern (file-wide `#if` / `#endif` with no non-comment tokens outside that), and then "mark" that header as "read". Unless the header file has changed, whether it's re-read or not on subsequent re-includes does not make any difference, and the standard allows as-if optimizations unless I am mistaken. – DevSolar Nov 18 '15 at 14:10
  • This GCC maintainer could provide links but that'd be against SO policy and would get flagged for deletion, and I can't be bothered typing out an explanation. Basically, what @DevSolar said. – Jonathan Wakely Nov 18 '15 at 15:24
  • @JonathanWakely: LOL... "I was right! I was right!" {hop around in circles} -- Thank you for your comment, and your work on GCC. – DevSolar Nov 18 '15 at 15:47

2 Answers2

6

Disabling sections of code without having to worry about nested comments.

#if 0
...
#endif

Conditional compilation of various kinds.

// C/C++ dual-purpose headers
#if __cplusplus
extern "C" {
#endif

// checking third-party library versions for API compatibility
#if BOOST_VERSION >= 104600
...
#endif

// checking platforms for API compatibility
#if _WIN32
...
#endif
DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • I often do the first one and I feel very bad when I do it. I'm glad I can continue to justify this behavior for some time in the future. – Dean Nov 18 '15 at 13:23
  • @Dean: I firmly believe C++ is not about being beautiful (on the inside, at least), but being *effective*. I'll probably *keep* using [`SSTR()`](http://stackoverflow.com/a/5590404/60281) for years to come for non-POD types and pre-C++11 targets. ;-) – DevSolar Nov 18 '15 at 13:31
  • 1
    `#if 0` is not a macro. The question is not "what uses of the preprocessor are still unavoidable?" but if it was then someone should have mentioned `#include` :-) – Jonathan Wakely Nov 20 '15 at 00:49
  • 1
    @JonathanWakely: The OP explicitly mentioned include guards (*and* include) so I assumed his definition of "macro" was a bit fuzzy in the first place. ;-) But yes, `#include` is so obvious I didn't even think about that. :-D – DevSolar Nov 20 '15 at 06:07
  • "without having to worry about nested comments." <- What's the problem with `//` comments? (Ok, they're not perfect, but they do work without requiring macros). Also, like @JonathanWakely says, preprocessor directives do not necessarily use macros. Include guards involve macros, which is why I mentioned them. – einpoklum Dec 11 '15 at 19:16
  • Also, if I rephrase the ghist of your answer, the remaining use is accessing compiler settings (which version, which language / language variant, which target platform etc.) for conditional compilation. – einpoklum Dec 11 '15 at 19:26
  • @einpoklum: The problem with `//` comments is that they are a bit unwieldly for disabling *stretches* of code. And I did not list all uses I *personally* have for preprocessor macros, just those I consider uncontroversial. I mentioned `SSTR()` above; I also have a couple of macros I use for debugging / tracing purposes, but did not want to put up for discussion here. – DevSolar Dec 12 '15 at 09:27
  • @DevSolar: Then perhaps you could provide a link to somewhere with those key-useful-macros-I-still-use? – einpoklum Dec 12 '15 at 14:41
  • @einpoklum: I linked SSTR() above. Others are situational, i.e. not of general use. (With the tracing, for example, the macros are only part of a larger plumbing code, and as I said, probably not fit-for-presentation-use.) – DevSolar Dec 14 '15 at 07:28
3

My question is - what's left? What kinds of macro use are completely unavoidable, or very painful to avoid? The main examples I can think of is:

  • Using filenames and line numbers:

std::experimental::source_location should make macros unnecessary for many of those kind of uses.

  • AT_SCOPE_EXIT { release_resource(); } in Andrei Alexandrescu's ScopeGuard. Although I guess we don't really need that.

See P0052 for a proposed macro-free alternative.

Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Why have people downvoted this so severely? These links are interesting. – einpoklum Nov 18 '15 at 13:43
  • 3
    Because interesting links and good Stack Overflow answers are not the same thing. It might be especially important to consider the original version of this answer was far worse and was literally just quotes and links without *any* plain English to go along with it. – nhgrif Nov 18 '15 at 13:44
  • 1
    Still, it's *aggressive* downvoting there... – YSC Nov 18 '15 at 13:45
  • @YSC What is "aggressive" downvoting? I read the answer, decided, individually, that it needed a downvote, and downvoted it. Full disclosure, mine was actually the *first* of the 6 downvotes, and I can't speak for the others (currently 5). But perhaps most importantly, the 6th downvoter shouldn't vote any differently based on the existing up or downvotes--they should vote based on their individual reading of the answer and opinion on whether or not it constitutes a good Stack Overflow answer. If they individually decide it doesn't, they should downvote... – nhgrif Nov 18 '15 at 13:50
  • 1
    ...and that decision to downvote should be made independently of any existing votes on the answer. Whether it was sitting at 0, +10, -10, etc., it does not matter. Voting on Stack Exchange should not be based on existing votes. The votes on this answer say this exactly "Six people read this answer and decided it didn't make for a good answer." What it shouldn't say is "Some unknown number of people read this, the first three thought it was bad and downvoted, then it was at -3 so no one else voted because that'd be 'aggressive'". – nhgrif Nov 18 '15 at 13:51
  • 1
    @nhgrif sure ... it's just surprising. – YSC Nov 18 '15 at 13:51
  • 1
    Yes, I know the policy, I don't care. If people want to know about those things the links are there, I'm not going to duplicate the info. The essential parts of the answer are that there's a type called `std::experimental::source_location` and that there's a proposal called P0052, and they make the quoted uses of macros unnecessary. Further details can be found at the links for people who are interested. – Jonathan Wakely Nov 18 '15 at 15:08
  • @nhgrif that's not true, it was never just links without _any_ plain English, the very first version (which was there for about 30 seconds) said "See ..." for both links :-P Most of the downvotes came long after that, when it was in its present form. – Jonathan Wakely Nov 18 '15 at 15:09
  • 1
    Congratulations on your most downvoted answer on SO, Mr. Wakely! Most of us thought you'd surely never make it to -7. I'm proud of you, buddy. – Barry Nov 18 '15 at 15:34
  • 5
    @Barry, thanks dude, it's an emotional experience _sniff_. I'd like to thank my family, and my agent, and most of all the cats who are scared of cucumbers. I do it all for the cats. – Jonathan Wakely Nov 18 '15 at 15:55
  • 2
    Man, that's some weird politics you high-rep users are playing. +1 for the balance though. – einpoklum Nov 18 '15 at 19:50
  • 1
    This post is a correction for the question because while the question asks "what kind of macors are unavoidable?" this post explains "some of your examples in the post are not anymore unavoidable soon". Therefore it should have been a comment rather than being posted as an answer. – Johannes Schaub - litb Nov 19 '15 at 21:38
  • 2
    @ᐅJohannesSchaub-litbᐊ It answers _"My question is - what's left? What kinds of macro use are completely unavoidable, or very painful to avoid?"_ by saying "very little is left, those kinds of macro are not unavoidable". Whether that's an answer or a correction seems to be splitting hairs, and if you take that view then 90% of C++ questions are answered by corrections that say "no, that's not how C++ works, your code is broken". – Jonathan Wakely Nov 20 '15 at 00:47