2011-12-24 10 views
22

estoy aprendiendo D y he visto un montón de código como este:¿Operador de exclamación?

ushort x = to!ushort(args[1]); 

Asumo que esto arroja args[1] a ushort, pero ¿cuál es la diferencia entre esto y cast(ushort)?

EDITAR: ¿Y qué otros usos tiene el operador de exclamación?

Respuesta

31

En D,

to!ushort(args[1]) 

es la abreviatura de la creación de instancias plantilla

to!(ushort)(args[1]) 

y es similar a

to<ushort>(args[1]) 

en lenguajes como C++/Java/C#.

El signo de exclamación es notar el hecho de que no es un argumento normal, sino un argumento de plantilla.

La notación hace no paréntesis angulares uso porque son ridículamente difícil de analizar correctamente para un compilador (y hacen que la gramática muy sensibles al contexto), lo que hace que sea mucho más difícil de implementar un compilador correcta. Vea here para más información.

El único otro uso que conozco es simplemente la operación 'no' unario (por ejemplo, false == !true) ... No puedo pensar en ningún otro uso en este momento.


En cuanto al reparto:

cast(ushort) es un sin control fundido, por lo que no será una excepción si el valor está fuera de rango.

to!ushort() es un revisado emitido, por lo que arroja una excepción si el valor está fuera del intervalo.

+0

muchas gracias =] ¡excelente respuesta! – thwd

+3

¡Parece que también eso! es más un elenco léxico, por ejemplo,! string (f) es válido para el punto flotante fy el molde (cadena) f - no. –

+5

Me gustaría señalar que técnicamente hablando 'to! Ushort (val)' no es realmente un elenco. Es una conversión usando la función 'std.conv.to'. Se verifica, pero si comienzas a llamarlo yeso, te arriesgas a causar confusión. La conversión solo se realiza con el operador de transmisión. –

3

El signo de exclamación aquí no es un operador, es solo una parte simbólica de la sintaxis explícita de creación de instancias de plantilla (descrita en detalle en here).

std.conv.to (docs) es una plantilla de función para la conversión entre tipos arbitrarios. Se implementa por completo en la biblioteca y no tiene un soporte especial en el idioma. Tiene un alcance más amplio y diferente en comparación con el operador de elenco.

La plantilla to toma dos parámetros de tipo; un tipo "para" y un tipo "de", en ese orden. En su ejemplo, la plantilla se instancia explícitamente con el argumento de tipo único ushort para el parámetro "a", y un segundo argumento de tipo string (suponiendo que args proviene del primer parámetro a main) se deduce automáticamente del argumento de función normal pasado al función (args[1]) como el parámetro "desde".

La función resultante toma un parámetro de cadena y devuelve un ushort analizado de esa cadena, o arroja una excepción si falla. El operador de transmisión no intentará este tipo de conversión de alto nivel.

Tenga en cuenta que si hay más de un parámetro de plantilla explícita, o que el parámetro tiene más de un token en ella (ushort es un único token de palabras clave), debe envolver la lista de parámetros de plantilla en paréntesis:

ushort result; 
result = to!(typeof(result))(args[1]); 

En este ejemplo, typeof, (, result y ) son cuatro tokens separados y, por lo tanto, se requieren los paréntesis.

para responder a su última pregunta, el token ! también se utiliza para el operador unario no, no relacionado con ejemplificaciones plantilla:

bool yes = true; 
bool no = !yes; // 'no' is false 
2

Ya tiene dos excelentes respuestas por jA_cOp y Merhdad. Solo quiero responder directamente a la pregunta OP (¿cuál es la diferencia entre esto y el molde (ushort)?) - La diferencia es que cast(ushort)args[1] no funcionará (no se puede convertir de una cadena a una uint así), mientras que La plantilla to!(type)(param) sabe qué hacer con la cadena y cómo convertirla al tipo primitivo.

+0

muchas gracias, esto tiene sentido. – thwd

Cuestiones relacionadas