[cpp.cond]

# 15 Preprocessing directives [[cpp]](./#cpp)

## 15.2 Conditional inclusion [cpp.cond]

[defined-macro-expression:](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")  
defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")  
defined ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )

[h-preprocessing-token:](#nt:h-preprocessing-token "15.2 Conditional inclusion [cpp.cond]")  
any [*preprocessing-token*](lex.pptoken#nt:preprocessing-token "5.5 Preprocessing tokens [lex.pptoken]") other than >

[h-pp-tokens:](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]")  
[*h-preprocessing-token*](#nt:h-preprocessing-token "15.2 Conditional inclusion [cpp.cond]") [*h-pp-tokens*](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]")opt

[header-name-tokens:](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]")  
[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")  
< [*h-pp-tokens*](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]") >

[has-include-expression:](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")  
__has_include ( [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") )  
__has_include ( [*header-name-tokens*](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") )

[has-embed-expression:](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")  
__has_embed ( [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )  
__has_embed ( [*header-name-tokens*](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )

[has-attribute-expression:](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")  
__has_cpp_attribute ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") )

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L380)

The expression that controls conditional inclusion
shall be an integral constant expression except that
identifiers
(including those lexically identical to keywords)
are interpreted as described below[123](#footnote-123 "Because the controlling constant expression is evaluated during translation phase 4, all identifiers either are or are not macro names â there simply are no keywords, enumeration constants, etc.") and it may contain zero or more[*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")*s*,
and/or [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")*s* as unary operator expressions[.](#1.sentence-1)

A [*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]") shall not appear
within a [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") or [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")[.](#1.sentence-2)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L401)

A [*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]") evaluates to 1 if the identifier is currently defined
as a macro name
(that is, if it is predefined
or if it has one or more active macro definitions ([[cpp.import]](cpp.import "15.6 Header unit importation")),
for example because
it has been the subject of a#define preprocessing directive
without an intervening#undef directive with the same subject identifier), 0 if it is not[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L415)

The header or source file identified by
the parenthesized preprocessing token sequence
in each contained [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") is searched for as if that preprocessing token sequence
were the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #include directive,
except that no further macro expansion is performed[.](#3.sentence-1)

If the preprocessing token sequence does not consist solely of a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") or cannot be combined ([[cpp.include]](cpp.include "15.3 Source file inclusion")) into a single[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token, the program is ill-formed[.](#3.sentence-2)

The [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") evaluates
to 1 if the search for the source file succeeds, and
to 0 if the search fails[.](#3.sentence-3)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L429)

The parenthesized preprocessing token sequence of each contained[*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") is processed as if that
preprocessing token sequence were the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #embed directive ([[cpp.embed]](cpp.embed "15.4 Resource inclusion")),
except that no further macro expansion is performed[.](#4.sentence-1)

The [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") evaluates to:

- [(4.1)](#4.1)

  __STDC_EMBED_FOUND__ if the search for the resource succeeds,
all the given [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]")*s* in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]") are supported, and the resource is not empty[.](#4.1.sentence-1)

- [(4.2)](#4.2)

  Otherwise, __STDC_EMBED_EMPTY__ if the search for the resource succeeds,
all the given [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]")*s* in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]") are supported, and the resource is empty[.](#4.2.sentence-1)

- [(4.3)](#4.3)

  Otherwise, __STDC_EMBED_NOT_FOUND__[.](#4.3.sentence-1)

[*Note [1](#note-1)*:

An unrecognized [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") in an [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") is not ill-formed and is instead treated as not supported[.](#4.sentence-3)

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L453)

Each [*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") is replaced by
a non-zero [*pp-number*](lex.ppnumber#nt:pp-number "5.7 Preprocessing numbers [lex.ppnumber]") matching the form of an [*integer-literal*](lex.icon#nt:integer-literal "5.13.2 Integer literals [lex.icon]") if the implementation supports an attribute
with the name specified by interpreting
the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), after macro expansion,
as an [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
and by 0 otherwise[.](#5.sentence-1)

The program is ill-formed if the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") do not match the form of an [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#5.sentence-2)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L465)

For an attribute specified in this document,
it is implementation-defined
whether the value of the [*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") is 0 or is given by Table [21](#tab:cpp.cond.ha "Table 21: __has_­cpp_­attribute values")[.](#6.sentence-1)

For other attributes recognized by the implementation,
the value isimplementation-defined[.](#6.sentence-2)

[*Note [2](#note-2)*:

It is expected
that the availability of an attribute can be detected by any non-zero result[.](#6.sentence-3)

â *end note*]

Table [21](#tab:cpp.cond.ha) — __has_cpp_attribute values [[tab:cpp.cond.ha]](./tab:cpp.cond.ha)  

| [ð](#tab:cpp.cond.ha-row-1)<br>**Attribute** | **Value** |
| --- | --- |
| [ð](#tab:cpp.cond.ha-row-2)<br>assume | 202207L |
| [ð](#tab:cpp.cond.ha-row-3)<br>deprecated | 201309L |
| [ð](#tab:cpp.cond.ha-row-4)<br>fallthrough | 201603L |
| [ð](#tab:cpp.cond.ha-row-5)<br>indeterminate | 202403L |
| [ð](#tab:cpp.cond.ha-row-6)<br>likely | 201803L |
| [ð](#tab:cpp.cond.ha-row-7)<br>maybe_unused | 201603L |
| [ð](#tab:cpp.cond.ha-row-8)<br>no_unique_address | 201803L |
| [ð](#tab:cpp.cond.ha-row-9)<br>nodiscard | 201907L |
| [ð](#tab:cpp.cond.ha-row-10)<br>noreturn | 200809L |
| [ð](#tab:cpp.cond.ha-row-11)<br>unlikely | 201803L |

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L496)

The#ifdef, #ifndef, #elifdef, and #elifndef directives, and
the defined conditional inclusion operator,
shall treat __has_include, __has_embed, and __has_cpp_attribute as if they were the names of defined macros[.](#7.sentence-1)

The identifiers __has_include, __has_embed, and __has_cpp_attribute shall not appear in any context not mentioned in this subclause[.](#7.sentence-2)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L506)

Each preprocessing token that remains (in the list of preprocessing tokens that
will become the controlling expression)
after all macro replacements have occurred
shall be in the lexical form of a [token](lex.token "5.10 Tokens [lex.token]")[.](#8.sentence-1)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L512)

Preprocessing directives of the forms

# if  [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt  
# elif  [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt

check whether the controlling constant expression evaluates to nonzero[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L522)

Prior to evaluation,
macro invocations in the list of preprocessing tokens
that will become the controlling constant expression
are replaced
(except for those macro names modified by thedefined unary operator),
just as in normal text[.](#10.sentence-1)

If replacement of macros in the preprocessing tokens following the sequence__has_embed ( and before a matching ) (possibly produced by macro expansion)
encounters a preprocessing token that is one of the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s*limit, prefix, suffix, or if_empty and that [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is defined
as a macro ([[cpp.replace.general]](cpp.replace.general "15.7.1 General")), the program is ill-formed[.](#10.sentence-2)

If the preprocessing tokendefined is generated as a result of this replacement process
or use of thedefined unary operator does not match one of the two specified forms
prior to macro replacement,
the program is ill-formed, no diagnostic required[.](#10.sentence-3)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L547)

After all replacements due to macro expansion and
evaluations of[*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")*s*, and[*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")*s* have been performed,
all remaining identifiers and keywords,
except fortrue andfalse,
are replaced with the [*pp-number*](lex.ppnumber#nt:pp-number "5.7 Preprocessing numbers [lex.ppnumber]")0,
and then each preprocessing token is converted into a token[.](#11.sentence-1)

[*Note [3](#note-3)*:

An [alternative
token](lex.digraph "5.9 Alternative tokens [lex.digraph]") is not an identifier,
even when its spelling consists entirely of letters and underscores[.](#11.sentence-2)

Therefore it is not subject to this replacement[.](#11.sentence-3)

â *end note*]

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L570)

The resulting tokens comprise the controlling constant expression
which is evaluated according to the rules of [[expr.const]](expr.const "7.7 Constant expressions") using arithmetic that has at least the ranges specified
in [[support.limits]](support.limits "17.3 Implementation properties")[.](#12.sentence-1)

For the purposes of this token conversion and evaluation
all signed and unsigned integer types
act as if they have the same representation as, respectively,intmax_t or uintmax_t ([[cstdint.syn]](cstdint.syn "17.4.1 Header <cstdint> synopsis"))[.](#12.sentence-2)

[*Note [4](#note-4)*:

Thus on an
implementation where std​::​numeric_limits<int>​::​max() is 0x7FFF and std​::​numeric_limits<unsigned int>​::​max() is 0xFFFF,
the integer literal 0x8000 is signed and positive within a #if expression even though it is unsigned in [translation phase
7](lex.phases "5.2 Phases of translation [lex.phases]")[.](#12.sentence-3)

â *end note*]

This includes interpreting [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s* according to the rules in [[lex.ccon]](lex.ccon "5.13.3 Character literals")[.](#12.sentence-4)

[*Note [5](#note-5)*:

The associated character encodings of literals are the same
in #if and #elif directives and in any expression[.](#12.sentence-5)

â *end note*]

Each subexpression with typebool is subjected to integral promotion before processing continues[.](#12.sentence-6)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L596)

Preprocessing directives of the forms

# ifdef  [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt  
# ifndef  [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt  
# elifdef  [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt  
# elifndef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt

check whether the identifier is or is not currently defined as a macro name[.](#13.sentence-1)

Their conditions are equivalent to#if defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),#if !defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),#elif defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"), and#elif !defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),
respectively[.](#13.sentence-2)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L616)

Each directive's condition is checked in order[.](#14.sentence-1)

If it evaluates to false (zero),
the group that it controls is skipped:
directives are processed only through the name that determines
the directive in order to keep track of the level
of nested conditionals;
the rest of the directives' preprocessing tokens are ignored,
as are the other preprocessing tokens in the group[.](#14.sentence-2)

Only the first group
whose control condition evaluates to true (nonzero) is processed;
any following groups are skipped and their controlling directives
are processed as if they were in a group that is skipped[.](#14.sentence-3)

If none of the conditions evaluates to true,
and there is a#elsedirective,
the group controlled by the#else is processed; lacking a#else directive, all the groups until the#endifare skipped[.](#14.sentence-4)[124](#footnote-124 "As indicated by the syntax, a preprocessing token cannot follow a #else or #endif directive before the terminating new-line character. However, comments can appear anywhere in a source file, including within a preprocessing directive.")

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L654)

[*Example [1](#example-1)*:

This demonstrates a way to include a library optional facility
only if it is available:#if __has_include(<optional>)# include <optional># if __cpp_lib_optional >= 201603# define have_optional 1# endif#elif __has_include(<experimental/optional>)# include <experimental/optional># if __cpp_lib_experimental_optional >= 201411# define have_optional 1# define experimental_optional 1# endif#endif#ifndef have_optional# define have_optional 0#endif

â *end example*]

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L677)

[*Example [2](#example-2)*:

This demonstrates a way to use the attribute [[acme​::​deprecated]] only if it is available[.](#16.sentence-1)

#if __has_cpp_attribute(acme::deprecated)# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]]#else# define ATTR_DEPRECATED(msg) [[deprecated(msg)]]#endif ATTR_DEPRECATED("This function is deprecated") void anvil(); â *end example*]

[123)](#footnote-123)[123)](#footnoteref-123)

Because the controlling constant expression is evaluated
during translation phase 4,
all identifiers either are or are not macro names â
there simply are no keywords, enumeration constants, etc[.](#footnote-123.sentence-1)

[124)](#footnote-124)[124)](#footnoteref-124)

As indicated by the syntax,
a preprocessing token cannot follow a#else or#endif directive before the terminating new-line character[.](#footnote-124.sentence-1)

However,
comments can appear anywhere in a source file,
including within a preprocessing directive[.](#footnote-124.sentence-2)
