2012-06-04 11 views
10

El nuevo concepto literal definido por el usuario en C++ sugiere algunos usos muy interesantes de cadena literales, tales como:¿Pueden los literales definidos por el usuario basados ​​en cadenas estar fuertemente tipados?

"Goodbye %s world"_fmt("cruel"); 
"Goodbye %s world"_fmt(123); // Error: arg 1 must be convertible to const char* 

R"(point = \((\d+), (\d+)\))"_re; // Builds DFA at compile-time. 

typedef table< 
    column<"CustId"_name , std::string>, 
    column<"FirstName"_name, std::string>, 
    column<"LastName"_name , std::string>, 
    column<"DOB"_name  , date  > 
> Customer; 

Sin embargo, cuando construyo este tipo de construcciones en gcc, por ejemplo:

template <char... Chars> Name<Chars...> operator "" _name() { 
    return Name<Chars...>(); 
} 

auto a = 123_name; // OK 
auto b = "abc"_name; // Error 

me sale el siguiente error:

…unable to find string literal operator ‘operator"" _name’ with ‘const char [4]’, ‘long unsigned int’ arguments 

de la lectura de todo, supongo que la forma variadic-plantilla no está disponible para los UDL derivan d de literales de cadena.

  1. ¿Es de hecho el caso que los literales de cadena no se pueden resolver usando el formulario de plantilla variadic?
  2. Si es así, ¿alguien tiene alguna idea de por qué una forma tan útil de UDL se quedó fuera de la norma?
+0

¿Qué es exactamente útil sobre la creación de un nuevo tipo para cada literal, tipos que serían completamente distintos el uno del otro? –

+0

@NicolBolas: en los ejemplos que se muestran, * quieres * literales diferentes para tener diferentes tipos. Además, el tipo final de un literal no sería necesariamente una concatenación ingenua de sus caracteres. Por ejemplo, '" freq:% g Hz "world" _fmt (44000) 'podría resolver algo como' Formatter ("freq:", "Hz") (44000) 'mediante metaprogramación. –

+0

Eso también significaría que * no * puede pasarle algo que no es un número. Por lo tanto, no podría pasarle algo que podría usar 'operator <<' para convertirlo en una secuencia, eliminando así la posibilidad de personalizar los tipos de datos. –

Respuesta

8

Tienes razón. Los literales de cadena no se pueden utilizar con la forma variadic plantilla (§2.14.8/5):

If L is a user-defined-string-literal, let str be the literal without its ud-suffix and let len be the number of code units in str (i.e., its length excluding the terminating null character). The literal L is treated as a call of the form

operator "" X (str, len) 

He barajado a través de los cuadernos de propuestas (la última de las cuales pude encontrar fue N2750) y no pudieron encontrar una explicación por no permitir el uso del formulario de plantilla variadic.

+0

¿Podría ser algo tan trivial como desarrollo concurrente de las dos características que impidieron usar el otro? –

+0

@ Matthieu METRO. No lo creo. No puedo encontrar evidencia de que se desarrollen por separado (siempre están juntos en el mismo documento). Para ser sincero, cuando vi la forma variadica, lo primero que me vino a la mente fue el tipo de ideas que OP muestra en la respuesta. Me gustaría asumir que el comité vio algún problema potencial en esto. O eso o un descuido muy molesto. –

+3

Todos los literales definidos por el usuario que permiten el uso de la forma variadic se limitan al conjunto de caracteres fuente básico (simplemente porque la gramática no permite nada más en ints o flotantes). Los literales de cadena no tienen esa limitación, por lo que con una codificación fuente/ejecución multibyte tienes c-chars en el literal de cadena que pueden no ser representables como caracteres individuales. Eso podría tener algo que ver con la decisión de no permitir la forma variadica con literales de cadena. – bames53

2

N3599, que permite esto, se ha implementado en gcc y clang.

template<class CharT, CharT... chars> 
int operator ""_suffix(){ 
    return 42; 
} 
Cuestiones relacionadas