c++ - sirve - metodo const java
atributos de función pure/const en diferentes compiladores (2)
En primer lugar, es útil tener en cuenta que "const" es una versión más estricta de "puro", por lo que "puro" se puede utilizar como alternativa si un compilador no implementa "const".
Como han mencionado otros, MSVC realmente no tiene nada similar, pero muchos compiladores han adoptado la sintaxis de GCC, incluidos muchos que no definen __GNUC__
(y algunos que a veces lo hacen y otras veces no, según las banderas).
- GCC es compatible con pure since 2.96+ y const desde 2.5.0, en caso de que desee verificar la versión.
- Clang es compatible con ambos; puede usar
__has_attribute(pure)
y__has_attribute(const)
para detectarlas, pero probablemente sea mejor simplemente confiar en la configuración__GNUC__
. Esto también incluye compiladores basados en clang como emscripten y XL C / C ++ 13+. - El compilador Intel C / C ++ admite ambos, pero su documentación es terrible, así que no tengo idea de cuándo se agregaron. 16.0+ es ciertamente seguro.
- Oracle Developer Studio 12.2+ compatible con ambos.
- ARM C / C ++ Compiler 4.1+ (y posiblemente más antiguo) es compatible con pure y const
- IBM XL C / C ++ desde al menos 10.1 .
- TI 8.0+
- TI 7.3+ con --gcc (detectado con
__TI_GNU_ATTRIBUTE_SUPPORT__
) admite ambos. - PGI no lo documenta (AFAICT), pero ambos atributos funcionan (o al menos se ignoran silenciosamente). 17.10+ es seguro, aunque probablemente hayan sido aceptados por mucho más tiempo.
De estos, clang siempre define __GNUC__
y amigos (actualmente a 4.2, IIRC). Intel define __GNUC__
por defecto (aunque se puede suprimir con -no-gcc) como lo hace PGI en modo C ++ (pero no en modo C). Los demás lo tendrás que verificar manualmente.
Oracle Developer Studio también ha sido compatible con pragmas ya que era conocido como Forte Developer 6 . Se usan de forma un poco diferente ya que requieren que especifique el nombre de la función:
/* pure: */
#pragma does_not_write_global_data (funcname)
/* const; SPARC-only until 12.2 */
#pragma no_side_effect (funcname)
TI 6.0+ (al menos) admite un #pragma FUNC_IS_PURE;
pragma en modo C ++ solamente. En el modo C, es #pragma FUNC_IS_PURE(funcname);
.
La mayor parte de esto puede ocultarse detrás de una macro, que es lo que hice en Hedley :
#if /
HEDLEY_GNUC_HAS_ATTRIBUTE(pure,2,96,0) || /
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || /
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || /
HEDLEY_ARM_VERSION_CHECK(4,1,0) || /
HEDLEY_IBM_VERSION_CHECK(10,1,0) || /
HEDLEY_TI_VERSION_CHECK(8,0,0) || /
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || /
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_PURE __attribute__((__pure__))
#elif HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
# define HEDLEY_NO_RETURN _Pragma("FUNC_IS_PURE;")
#else
# define HEDLEY_PURE
#endif
#if HEDLEY_GNUC_HAS_ATTRIBUTE(const, 2, 5, 0) || /
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || /
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || /
HEDLEY_ARM_VERSION_CHECK(4,1,0) || /
HEDLEY_IBM_VERSION_CHECK(10,1,0) || /
HEDLEY_TI_VERSION_CHECK(8,0,0) || /
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || /
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_CONST __attribute__((__const__))
#else
# define HEDLEY_CONST HEDLEY_PURE
#endif
Esto no incluye las variantes que requerirían los nombres de las funciones como argumento, pero aún cubre la gran mayoría de los usuarios, y es seguro usarlos en todas partes.
Si no desea usar Hedley (es un único dominio público / encabezado CC0), no debería ser demasiado difícil reemplazar las macros de la versión interna. Si eliges hacer eso, probablemente deberías basar tu puerto en el repositorio de Hedley en lugar de esta respuesta ya que es más probable que lo mantenga actualizado.
pure es un atributo de función que dice que una función no modifica ninguna memoria global.
const es un atributo de función que dice que una función no lee / modifica ninguna memoria global.
Dada esa información, el compilador puede hacer algunas optimizaciones adicionales.
Ejemplo para GCC:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
En ese ejemplo, el compilador podría optimizar la función calcular para:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum += temp;
return sum;
}
O si su compilador es lo suficientemente inteligente (y no tan estricto sobre los flotadores):
float calculate(float x, unsigned int C) { return C ? sigmoid(x) * C : 0.0f; }
¿Cómo puedo marcar una función de tal manera para los diferentes compiladores, es decir, GCC, Clang, ICC, MSVC u otros?
- GCC: atributos de la función pure / const
- llvm-gcc: admite los atributos GCC pure / const
- Clang: parece apoyarlo (probé un ejemplo simple con los atributos de estilo GCC y funcionó).
- ICC: parece adoptar los atributos de GCC (Disculpa, solo una publicación en el foro).
- MSVC: Parece que no lo admite. ( discussion )
En general, parece que casi todos los compiladores admiten los atributos GCC. MSVC es hasta ahora el único compilador que no los admite (y que tampoco tiene ninguna alternativa).