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 expression
|
|||||||||
#ifndef expression
|
|||||||||
#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.
If the expression contains unary operators in form defined
identifier or defined (
identifier)
, it is evaluated first. 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 macro expansion and evaluation of the defined
operator, any identifier which is not a boolean literal, nor currently defined as a macro name, are replaced with the number 0.
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
C documentation for Conditional inclusion
|