В то время как clang компилирует следующую строку, g ++ 6.1 жалуется на разделитель цифр (см. живой пример на колиру):
auto time = 01'23s;
Какой компилятор, если таковой имеется, является правильным в соответствии со стандартом C ++ 14 (N3796)?
В противном случае разрешается использование разделителей цифр (§2.14.2) только в деталях реализации пользовательских литералов (§2.14.8) <chrono>
библиотека (§20.12.5.8)? ИМХО так быть не должно, так как эти литералы определены на unsigned long long
параметры.
Я помню, как Говард Хиннант использовал 10'000s
в качестве примера во время его CppCon 2016 talk «A <chrono>
руководство» (около 42 минут в его разговоре).
(Обратите внимание, что я не собирался кодировать «1 минуту и 23 секунды», то есть только правильно случайно, поскольку восьмеричный литерал 0123 равен 64 + 16 + 3 == 83. Для этого я должен написать
auto time = 1min + 23s;
но это возможное вводящее в заблуждение толкование не является частью вопроса.)
Если вы посмотрите на грамматику, определяемый пользователь целочисленного-буквальная может быть восьмерично-буквальный ud-суффикс, а также восьмеричный литерал определяется как либо 0
или же восьмерично-буквальныйвыбирать восьмеричное-значный.
N4140 §2.14.8
определяемый пользователь-буквальный:
- определяемый пользователь целочисленного-буквальная
- […]
определяемый пользователь целочисленного-буквальная:
- восьмерично-буквальный ud-суффикс
- […]
N4140 §2.14.2
восьмеричный литерал:
0
- восьмерично-буквальныйвыбирать восьмеричное-значный
Так 01'23s
это совершенно действительный литерал.
WLOG для десятичных литералов:
определяемого пользователь целочисленного-буквальный:
десятичный литерал уд-суффикс
десятичный литерал:
ненулевая цифра
десятичный литерал’
выбирать
цифра
То есть да, в UDL допускаются разделители цифр.
Это похоже на ошибку в реализации GCC <chrono>
библиотека, как предложил Аарон МакДейд. Существует (в настоящее время неподтвержденное) сообщение об ошибке: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69905
Libstdc ++ GCC реализует две подписи для 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;
Редактировать:
Как недавно отметил Джонатан Уэйкли в комментариях к сообщению об ошибке,
реализация была выбрана по проекту в связи с
вопрос открытой рабочей группы библиотеки, но не принял во внимание разделители цифр.