用户定义的数字文字后可以紧跟一个点吗?

Can user defined numeric literals be immediately followed by a dot?

从 C++11 开始,可以创建 User Defined Literals。正如预期的那样,可以从这些文字中 return 复杂结构。但是,当尝试使用 123_foo.bar():

等运算符时
struct foo {
    int n;
    int bar() const { return n; }
};

constexpr foo operator ""_foo(unsigned long long test)
{
    return foo{ static_cast<int>(test) };
}

int main() {
    return 123_foo.bar();
}

GCC and Clang reject it, saying they can't find an operator""_foo.bar. MSVC accepts it. If I instead write 123_foo .bar(), all three compilers accept it

谁在这儿? 123_foo.bar() 是否有效?


一些额外信息:


我倾向于认为这是一个 GCC 和 Clang 错误,因为 . 不是有效标识符的一部分。

TLDR Clang 和 GCC 是正确的,您不能在用户定义 integer/floating 文字后立即编写 .,这是一个 MSVC 错误。

当一个程序被编译时,它会按顺序经过9 phases of translations。这里要注意的关键是在考虑其语义含义之前将源代码词法化(分离)为标记。

在这个阶段,maximal munch生效,即token被认为是语法上有效的最长字符序列。例如 x+++++y 被词法化为 x ++ ++ + y 而不是 x + ++ ++ y 即使前者在语义上无效。

接下来的问题是 123_foo.bar 的最长句法有效序列是什么。在 production rules 之后的预处理编号,确切的顺序是

pp-number → pp-number identifier-nondigit → ... → pp-number identifier-nondigit³ →
pp-number nondigit³ → pp-number . nondigit³ → ... → pp-number nondigit⁴ . nondigit³ →
pp-number digit nondigit⁴ . nondigit³ → ... → pp-number digit² nondigit⁴ . nondigit³ →
digit³ nondigit⁴ . nondigit³

解析为 123_foo.bar,如错误消息中所示