将用户定义字面量与方法调用相结合

6
我想知道为什么我不能像这样编写代码:
constexpr double radius = 27_km.to_miles(); // _km returns Distance instance 
                                            // which has to_miles()

无论是GCC 4.8.1还是Clang 3.4都会报错,除非我将27_km用括号括起来,否则它们都找不到文字字面量的运算符operator"" _km.to_miles

constexpr double radius = (27_km).to_miles(); // fine

根据我对标准的2.14.8节的理解,UDL后缀不能包含句点。那么编译器为什么会解析这段代码呢?它们是正确的还是有bug?

编辑:您可以在此处查看完整示例(使用不同的UDL和方法名称):http://ideone.com/rvB1pk


我甚至不知道C++11的这个特性,谢谢! - orlp
1
你能展示一个产生错误的完整例子吗? - Jesse Good
我已经添加了一个示例链接。 - Alex Korban
这个版本可在clang++3.4上编译: 30_au .to_light_years(); (注意空格)-- 这有点奇怪。 - dyp
@DyP:GCC 4.8.1也是同样的情况。您也可以在变量名称后面插入空格,这样并不奇怪。 - Alex Korban
1
我并不是说插入一个空格就能使它工作很奇怪(我怀疑它会工作,尝试了一下,成功了),但奇怪的是30_au.to_light_years()30_au .to_light_years()[有一个空格]之间存在差异。我同意Jerry Coffin的分析,这可能是一个错误。 - dyp
2个回答

3

UDL的后缀应该是一个普通标识符(带有下划线前缀),所以在我看来这似乎是一个错误。


2
这可能是一个词法分析器问题。用户定义的文字量应该被解析为单个块——数字加后缀是一个整体标记。对于数字文字量,它可以含有连字符 '.' 的字符。请查阅标准最新草案中的 pp-number:2.10 节 - lex.ppnumber。逐步了解预处理器(词法分析器)如何扫描令牌:
30_au.to_light_years()

digit
digit
identifier-nondigit
.
identifier-nondigit x 14
( breaks the spell

因此,预处理器30_au.to_light_years视为一个巨大的奇怪(浮点)数字。然后,在数字解析阶段稍后,我们看到digit,digit,identifier-nondigit ...。此时,从“-”开始的余数被作为后缀标识符传递。
请记住,数字文字是在预处理器标记化之后解释的。
我认为这实际上不是一个缺陷。

在查看了第2.10节之后,我同意 - 这似乎不是一个缺陷,尽管它很不方便! - Alex Korban
@AlexKorban:在查看了§2.2/7之后,我持有不同意见。"分析和翻译记号的过程有时可能会导致一个记号被一系列其他记号所取代"。作为一个单一的预处理器记号开始并不意味着它在整个编译过程中仍然是一个单一的记号。 - Jerry Coffin
@JerryCoffin:那个注释特别指的是14.2(“模板特化的名称”),似乎是关于>>的消歧义。所以在我看来,emsr的解释仍然是正确的。我有什么遗漏吗? - Alex Korban
@AlexKorban:是的,我也这样认为——这只是提到一种可能性的参考,并不能将其限制在那一个可能性上。 - Jerry Coffin
@JerryCoffin:我猜可以这样解释。希望你是正确的,因为这意味着将来可能不必在括号中包含文字常量! - Alex Korban

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接