用户定义的文字是否允许C ++ 14位分隔符?
当clang编译以下代码时,g ++ 6.1会抱怨数字分隔符(请参阅Coliru上的实例 ):
auto time = 01'23s;
哪个编译器(如果有的话)根据C ++ 14标准(N3796)是正确的?
否则,允许数字分隔符(§2.14.2)只是<chrono>
chrono <chrono>
库(§20.12.5.8)的用户定义文字(§2.14.8)中的实现细节? 恕我直言,它应该不是,因为这些文字是在unsigned long long
参数上定义的。
我记得霍华德· 10'000s
(Howard 10'000s
在他的2016年CppCon演讲“A <chrono>
年代<chrono>
教程” (约42分钟的演讲)中以10'000s
为例。
(请注意,我并不打算编码“1分23秒”,这只是偶然的 ,因为八进制文字0123是64 + 16 + 3 == 83。为了这个目的,我应该写
auto time = 1min + 23s;
但是这种可能的误导性解释不是问题的一部分。)
如果您查看语法,则用户定义的整数字面值可以是八进制文字的ud-suffix , 八进制文字可以定义为0
或八进制文字“ opt八进制数字” 。
N4140§2.14.8
用户定义的文字 :
- 用户定义的整数字面
- […]
用户定义的整数文字 :
- 八进制文字ud后缀
- […]
N4140§2.14.2
八进制文字 :
0
- 八进制文字' select八进制数字
所以01'23s
是完全合法的文字。
WLOG十进制文字:
[lex.ext] :
用户定义的整数字面:
十进制文字 ud后缀
[lex.icon] :
十进制文字 :
非零数字
十进制文字'
select数字
也就是说,UDL中允许使用数字分隔符。
这似乎是GCC执行<chrono>
chrono <chrono>
库时的一个错误,正如@Aaron McDaid所build议的。 有一个(目前未经证实的)错误报告: https : //gcc.gnu.org/bugzilla/show_bug.cgi?id = 69905
GCC的libstdc ++为std::chrono_literals
实现了两个签名:
constexpr chrono::duration<long double> operator""s(long double __secs) { return chrono::duration<long double>{__secs}; } template <char... _Digits> constexpr chrono::seconds operator""s() { return __check_overflow<chrono::seconds, _Digits...>(); }
给出错误的模板版本不是标准所要求的。 添加时
constexpr chrono::seconds operator""s(unsigned long long __secs) { return chrono::seconds{__secs}; }
到<chrono>
标题(我的本地安装)错误消失。
但是,GCC的库实现者可能故意忽略了这个版本,所以他们可以防止不需要的无符号签名转换,因为秒被定义为
typedef duration<int64_t> seconds;
编辑:
正如Jonathan Wakely最近在错误报告的评论中指出的那样,这个实现是在devise时select了一个开放的图书馆工作组的问题 ,但没有考虑数字分隔符。