Подтвердить что ты не робот

Разрешены ли 14-значные разделители С++ в пользовательских литералах?

Пока clang компилирует следующую строку, g++ 6.1 жалуется на разделитель цифр (см. живой пример на Coliru):

auto time = 01'23s;

Какой компилятор, если он есть, является правильным в соответствии со стандартом С++ 14 (N3796)?

В противном случае разрешает разделители цифр (§2.14.2) только деталь реализации в пользовательских литералах (§2.14.8) библиотеки <chrono> (§20.12.5.8)? ИМХО это не должно быть, поскольку эти литералы определены на параметрах unsigned long long.

Я помню, как Говард Хиннант использовал 10'000s в качестве примера во время беседы CppCon 2016" Учебное пособие <chrono> (примерно 42 минуты в его разговоре).


(Пожалуйста, обратите внимание, что я не собирался вводить код "1 минута и 23 секунды", который корректен только с ошибкой, так как восьмеричный литерал 0123 равен 64 + 16 + 3 == 83 Для этого я должен написать

auto time = 1min + 23s;

но эта возможная вводящая в заблуждение интерпретация не является частью вопроса.)

4b9b3361

Ответ 1

Если вы посмотрите на грамматику, пользовательский-целочисленный-литерал может быть восьмеричным буквальным ud-суффиксом, а восьмеричный-литерал определяется как 0 или восьмеричный-литерал opt восьмеричный -значное.

N4140 §2.14.8

определяемого пользователя-буквальный:

  • определяемого пользователя целочисленной-буквальный
  • [...]

определяемого пользователя целочисленный-буквальный:

  • восьмеричный литерал ud-suffix
  • [...]

N4140 §2.14.2

восьмеричный литерал:

  • 0
  • восьмеричный opt восьмеричный

Итак, 01'23s - вполне допустимый литерал.

Ответ 2

WLOG для десятичных букв:

[lex.ext]:

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

[lex.icon]:

decimal-literal:               decimal-literal opt цифра

т.е. да, разделители цифр разрешены в UDL.

Ответ 3

Кажется, это ошибка в реализации GCC библиотеки <chrono>, как предположил @Aaron McDaid. Существует (в настоящее время неподтвержденный) отчет об ошибке: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69905

GCC libstdС++ реализует две подписи для 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;

Edit:

Как недавно отметил Джонатан Вакели в комментариях к отчету об ошибке, реализация была выбрана по проекту в связи с открыть задачу рабочей группы библиотеки, но не учитывает разделители цифр.