2012-06-09 11 views
11

Parece que me falta algo más que fundamental. Estoy tratando de usar miembros de la matriz const en tiempo de compilación.Constantes de matriz en tiempo de compilación

const int list[3] = { 2, 5, 7 }; 
const int a = list[2]; // this doesn't error? 

template<int N1, int N2> 
struct tmax { 
    enum { value = ((N1 > N2) ? N1 : N2) }; 
}; 

const int b = tmax<2,4>::value; 
const int c = tmax<list[0],list[1]>::value; // error is here 

int main() 
{ 
    return 0; 
} 

Errores:

prog.cpp:10:24: error: 'list' cannot appear in a constant-expression 
prog.cpp:10:30: error: an array reference cannot appear in a constant-expression 

Aquí está la relevent IDEOne link

Entonces, ¿por qué no funciona? ¿Qué me estoy perdiendo? ¿Qué debería hacer de manera diferente?

Respuesta

9

El hecho de que un objeto sea const no significa que sea una expresión constante de tiempo de compilación.

main.cpp:10:20: error: non-type template argument is not a constant expression 
const int c = tmax<list[0],list[1]>::value; // error is here 
        ^~~~~~~ 
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression 
main.cpp:1:11: note: declared here 
const int list[3] = { 2, 5, 7 }; 
     ^

Esta es la razón de constexpr:

constexpr int list[3] = { 2, 5, 7 }; 

template<int N1, int N2> 
struct tmax { 
    enum { value = ((N1 > N2) ? N1 : N2) }; 
}; 

const int b = tmax<2,4>::value; 
const int c = tmax<list[0],list[1]>::value; // works fine now 

En cuanto a por qué esto funciona:

const int a = list[2]; // this doesn't error? 

inicializar una variable const no requiere una expresión constante:

int foo(int n) { 
    const int a = n; // initializing const var with a non-compile time constant 
+0

Me imaginé que constexpr sería útil, y ahora que lo veo, veo que tiene una adopción más amplia de lo que pensaba. Dicho esto, un poco más de una explicación de por qué la declaración de const int a funciona pero la lista [1] específicamente no sería apreciada. Gracias. –

+0

OK, por lo que visual studio 2012 no tiene previsto admitir constexpr. Alguien tiene otras soluciones? NO TENGO que usarlo para esto, pero sería bueno. –

+0

@ std''OrgnlDave Agregué más de los diagnósticos del compilador que explica exactamente por qué la lista [1] no es una expresión constante. – bames53

4

Las expresiones no son expresiones constantes si contienen una cualquiera de una serie de subexpresiones no permitidas. Una de tales clases de sub-expresiones no permitidos es:

  • un lvalue-a-rvalue de conversión (4,1) a menos que se aplica a
    • un glvalue de tipo integral o enumeración que se refiere a un no medicamentos basados ​​en objeto const con un inicialización precedente, inicializado con una expresión constante, o
    • un glvalue de tipo literal que se refiere a un objeto no volátil se define con constexpr, o que se refiere a un subobjeto de un objeto tal o
    • un glvalue de tipo literal que hace referencia a un objeto temporal no volátil cuya duración no ha finalizado , se inicializó con una expresión constante;

En particular, mientras que el nombre de un objeto const de enum o tipo intergral inicializado con un inicializador constante forma una expresión constante (leer su valor es lo que causa la lvalue-a-rvalue conversión), los subelementos de un objeto agregado const (como list en su ejemplo, una matriz) no, pero lo haría si se declara constexpr.

const int list[3] = { 2, 5, 7 }; 
const int a = list[2]; 

Esto es válido, pero a no constituye una expresión constante , ya que no se ha inicializado con una expresión constante.

Al cambiar la declaración de list (no tenemos que cambiar la declaración de a), podemos hacer que a forme una expresión constante.

constexpr int list[3] = { 2, 5, 7 }; 
const int a = list[2]; 

Como list[2] es ahora una expresión constante, a es ahora un objeto const de tipo intergral inicializado con una expresión constante así a ahora se puede utilizar como una expresión constante.

+0

Casi me hace llorar que el estudio visual 2k12 no va a ser compatible con constexpr. Nunca he usado matrices como esta en la metaprogramación de plantillas, pero estaba deseando que ... –

Cuestiones relacionadas