为浮动常量调用伪析构函数的有效语法

Vla*_*cow 9 c++ floating-point syntax pseudo-destructor c++17

考虑以下演示程序。

#include <iostream>

int main()
{
    typedef float T;

    0.f.T::~T();
}
Run Code Online (Sandbox Code Playgroud)

该程序由Microsoft Visual Studio Community 2019.

但是clanggcc发出这样的错误

prog.cc:7:5: error: unable to find numeric literal operator 'operator""f.T'
    7 |     0.f.T::~T();
      |     ^~~~~
Run Code Online (Sandbox Code Playgroud)

如果像这样写表达式,( 0.f ).T::~T()那么所有三个编译器都会编译程序。

所以出现了一个问题:这个记录在0.f.T::~T()语法上有效吗?如果不是,那么什么句法规则被破坏了?

Eri*_*idt 3

数字标记的解析非常粗糙,并且允许许多实际上不是有效数字的东西。在 C++98 中,“预处理数字”的语法(可在 [lex.ppnumber] 中找到)是

pp-number:
    digit
    . digit
    pp-number digit
    pp-number nondigit
    pp-number e sign
    pp-number E sign
    pp-number .
Run Code Online (Sandbox Code Playgroud)

这里,“非数字”是除数字之外可在标识符中使用的任何字符,并且“符号”是+或-。后来的标准将扩展定义以允许单引号 (C++14) 和 p-、p+、P-、P+ (C++17) 形式的序列。

结果是,在该标准的任何版本中,虽然预处理数字需要以数字或句点后跟数字开头,但之后可以跟随任意数字、字母和句点序列。使用最大咀嚼规则,即使不是有效的数字标记,也0.f.T::~T();需要将其标记为。0.f.T :: ~ T ( ) ;0.f.T

因此,该代码在语法上无效