válido variable valor siguientes siguiente programacion nombre literales literal las entero cuál cadenas 0x8 c++ c++14 language-lawyer user-defined-literals digit-separator

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:

[lex.ext] :

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

[lex.icon] :

decimal-literal :
dígito distinto de cero
decimal-literal '' opt digit

Es decir sí, los separadores de dígitos están permitidos en UDL.