And*_*y G 12 c++ syntax language-lawyer user-defined-literals c-preprocessor
通过C++ 17标准阅读,在我看来,pp-number预处理器和数字文字处理之间存在不一致,例如user-defined-integer-literal,它们被定义为由"上层"语言处理.
例如,pp-number根据预处理器语法正确解析以下内容:
123_e+1
Run Code Online (Sandbox Code Playgroud)
但放在符合C++ 11的代码片段的上下文中,
int operator"" _e(unsigned long long)
{ return 0; }
int test()
{
return 123_e+1;
}
Run Code Online (Sandbox Code Playgroud)
目前的Clang或GCC编译器(我还没有测试过其他编译器)会返回类似这样的错误:
unable to find numeric literal operator 'operator""_e+1'
Run Code Online (Sandbox Code Playgroud)
在那里operator"" _e(...)没有找到,并试图定义operator"" _e+1(...)将是无效的.
似乎这是因为编译器将令牌作为pp-number第一个使用,但是user-defined-integer-literal在解析最终表达式时无法回滚并应用语法规则.
相比之下,以下代码编译正常:
int operator"" _d(unsigned long long)
{ return 0; }
int test()
{
return 0x123_d+1; // doesn't lex as a 'pp-number' because 'sign' can only follow [eEpP]
}
Run Code Online (Sandbox Code Playgroud)
这是标准的正确读数吗?如果是这样,编译器应该处理这个,可以说是罕见的极端案例是否合理?
您已经成为最大咀嚼规则的受害者,该规则使词法分析器采用尽可能多的字符来形成有效的标记。
\n\n[lex.pptoken]p3节对此进行了介绍(强调我的):
\n\n\n\n\n否则,下一个预处理标记是可以构成预处理标记的最长字符序列,即使这会导致进一步的词法分析失败,除非标头名称 ([lex.header]) 仅在 #include 内形成指示。
\n
并包括几个例子:
\n\n\n\n\n[\xe2\x80\x89示例:
\n\nRun Code Online (Sandbox Code Playgroud)\n\n#define R "x"\nconst char* s = R"y"; // ill-formed raw string, not "x" "y"\n\xe2\x80\x94\xe2\x80\x89结束示例\xe2\x80\x89]
\n\n4 [\xe2\x80\x89示例:程序片段0xe+foo 被解析为预处理数字标记(不是有效的浮点或整数文字标记),即使解析为三个预处理标记0xe、+ 和 foo 可能会生成有效的表达式(例如,\n 如果 foo 是定义为 1 的宏)。类似地,程序片段 1E1\n 被解析为预处理数字(一个有效的浮点\n 文字标记),无论 E 是否是宏名称。\xe2\x80\x94\xe2\x80\x89结束示例]
\n\n5[\xe2\x80\x89示例:程序片段 x+++++y 被解析为 x ++ ++ + y,\n 如果 x 和 y 具有整数类型,则违反\n 增量运算符的约束,即使解析 x ++ + ++ y 可能会产生正确的表达式。\xe2\x80\x94\xe2\x80\x89end 示例 \xe2\x80\x89]
\n
此规则会影响其他几个众所周知的情况,例如a+++++b和标记 >= ,需要修复才能允许.
\n\n作为参考,pp-token语法如下:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\npp-number: \n digit \n . digit \n pp-number digit \n pp-number identifier-nondigit \n pp-number \' digit \n pp-number \' nondigit \n pp-number e sign \n pp-number E sign \n pp-number p sign \n pp-number P sign \n pp-number . \n
注意e sign生产,这就是这个案例的问题所在。另一方面,如果你d像第二个例子一样使用,你就不会碰到这个(在 godbolt 上看到它)。
另外添加间距也可以解决您的问题,因为您将不再受到最大咀嚼的影响(请参阅 godbolt 上的直播):
\n\n123_e + 1\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
258 次 |
| 最近记录: |