用户定义的文字中是否允许使用C++ 14位分隔符?

Ren*_*ter 42 c++ language-lawyer user-defined-literals c++14 digit-separator

当clang编译以下行时,g ++ 6.1会抱怨数字分隔符(请参阅Coliru上的实例):

auto time = 01'23s;
Run Code Online (Sandbox Code Playgroud)

根据C++ 14标准(N3796),哪个编译器(如果有)是正确的?

否则,允许数字分隔符(§2.14.2)只是<chrono>库的用户定义文字(§2.14.8)中的实现细节(§20.12.5.8)?恕我直言,它应该不是,因为这些文字是在unsigned long long参数上定义的.

我记得Howard Hinnant10'000s在他的CppCon 2016演讲"A <chrono>tutorial"(在他的演讲中大约42分钟)中作为一个例子.


(请注意,我不打算编码"1分23秒",这只是偶然的,因为八进制文字0123是64 + 16 + 3 == 83.为此我应该写

auto time = 1min + 23s;
Run Code Online (Sandbox Code Playgroud)

但是这种可能误导性的解释不是问题的一部分.)

krz*_*zaq 19

如果你看一下语法,用户定义的整数字面可以八进制字面UD-后缀,和八进制文字被定义为0八进制字符' 选择八进制数字.

N4140§2.14.8

user-defined-literal:

  • 用户定义的整数字面
  • [...]

user-defined-integer-literal:

  • 八进制文字ud后缀
  • [...]

N4140§2.14.2

八进制:

  • 0
  • 八进制' 选择八进制数字

01'23s是一个完全有效的文字.


Col*_*mbo 5

用于十进制文字的WLOG:

[lex.ext]:

user-defined-integer-literal:
    decimal-literal ud-suffix

[lex.icon]:

decimal-literal:
    非零位
    十进制文字的   opt   数字

也就是说,UDL中允许使用数字分隔符.


Ren*_*ter 5

<chrono>正如@Aaron McDaid建议的那样,这似乎是GCC实施图书馆的一个错误.有一个(目前未经证实的)错误报告: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...>(); }
Run Code Online (Sandbox Code Playgroud)

标准不要求提供错误的模板版本.添加时

constexpr chrono::seconds
operator""s(unsigned long long __secs)
{ return chrono::seconds{__secs}; }
Run Code Online (Sandbox Code Playgroud)

<chrono>标题(我的本地安装)错误消失.

但是,GCC的库实现者可能故意省略了这个版本,因此它们可以防止不需要的无符号签名转换,因为秒被定义为

typedef duration<int64_t> seconds;
Run Code Online (Sandbox Code Playgroud)

编辑:

正如Jonathan Wakely最近在错误报告的评论中指出的那样,实施是通过设计选择与 开放式图书馆工作组问题相关联的,但没有考虑数字分隔符.