2010-04-29 13 views
27

Me gustaría definir dentro de una clase una constante cuyo valor es el máximo posible int. Algo como esto:Usando numeric_limits :: max() en las expresiones constantes

class A 
{ 
    ... 
    static const int ERROR_VALUE = std::numeric_limits<int>::max(); 
    ... 
} 

Esta declaración falla al compilar con el siguiente mensaje:

numeric.cpp:8: error: 'std::numeric_limits::max()' cannot appear in a constant-expression numeric.cpp:8: error: a function call cannot appear in a constant-expression

entiendo por qué esto no funciona, pero hay dos cosas parecer extraño para mí:

  1. Me parece una decisión natural utilizar el valor en expresiones constantes. ¿Por qué los diseñadores de idiomas decidieron hacer max() una función que no permite este uso?

  2. Las reclamaciones de especificaciones en 18.2.1 que

    For all members declared static const in the numeric_limits template, specializations shall define these values in such a way that they are usable as integral constant expressions.

    no ¿Quiere decir que yo debería ser capaz de utilizarlo en mi escenario y no se contradice el mensaje de error?

Gracias.

+1

puede utilizar climits http://www.cplusplus.com/reference/clibrary/climits/ – Anycorn

+1

@aaa: Pero 'climits' no funcionará bien con plantillas. – UncleBens

+2

@Uncle por desgracia. en principio puede ajustar define en plantillas, algo de trabajo pero factible. o boost integer_traits Creo que ya los proporciona: 'integer_traits <> :: const_max/const_min' – Anycorn

Respuesta

16

Mientras que el estándar actual carece de apoyo aquí, para este tipo de integrales Boost.IntegerTraits le da el tiempo de compilación constantes de const_min y const_max.

El problema surge de §9.4.2/4:

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions.

Nota que añade:

The member shall still be defined in a name- space scope if it is used in the program and the namespace scope definition shall not contain an initializer.

Como otros ya mencionados numeric_limit s min() y max() simplemente no son expresiones constantes integrales, es decir, constantes de tiempo de compilación.

13

que desee:

#include <limits> 

struct A { 
static const int ERROR_VALUE; 
}; 

const int A::ERROR_VALUE = std::numeric_limits<int>::max(); 

Ponga la clase/struct en una cabecera y la definición en un archivo .cpp.

+2

¿ERR_VALUE definido como se puede utilizar anteriormente como argumento de plantilla? – Anycorn

+2

¿Cuál es la diferencia entre la inicialización dentro de la clase y fuera? Sé que puedo inicializar consts dentro de la clase con valores integrales. Además, debo tener al menos una instancia de dicha clase, ¿verdad? De lo contrario, el compilador podría decidir no inicializarlo? – FireAphis

+0

Etiquetando a lo largo de: ¿no hay aquí ninguna biblioteca (tal vez impulso) que redefina esos valores para que puedan ser utilizados en la programación metatemplate? Tendría sentido tenerlos a nuestra disposición en tiempo de compilación ... –

15

Parece un poco de un defecto ...

En C++ 0x, numeric_limits tendrá todo marcado con constexpr, que significa que será capaz de utilizar min() y max() como constantes en tiempo de compilación.

+0

Para aquellos que se preguntan, aparentemente el soporte para esto fue agregado en Visual Studio 2015. Ahora bien, si pudiera actualizar IT a partir de 2013 ... – Phlucious

4

No se contradice, porque max no está definido static const. Es solo una función miembro estática. Las funciones no pueden ser const, y las funciones de miembros estáticos tampoco pueden tener un const adjunto a la derecha. También hay un double max() en la versión doble de los límites, y en C++ 03 no funcionaría decir static double const max = .... Entonces, para ser consistente, max() es una función para todas las versiones de la plantilla de límite.

Ahora, se sabe que max() no se puede utilizar de esa manera es malo, y C++ 0x ya lo resuelve por lo que es una función constexpr, lo que permite su uso propuesto.

2
  • voy a tratar de responder a usted tanto como yo entendí de su pregunta:

1- Si quieres un const int estática en su programa que se inicia con una función:

int Data() 
{ 
return rand(); 
} 

class A 
{ 
public : 
    static const int ee; 
}; 
const int A::ee=Data(); 

Esto funciona en VS 2008

2- Si desea obtener el número máximo y mínimo para un determinado tipo de datos, a continuación, utilizar estas definiciones INT_MAX, IN T_MIN, LONG_MAX y así sucesivamente ..

3- Sin embargo, si es necesario utilizar este tipo de plantilla WRT, entonces codificar las plantillas usted mismo

template<> 
int MaxData() 
{ 
return INT_MAX; 
} 

y

template<> 
long MaxData() 
{ 
return LONG_MAX ; 
} 

y llamarlos como este

int y=MaxData<int>(); 

4- y si solo se trata de binarios representados Sólo tipos, a continuación, utilizar esto:

template <class T> 
T MaxData(){ 
    return ~(1<<((sizeof(T)*8)-1)); 
} 

y esto

template <class T> 
T MinData(){ 
    return (1<<((sizeof(T)*8)-1)); 
} 

Hope esto le puede ayudar ..

+0

En lugar de usar el valor numérico 8, más bien usar la macro CHAR_BIT de climits (limits.h). – Aconcagua

Cuestiones relacionadas