Conditional inclusion
The preprocessor supports conditional compilation of parts of source file. This behavior is controlled by #if, #else, #elif, #ifdef, #ifndef and #endif directives.
Syntax
#if expression | ||
#ifdef identifier | ||
#ifndef identifier | ||
#elif expression | ||
#else | ||
#endif |
Explanation
The conditional preprocessing block starts with #if, #ifdef or #ifndef directive, then optionally includes any number of #elif directives, then optionally includes at most one #else directive and is terminated with #endif directive. Any inner conditional preprocessing blocks are processed separately.
Each of #if, #elif, #else, #ifdef and #ifndef directives control code block until first #elif, #else, #endif directive not belonging to any inner conditional preprocessing blocks.
#if, #ifdef and #ifndef directives test the specified condition (see below) and if it evaluates to true, compiles the controlled code block. In that case subsequent #else and #elif directives are ignored. Otherwise, if the specified condition evaluates false, the controlled code block is skipped and the subsequent #else or #elif directive (if any) is processed. In the former case, the code block controlled by the #else directive is unconditionally compiled. In the latter case, the #elif directive acts as if it was #if directive: checks for condition, compiles or skips the controlled code block based on the result, and in the latter case processes subsequent #elif and #else directives. The conditional preprocessing block is terminated by #endif directive.
Condition evaluation
#if, #elif
The expression is a constant expression.
The expression may contain unary operators in form defined identifier or defined (identifier). The result is 1 if the identifier was defined as a macro name or the identifier is __has_include (since C++17), otherwise the result is 0.
After all macro expansion and evaluation of defined and __has_include (since C++17) expressions, any identifier which is not a boolean literal is replaced with the number 0 (this includes identifiers that are lexically keywords, but not alternative tokens like and).
If the expression evaluates to nonzero value, the controlled code block is included and skipped otherwise.
| Note: | (until C++14) |
#ifdef, #ifndef
Checks if the identifier was defined as a macro name.
#ifdef identifier is essentially equivalent to #if defined identifier.
#ifndef identifier is essentially equivalent to #if !defined identifier.
Example
#define ABCD 2
#include <iostream>
int main()
{
#ifdef ABCD
std::cout << "1: yes\n";
#else
std::cout << "1: no\n";
#endif
#ifndef ABCD
std::cout << "2: no1\n";
#elif ABCD == 2
std::cout << "2: yes\n";
#else
std::cout << "2: no2\n";
#endif
#if !defined(DCBA) && (ABCD < 2*4-3)
std::cout << "3: yes\n";
#endif
}Output:
1: yes 2: yes 3: yes
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 1955 | C++14 | failed #elif's expression was required to be valid | failed elif is skipped |
See also
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/preprocessor/conditional