variable - ¿Se permiten separadores C++ 14 dígitos en literales definidos por el usuario?
¿cuál de las siguientes cadenas es un nombre de variable válido ? (3)
Esto parece ser un error en la implementación de GCC de la biblioteca <chrono>
, como sugirió @Aaron McDaid. Hay un informe de error (actualmente no confirmado): gcc.gnu.org/bugzilla/show_bug.cgi?id=69905
La libstdc ++ de GCC implementa dos firmas para 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...>(); }
El estándar no exige la versión de la plantilla que proporciona el error. Al agregar
constexpr chrono::seconds
operator""s(unsigned long long __secs)
{ return chrono::seconds{__secs}; }
al encabezado <chrono>
(de mi instalación local) el error desaparece.
Sin embargo, los implementadores de bibliotecas de GCC pueden haber omitido esta versión a propósito, por lo que pueden evitar una conversión no deseada no firmada a firmada, ya que los segundos se definen como
typedef duration<int64_t> seconds;
Editar:
Como señaló recientemente Jonathan Wakely en los comentarios del informe de errores, la implementación se eligió por diseño en relación con un problema abierto del Grupo de trabajo de bibliotecas , pero no se tomaron en cuenta los separadores de dígitos.
Mientras clang compila la siguiente línea, g ++ 6.1 se queja del separador de dígitos (ver ejemplo en vivo en Coliru ):
auto time = 01''23s;
¿Qué compilador, si lo hay, es correcto según el estándar C ++ 14 (N3796)?
De lo contrario, ¿está permitiendo separadores de dígitos (§2.14.2) solo un detalle de implementación en los literales definidos por el usuario (§2.14.8) de la biblioteca <chrono>
(§20.12.5.8)? En mi humilde opinión, no debería ser así, ya que estos literales se definen en parámetros de unsigned long long
.
Recuerdo a Howard Hinnant usando 10''000s
como ejemplo durante su conversación de CppCon 2016 "A <chrono>
tutorial" (aproximadamente 42 minutos en su charla).
(Tenga en cuenta que no tenía la intención de codificar "1 minuto y 23 segundos", lo cual es correcto solo por accidente , ya que el octal literal 0123 es 64 + 16 + 3 == 83. Para ello debo escribir
auto time = 1min + 23s;
pero esa posible interpretación engañosa no es parte de la pregunta).
Si nos fijamos en la gramática, el literal entero definido por el usuario puede ser octal-literal ud-sufijo , y octal-literal se define como 0
o octal-literal '' opt octal-digit .
N4140 §2.14.8
definido por el usuario-literal :
- definido por el usuario-entero-literal
- [...]
user-defined-integer-literal :
- octal-literal ud-sufijo
- [...]
1.
N4140 §2.14.2
octal-literal :
0
- octal-literal '' opt octal-digit
Entonces 01''23s
es un literal perfectamente válido.
WLOG para literales decimales:
user-defined-integer-literal:
decimal-literal ud-sufijo
decimal-literal :
dígito distinto de cero
decimal-literal''
opt digit
Es decir sí, los separadores de dígitos están permitidos en UDL.