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

时间:2016-10-26 12:23:40

标签: c++ c++14 language-lawyer user-defined-literals digit-separator

虽然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;

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

3 个答案:

答案 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:

[lex.ext]

  

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

[lex.icon]

  

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,但没有考虑数字分隔符。