42

虽然 clang 编译了以下行,但 g++ 6.1 抱怨数字分隔符(参见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 演讲“A tutorial”(在他的演讲中大约 42 分钟)中使用10'000s了一个例子。<chrono>


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

auto time = 1min + 23s;

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

4

3 回答 3

19

如果您查看语法,用户定义的整数文字可以是八进制文字 ud-suffix,而八进制文字定义为0or octal-literal '<sub>opt octal-digit

N4140 §2.14.8

用户定义文字

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

用户定义的整数文字

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

​</p>

N4140 §2.14.2

八进制

  • 0
  • 八进制文字'<sub>选择八进制数字

01'23s一个完全有效的文字也是如此。

于 2016-10-26T12:27:50.477 回答
5
于 2016-10-26T12:28:40.710 回答
5

This seems to be a bug in GCC's implementation of the <chrono> library, as @Aaron McDaid suggested. There is a (currently unconfirmed) bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69905

GCC's libstdc++ implements two signatures for 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...>(); }

The template version giving the error is not required by the standard. When adding

constexpr chrono::seconds
operator""s(unsigned long long __secs)
{ return chrono::seconds{__secs}; }

to the <chrono> header (of my local installation) the error dissappears.

However, GCC's library implementers may have left out this version on purpose, so they can prevent an unwanted unsigned to signed conversion, since seconds are defined as

typedef duration<int64_t> seconds;

Edit:

As recently pointed out by Jonathan Wakely in the comments of the bug report, the implementation was chosen by design in connection with an open Library Working Group issue, but did not take digit separators into account.

于 2016-10-26T14:33:07.883 回答