`#if`(条件包含预处理器指令)中允许使用哪些类型的表达式

What kinds of expressions are allowed in a `#if` (the conditional inclusion preprocesssor directives)

许多在线资源(例如,https://en.cppreference.com/w/cpp/preprocessor/conditional#Condition_evaluation)说表达式只需要是整数常量表达式。

以下都是不带任何标识符的整型常量表达式:

#include <compare>

#if (1 <=> 2) > 0
#error 1 > 2
#endif

#if (([]{}()), 0)
#error 0
#endif

#if 1.2 < 0.0
#error 1.2 < 0.0
#endif

#if ""[0]
#error null terminator is true
#endif

#if *""
#error null terminator is true
#endif

但是它们无法用 clang 或 gcc 编译,所以显然存在一些限制。

#if 指令的语法在标准 [cpp.pre] 中给出为:

if-group:
# if constant-expression new-line groupopt

前面的所有表达式都符合常量表达式的语法。

它接着说(在[cpp.cond]):

1/
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

8/
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]:

的形式

token:
identifier
keyword
literal
operator-or-punctuator

<=>,>,[,],{,},(,), * 都是 运算符或标点符号

1201.20.0""都是文字

那么标准的哪一部分排除了这些表达形式?哪些整数常量表达式子集是允许的?

我认为所有这些示例都是 ill-formed,尽管正如您所展示的那样,当前的标准措辞没有那种效果。

这似乎被跟踪为有效 CWG issue 1436。提议的决议将取消字符串文字、浮点文字以及 <=> 来自 #if 条件的资格。 (尽管 <=> 是在写完问题描述后才添加到语言中的。)我想这也是为了禁止 lambda,但这可能不在提议的措辞中。