虽然clang编译了以下行,但g ++ 6.1抱怨数字分隔符(参见live example on Coliru):
auto time = 01'23s;
根据C ++ 14标准(N3796),哪个编译器(如果有)是正确的?
否则,允许数字分隔符(§2.14.2)只是<chrono>
库(§20.12.5.8)的用户定义文字(§2.14.8)中的实现细节?恕我直言,它应该不是,因为这些文字是在unsigned long long
参数上定义的。
我记得Howard Hinnant在他的CppCon 2016 talk "A <chrono>
tutorial"期间使用10'000s
作为例子(在他的谈话中大约42分钟)。
(请注意,我不打算编码“1分23秒”,这是只是偶然正确,因为八进制文字0123是64 + 16 + 3 == 83为此我应该写
auto time = 1min + 23s;
但可能误导性的解释不是问题的一部分。)
答案 0 :(得分:19)
如果查看语法, user-defined-integer-literal 可以是 octal-literal ud-suffix , octal-literal 被定义为0
或八进制文字' opt 八进制数字。
N4140§2.14.8
用户定义字面:
- 用户定义整数字面
- [...]
用户定义整数字面:
- octal-literal ud-suffix
- [...]
N4140§2.14.2
八进制文字:
0
- octal-literal' opt octal-digit
所以01'23s
是完全有效的文字。
答案 1 :(得分:5)
用于十进制文字的WLOG:
user-defined-integer-literal:
decimal-literal ud-suffix
decimal-literal :
非零数字 decimal-literal’
opt 子> 位 强>
即。是的,UDL中允许使用数字分隔符。
答案 2 :(得分:5)
正如@Aaron McDaid建议的那样,这似乎是GCC实施<chrono>
库的一个错误。有一个(目前未经证实的)错误报告: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在错误报告的评论中指出, 实施是通过设计选择的 open Library Working Group issue,但没有考虑数字分隔符。