#if”中允许哪种表达式(条件包含预处理指令)

发布于 2025-01-29 16:02:37 字数 1613 浏览 3 评论 0 原文

在线许多来源(例如,)说,表达式仅是整数常数表达式。

以下都是整体常数的表达式,没有任何标识符:

#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
如果 constant-expression new-line group opt sub>

以前的所有表达式都符合恒定表达的语法。

稍后再说(在[cpp.cond]中):

1/
控制条件包含的表达式应为整体常数表达式,除非标识符(包括与关键字相同的标识符)如下所述

所述。

8/
在所有宏替换发生后,每个将成为控制表达式的预处理令牌(将成为控制表达式的预处理令牌列表中)的每个预处理令牌应为令牌的词汇形式。

>

所有的预处理令牌似乎都以[lex.token]的形式:

令牌
标识符
关键字
文字
操作员 - 或函数

&lt; =&gt; &gt; ,,] {}, *都是操作员 - 或 - 函数

1 2 0 1.2 ,<代码> 0.0 ,<代码>“” 都是文字

,那么标准的哪一部分排除了这些形式的表达式?允许哪些积分常数表达式?

Many sources online (for example, https://en.cppreference.com/w/cpp/preprocessor/conditional#Condition_evaluation) say that the expression need only be an integer constant expression.

The following are all integral constant expressions without any identifiers in them:

#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

Yet they fail to compile with clang or gcc, so there obviously are some limitations.

The grammar for the #if directive is given in [cpp.pre] in the standard as:

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

All of the previous expressions fit the grammar of constant-expression.

It goes on later to say (in [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.

All of the preprocessing tokens seem to be in the form of [lex.token]:

token:
identifier
keyword
literal
operator-or-punctuator

<=>, >, [, ], {, }, (, ), * are all an operator-or-punctuator

1, 2, 0, 1.2, 0.0, "" are all literals

So what part of the standard rules out these forms of expressions? And what subset of integral constant expressions are allowed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

多彩岁月 2025-02-05 16:02:37

I think that all of these examples are intended to be ill-formed, although as you demonstrate the current standard wording doesn't have that effect.

This seems to be tracked as active CWG issue 1436. The proposed resolution would disqualify string literals, floating point literals and also <=> from #if conditions. (Although <=> was added to the language after the issue description was written.) I suppose it is also meant to disallow lambdas, but that may not be covered by the proposed wording.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文