En el lenguaje de programación C ++ , decltype
es una palabra clave que se usa para consultar el tipo de expresión . Introducido en C ++ 11 , su uso previsto principal es en la programación genérica , donde a menudo es difícil, o incluso imposible, expresar tipos que dependen de los parámetros de la plantilla .
A medida que las técnicas de programación genéricas se hicieron cada vez más populares a lo largo de la década de 1990, se reconoció la necesidad de un mecanismo de deducción de tipo. Muchos proveedores de compiladores implementaron sus propias versiones del operador, normalmente llamado typeof
, y se desarrollaron algunas implementaciones portátiles con funcionalidad limitada, basadas en características de lenguaje existentes. En 2002, Bjarne Stroustrup propuso que se agregara una versión estandarizada del operador al lenguaje C ++, y sugirió el nombre "decltype", para reflejar que el operador produciría el "tipo declarado" de una expresión.
decltype
La semántica de 'fue diseñada para atender tanto a los escritores de bibliotecas genéricas como a los programadores novatos. En general, el tipo deducido coincide con el tipo de objeto o función exactamente como se declara en el código fuente. Al igual que el operador sizeof
[1] , decltype
el operando 'no se evalúa.
Motivación
Con la introducción de plantillas en el lenguaje de programación C ++ y el advenimiento de técnicas de programación genéricas iniciadas por la biblioteca de plantillas estándar , se reconoció la necesidad de un mecanismo para obtener el tipo de una expresión , comúnmente conocida como typeof
. En la programación genérica, a menudo es difícil o imposible expresar tipos que dependen de parámetros de plantilla, [2] [3] en particular el tipo de retorno de instanciaciones de plantilla de función. [2]
Muchos proveedores proporcionan el typeof
operador como una extensión del compilador. [4] Ya en 1997, antes de que C ++ estuviera completamente estandarizado, Brian Parker propuso una solución portátil basada en el sizeof
operador. [4] Su trabajo fue ampliado por Bill Gibbons, quien concluyó que la técnica tenía varias limitaciones y, en general, era menos poderosa que un typeof
mecanismo real . [4] En un artículo de octubre de 2000 del Dr. Dobb's Journal , Andrei Alexandrescu comentó que "tener un typeof haría mucho más fácil escribir y comprender el código de plantilla". [5] También señaló que "typeof y sizeof comparten el mismo backend, porque sizeof tiene que calcular el tipo de todos modos". [5] Andrew Koenig y Barbara E. Moo también reconocieron la utilidad de una typeof
instalación incorporada , con la salvedad de que "usarla a menudo invita a errores sutiles de programación, y hay algunos problemas que no puede resolver". [6] Caracterizaron el uso de convenciones de tipos, como las typedefs proporcionadas por la biblioteca de plantillas estándar , como una técnica más poderosa y general. [6] Sin embargo, Steve Dewhurst argumentó que tales convenciones son "costosas de diseñar y promulgar", y que sería "mucho más fácil ... simplemente extraer el tipo de expresión". [7] En un artículo de 2011 sobre C ++ 0x , Koenig y Moo predijeron que "decltype se utilizará ampliamente para hacer que los programas cotidianos sean más fáciles de escribir". [8]
En 2002, Bjarne Stroustrup sugirió extender el lenguaje C ++ con mecanismos para consultar el tipo de una expresión e inicializar objetos sin especificar el tipo. [2] Stroustrup observó que la semántica de eliminación de referencias ofrecida por el typeof
operador proporcionada por los compiladores GCC y EDG podría ser problemática. [2] A la inversa, un operador de volver un tipo de referencia basado en la lvalue -ness de la expresión se consideró demasiado confuso. La propuesta inicial al comité de estándares de C ++ esbozó una combinación de las dos variantes; el operador devolvería un tipo de referencia solo si el tipo declarado de la expresión incluye una referencia. Para enfatizar que el tipo deducido reflejaría el "tipo declarado" de la expresión, se propuso nombrar al operador decltype
. [2]
Una de las principales motivaciones citadas para la decltype
propuesta fue la capacidad de escribir plantillas de funciones de reenvío perfectas . [9] A veces es deseable escribir una función de reenvío genérica que devuelva el mismo tipo que la función envuelta, independientemente del tipo con el que se instancia. Sin decltype
, generalmente no es posible lograr esto. [9] Un ejemplo, que también utiliza el tipo de retorno final : [9]
int & foo ( int & i ); flotar foo ( flotar & f );plantilla < clase T > Auto transparent_forwarder ( T y T ) - > decltype ( foo ( t )) { retorno foo ( t ); }
decltype
es esencial aquí porque conserva la información sobre si la función envuelta devuelve un tipo de referencia. [10]
Semántica
De manera similar al sizeof
operador, el operando de no decltype
está evaluado. [11] De manera informal, el tipo devuelto por decltype(e)
se deduce de la siguiente manera: [2]
- Si la expresión se
e
refiere a una variable en el ámbito local o del espacio de nombres, una variable miembro estática o un parámetro de función, entonces el resultado es el tipo declarado de esa variable o parámetro. - De lo contrario, si
e
es un valor l ,decltype(e)
esT&
, dondeT
es el tipo de e; si e es un valor x , el resultado esT&&
; de lo contrario, e es un prvalue y el resultado esT
.
Esta semántica fue diseñada para satisfacer las necesidades de los escritores de bibliotecas genéricas, mientras que al mismo tiempo es intuitiva para los programadores novatos, porque el tipo de retorno de decltype
siempre coincide con el tipo de objeto o función exactamente como se declara en el código fuente. [2] Más formalmente, la Regla 1 se aplica a expresiones id-sin paréntesis y expresiones de acceso a miembros de clase. [12] [13] Ejemplo: [12] Nota para agregar líneas para la barra (). Debajo del tipo deducido para "bar ()" es simple int, no const int, porque los valores pr de tipos que no son de clase siempre tienen tipos cv-no calificados, a pesar del tipo diferente declarado estáticamente.
const int && foo (); const int bar (); int i ; estructura A { doble x ; }; const A * a = nueva A (); decltype ( foo ()) x1 ; // el tipo es const int && decltype ( bar ()) x2 ; // el tipo es int decltype ( i ) x3 ; // el tipo es int decltype ( a -> x ) x4 ; // el tipo es double decltype (( a -> x )) x5 ; // el tipo es const double &
La razón de la diferencia entre las dos últimas invocaciones de decltype
es que la expresión entre paréntesis (a->x)
no es una expresión de identificación ni una expresión de acceso a miembros y, por lo tanto, no denota un objeto con nombre. [14] Debido a que la expresión es un valor l, su tipo deducido es "referencia al tipo de expresión", o const double&
. [11]
En diciembre de 2008, Jaakko Järvi planteó al comité una preocupación sobre la incapacidad de usar decltype
para formar una id-calificada , [1] que es inconsistente con la intención que decltype(e)
debería ser tratada "como si fuera un typedef-name ". [15] Al comentar sobre el Borrador formal del Comité para C ++ 0x , el organismo miembro de ISO japonés señaló que "un operador de alcance (: :) no se puede aplicar a decltype, pero debería serlo. Sería útil en el caso de obtener el tipo de miembro (tipo anidado) de una instancia de la siguiente manera ": [16]
vector < int > v ; decltype ( v ) :: value_type i = 0 ; // int i = 0;
Este y otros problemas similares relacionados con la redacción que inhibe el uso de decltype
en la declaración de una clase derivada y en una llamada de destructor , fueron abordados por David Vandevoorde y votados en el documento de trabajo en marzo de 2010. [17] [18]
Disponibilidad
decltype
está incluido en el estándar del lenguaje C ++ desde C ++ 11 . [12] Varios compiladores lo proporcionan como una extensión. Microsoft 's Visual C ++ 2010 y compiladores posteriores proporcionan un decltype
especificador de tipo que se asemeja mucho a la semántica como se describe en la propuesta del Comité de Normas. Se puede usar tanto con código administrado como nativo. [10] La documentación indica que es "útil principalmente para los desarrolladores que escriben bibliotecas de plantillas". [10] decltype
se agregó a la línea principal del compilador GCC C ++ en la versión 4.3, [19] lanzado el 5 de marzo de 2008. [20] decltype
también está presente en Codegear 's C ++ Builder 2009 , [21] el Intel C ++ Compiler , [ 22] y Clang . [23]
Referencias
- ↑ a b Miller, William M. (29 de septiembre de 2009). "Problemas activos del lenguaje básico estándar de C ++, revisión 66" . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 3 de octubre de 2009 .
- ^ a b c d e f g Gregor, Douglas; Järvi, Jaakko; Siek, Jeremy; Stroustrup, Bjarne (28 de abril de 2003). "Decltype y auto" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 28 de agosto de 2015 .
- ^ Kalev, Danny (8 de mayo de 2008). "Limpiar el lío de la sintaxis de la función con decltype " . DevX.com . Consultado el 4 de septiembre de 2009 .
- ^ a b c Gibbons, Bill (1 de noviembre de 2000). Tipo de "operador portátil" . Diario del Dr. Dobb . Consultado el 3 de septiembre de 2009 .
- ^ a b Alexandrescu, Andrei (1 de octubre de 2000). " genérica: Mapeos entre tipos y valores"ón> . Diario del Dr. Dobb . Consultado el 3 de septiembre de 2009 .
- ^ a b Koenig, Andrew; Barbara E. Moo (1 de febrero de 2002). "C ++ más fácil: nombrar tipos desconocidos" . Diario del Dr. Dobb . Consultado el 3 de septiembre de 2009 .
- ^ Dewhurst, Steve (1 de agosto de 2000). "Conocimiento común: un operador de tipo bit a bit, parte 1" . Diario del Dr. Dobb . Consultado el 3 de septiembre de 2009 .
- ^ Koenig, Andrew; Barbara E. Moo (19 de julio de 2011). "4 nuevas funciones útiles en C ++ 0x" . Diario del Dr. Dobb . Consultado el 12 de enero de 2012 .
- ^ a b c Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (12 de octubre de 2004). "Decltype y auto (revisión 4)" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 4 de septiembre de 2009 .
- ^ a b c "Operador decltype" . Microsoft Corporation . Consultado el 4 de septiembre de 2009 .
- ^ a b Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (18 de julio de 2007). "Decltype (revisión 7): redacción propuesta" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 4 de septiembre de 2009 .
- ^ a b c Becker, Pete. "Borrador de trabajo, estándar para lenguaje de programación C ++" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 4 de septiembre de 2009 .
- ^ Miller, William M. (3 de agosto de 2009). "Informes de defectos del lenguaje básico estándar de C ++, revisión 65" . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 15 de septiembre de 2009 .
- ^ Miller, William M. (3 de agosto de 2009). "Problemas cerrados del lenguaje básico estándar de C ++, revisión 65" . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 4 de septiembre de 2009 .
- ^ Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (5 de noviembre de 2006). "Decltype (revisión 6): redacción propuesta" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 3 de octubre de 2009 .
- ^ Miller, William M. (3 de agosto de 2009). "Estado de comentario de C ++ CD1" . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 3 de octubre de 2009 .
- ^ Miller, William M. (29 de marzo de 2010). "Informes de defectos del lenguaje básico estándar de C ++, revisión 69" . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 10 de abril de 2010 .
- ^ Vandevoorde, Daveed (3 de febrero de 2010). "Problemas principales 743 y 950: usos adicionales de decltype (...)" (PDF) . ISO / IEC JTC1 / SC22 / WG21 - El Comité de Normas C ++ . Consultado el 10 de abril de 2010 .
- ^ "Soporte C ++ 0x en GCC" . Fundación de Software Libre . 2009-08-27 . Consultado el 4 de septiembre de 2009 .
- ^ "Serie de versiones GCC 4.3" . Fundación de Software Libre . 2009-08-13 . Consultado el 4 de septiembre de 2009 .
- ^ "Tipo de especificador decltype (C ++ 0x)" . Tecnologías Embarcadero. Archivado desde el original el 8 de julio de 2011 . Consultado el 4 de septiembre de 2009 .
- ^ "estándar, Qstd" . Intel Corporation . Consultado el 4 de septiembre de 2009 .
- ^ Gregor, Douglas (26 de enero de 2011). "Nuevo soporte de funciones C ++ 0x en Clang" . Archivado desde el original el 30 de enero de 2011.
enlaces externos
- Entrada de preguntas frecuentes de C ++ 0x de Bjarne Stroustrup para decltype