8

Macros are considered a good thing by one and evil by another.

Is there a rule of thumb when to and when not to use macros in C++?

When are macros idiomatic and when should they be avoided?

Mast
  • 201
  • 2
  • 12
  • 3
    http://stackoverflow.com/q/96196 – Robert Harvey Jun 29 '15 at 18:21
  • @RobertHarvey Should I conclude I should only use macros if there is no way around them? – Mast Jun 29 '15 at 18:24
  • 1
    @Mast That's my understanding, yes. The only uses of macros that I'd consider unobjectionable in C++ would be logging and assertions, because `__FILE__` and `__LINE__` are very, very useful things for logger and assertion output to have. – Ixrec Jun 29 '15 at 18:31
  • 2
    Also, include guards. While `#pragma once` is nice, it is nonstandard. –  Jun 29 '15 at 19:44
  • @Snowman `#pragma once` appears to work when compiling with MSVC, GCC and Clang (on Windows, Android NDK, and Xcode), when the source code is compiled as C++. – rwong Jun 30 '15 at 09:19
  • 2
    In addition to the aforementioned situations, compiler-vendor specific variations in keywords such as `restrict`, `export` (from a static or dynamic library), and `inline` / `noinline` also requires the use of conditional compilation macros. Workarounds for missing C++11 support in some compilers would also require conditional compilation macros. – rwong Jun 30 '15 at 10:33

3 Answers3

14

As a rule, you should only use macros, when a better alternative does not exist.

They should not be used to generate code; you should simply write the code instead (if the code is type-agnostic, write a template instead).

They should not be used to define constants; constants should be defined using one of these: (static) constexpr/const variables, anonymous enumerations, named enumerations, enum classes (depending on what you want to use them for).

They should be used for conditional compilation (include guards are one of these cases).

Ideally, they should not be used to conditionally change the API of a module at compilation (that is, ideally you should declare the same functions in all configurations, then use conditional compilation in the implementation file.

In all* other cases, macros should be avoided.


(*) - Sometimes, there are exceptions to "all other cases" (for example, you may have third party code that requires you to use macros; that's life :-) ).

utnapistim
  • 5,285
  • 16
  • 25
  • Sometimes a short set of macros (with `#undef` immediately after use!) is the right way to generate sets of function bodies. Case in point: [JVM bytecode instruction struct with serializer & parser](//codereview.stackexchange.com/q/285925/75307) - if you have suggestions to make that more maintainable without the macros, then please add a review there with your advice. – Toby Speight Jul 06 '23 at 07:05
12

When are macros idiomatic and when should they be avoided?

Macros are idiomatic only when there is no alternative to their use. Examples are include guards (they are the only portable form), embedded domain-specific languages, special compiler support not available through other language features (embedding built-in macros like __FILE__, stringifying and concatenating identifiers), and a few other places.

Macros should be avoided whenever possible. That's because they follow their own very simplistic syntax and know nothing about C++, dumbly trampling over any and all namespaces.

It has always been one of Stroustrup's goals to eliminate the preprocessor as much as possible. Function inlining, templates, and constants are a prime example, as are modules (to replace #include), which have been chewed on by the standardization committee for years. The language features created to avoid having to use macros are all very much better than the macros they replace. Make use of them whenever possible.

sbi
  • 9,992
  • 6
  • 37
  • 56
3

The only time I'd consider macros are for compile time constants, typically ones that affect the compilation (as opposed to constant application values, which are better modelled as const types).

However, I have modelled utility routines such as calls to logging functions in a macro just so they will be compiled out, but I think even this is unnecessary today - the compiler should be clever enough to realise a logging function that does nothing due to conditional compilation will be optimised away, but old habits die hard :)

gbjbaanb
  • 48,354
  • 6
  • 102
  • 172