En PHP y C #, las constantes se pueden inicializar a medida que se declaran:
class Calendar3
{
const int value1 = 12;
const double value2 = 0.001;
}
Tengo la siguiente declaración de C ++ de un functor que se usa con otra clase para comparar dos vectores matemáticos:
struct equal_vec
{
bool operator() (const Vector3D& a, const Vector3D& b) const
{
Vector3D dist = b - a;
return ( dist.length2() <= tolerance );
}
static const float tolerance = 0.001;
};
Este código compilado sin problemas con g ++. Ahora, en modo C ++ 0x (-std = c ++ 0x), el compilador g ++ genera un mensaje de error:
error: 'constexpr' necesario para la inicialización en clase del miembro de datos estáticos 'tolerancia' de tipo no integral
Sé que puedo definir e inicializar este static const
miembro fuera de la definición de clase. Además, un miembro de datos constantes no estáticos se puede inicializar en la lista de inicializadores de un constructor.
¿Pero hay alguna forma de inicializar una constante dentro de la declaración de clase como es posible en PHP o C #?
Actualizar
Usé la static
palabra clave solo porque era posible inicializar tales constantes dentro de la declaración de clase en g ++. Solo necesito una forma de inicializar una constante en una declaración de clase, sin importar si se declaró como static
o no.
I used static keyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as static or not.
Esa es la forma incorrecta de decidir si un miembro debería serlostatic
o no. Nunca dejes que la pereza léxica decida la semántica de tu código.That's the wrong way to decide whether a member should be static or not.
No estoy de acuerdo Creo que eso no importa para los miembros constantes.static
miembro no constante con información específica de la instancia. El hecho de que haya decidido que su constante es una propiedad del tipo en lugar de una instancia específica es la razón para hacerlostatic
, no porque le apeteciera un atajo de escritura.struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };
Todo lo que puede serconst
debe serconst
; que se aplica tanto a los miembros como a losstatic
nostatic
miembros.Respuestas:
En C ++ 11,
static
los miembros que no son de datos,static constexpr
los miembros de datos ystatic const
los miembros de datos de tipo integral o enumeración pueden inicializarse en la declaración de clase. p.ejstruct X { int i=5; const float f=3.12f; static const int j=42; static constexpr float g=9.5f; };
En este caso, el constructor generado por el compilador inicializa el
i
miembro de todas las instancias de la clase y el miembro se inicializa en . El miembro de datos se inicializa en y el miembro de datos se inicializa en .X
5
f
3.12
static const
j
42
static constexpr
g
9.5
Dado que
float
ydouble
no son de tipo integral o enumeración, dichos miembros deben serconstexpr
, o nostatic
, para que se permita el inicializador en la definición de clase.Antes de C ++ 11, solo
static const
los miembros de datos de tipo integral o enumeración podían tener inicializadores en la definición de clase.fuente
char const n[3]{'a', 'b', 'c'};
también.static const int
, perostatic constexpr float
? ¿qué significafloat and double are not of integral or enumeration type
?La inicialización de variables miembro estáticas distintas de los tipos const int no es C ++ estándar anterior a C ++ 11. El compilador gcc no le advertirá sobre esto (y, no obstante, producirá código útil) a menos que especifique la
-pedantic
opción. A continuación, debería obtener un error similar a:const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]
La razón de esto es que el estándar C ++ no especifica cómo se debe implementar el punto flotante y se deja en manos del procesador. Para sortear esta y otras limitaciones
constexpr
se introdujeron.fuente
Si. Simplemente agregue la
constexpr
palabra clave como dice el error.fuente
Si solo lo necesita en un método, puede declararlo localmente estático:
struct equal_vec { bool operator() (const Vector3D& a, const Vector3D& b) const { static const float tolerance = 0.001f; Vector3D dist = b - a; return ( dist.length2() <= tolerance ); } };
fuente
Me encontré con problemas reales con esto, porque necesito el mismo código para compilar con diferentes versiones de g ++ (el compilador GNU C ++). Entonces tuve que usar una macro para ver qué versión del compilador se estaba usando, y luego actuar en consecuencia, así
#if __GNUC__ > 5 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr #else #define GNU_CONST_STATIC_FLOAT_DECLARATION const #endif GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;
Esto usará 'const' para todo lo anterior a g ++ versión 6.0.0 y luego usará 'constexpr' para g ++ versión 6.0.0 y posteriores. Esa es una suposición de la versión donde se produce el cambio, porque francamente no me di cuenta de esto hasta la versión 6.2.1 de g ++. Para hacerlo bien, puede que tenga que mirar la versión menor y el número de parche de g ++, así que consulte
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
para obtener detalles sobre las macros disponibles.
Con gnu, también podría seguir usando 'const' en todas partes y luego compilar con la
-fpermissive
bandera, pero eso da advertencias y me gusta que mis cosas se compilen limpiamente.No es genial, porque es específico de los compiladores gnu, pero sospecho que podrías hacer algo similar con otros compiladores.
fuente