Format
#<directive> <stuff>
Allow command line flags
g++ test.cpp -DDEBUG_BUILD=true
if constexpr(DEBUG_BUILD) {
...
}
Directives do not have scope, the file is processed top down. So moving directives can change generated code.
Code exclusion antipatterns
- Exclude enum values
- Changing flow control
- Excluding members
Include
#include <file_to_include>
When to use:
- When you don’t have module support
C alternative:
- None
C++ alternative
- C++20 modules
Objects as macros
#define <identifier> <replacement>
#undef <identifier>
Reserved:
- start with _
- contain __
- match a language keyword
- match a standardized name
When to use:
- When you need a value to use during the pre-processing phase
- When you need to support multiple compiler capabilities
- Command line flags
C alternative:
- For constant expressin use enums
enum { ARRAY_SIZE = 44 } char arr[ARRAY_SIZE]
C++ alternative
- Use constexpr or static const values
Conditionals
#if <expr>
...
#elif <expr>
...
#else
...
#endif
When to use:
- Include guards
- C linkage specification
#ifndef __cplusplus extern C { #endif
- Very sparingly, to exclude code
- Check for header or feature availability flags
C alternative:
- Attempt to restructure code to limit inline code exclusion
C++ alternative
- Use constexpr if when all code is available
- Module imports
Function like macros
#define <identifier>(<arg1>, <arg2>)\
<replacement code>
When to use:
- Perform more complicated pre-processor operations
- Generate blocks of code
C alternative:
- Create multiple functions for each type with _Generic
C++ alternative
- constexpr functions
- templates
Variadic functions like macros
#define <identifier>(<arg1>, ...)\
<replacement code>
- Values accessed via VA_ARGS
-
- va_arg, va_start, va_copy, va_end - GCC: prepend ## to VA_ARGS to omit trailing coma in zero arguments case
- C++20: VA_OPT
When to use:
- Perform more complicated pre-processor operations
- Absorb all parameters and turn into noop
C alternative:
- variadic functions with
C++ alternative
- variadic templates
Remember:
do {
...
} while(0)
File and line info
When to use:
- If you don’t have C++20
C alternative:
- None
C++ alternative
- C++20 std::source_location
Stringification and Concatenation
#define <identifier>(<text>) #<text>
#define <identifier>(<text1>,<text2>) <text>##<text2>
When to use:
- If you need to generate function or variable names
C alternative:
- None
C++ alternative
- Consider templates
- Future: Static ; Reflection/Static ; Generation/Metaclasses
Pragma
#pragma
- Inclusion guard
- Warning/error manipulation
- Struct packing (last till he end of current translation unit)
When to use:
- Limit use as much as possible
C alternative:
- attribute
- __declspec
- packed
C++ alternative
- Same as C