从C ++ 11开始,就可以创建User Defined Literals。正如预期的那样,可以从这些文字返回复杂的结构。但是,在尝试使用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,说他们找不到operator""_foo.bar
。 MSVC接受它。如果我改为写123_foo .bar()
,all three compilers accept it
谁在这? 123_foo.bar()
是否有效?
一些额外信息:
std::chrono
literals以及我倾向于认为这是GCC和Clang错误,因为.
不是有效标识符的一部分。
答案 0 :(得分:10)
TLDR Clang和GCC是正确的,你不能在用户定义的整数/浮点字面值之后写.
,这是一个MSVC错误。
程序编译后,按顺序经过9 phases of translations。这里需要注意的关键是将源代码lexing(分离)到令牌中,然后再考虑它的语义。
在此阶段,maximal munch生效,即令牌被视为语法上有效的最长字符序列。例如,x+++++y
被定义为x ++ ++ + y
而不是x + ++ ++ y
,即使前者在语义上无效。
那么问题是123_foo.bar
的语法有效序列是什么。在production rules之后获得预处理编号,确切的序列为
pp-number→pp-number identifier-nondigit→...→pp-number identifier-nondigit³→
pp-numbernondigit³→pp-number。 nondigit³→...→pp-numbernondigit⁴。 nondigit³→
pp-数字nondigit⁴。 nondigit³→...→pp-numberdigital²nondigit⁴。 nondigit³→
digit³nondigit⁴。 nondigit³
哪个解析为123_foo.bar
,如错误消息