2011-07-19 14 views
6

wikipedia (here) da un desenrollado tiempo de compilación del bucle for ....... me preguntaba podemos utilizar un bucle similar para con las declaraciones de plantilla dentro ... por ejemplo ...argumentos de plantilla dentro de un tiempo de compilación desenrollado para el bucle?

es el siguiente bucle válido

template<int max_subdomain> 
void Device<max_sudomain>::createSubDomains() 
{ 
    for(int i=0; i< max_subdomain; ++i) 
    { 
     SubDomain<i> tmp(member); 
     ... 
     // some operations on tmp 
     ... 
    } 
} 

subdominio es una clase que se lleva en el int un parámetro de plantilla y aquí se ha construido con un argumento que es un miembro de la clase de dispositivo.

Gracias por la respuesta chicos ... ahora que sabes lo que quiero ... ¿hay alguna forma de lograr lo que quiero?

que finalmente conseguí lo que quería .............. en lugar de utilizar directamente el bucle for ... se puede utilizar en su lugar el Boost::MPL for_each construct. Todavía no lo he implementado, pero supongo que esto proporciona una manera de hacer lo que quería .....

Tomé la respuesta de otra pregunta de desbordamiento de pila here ... Sin embargo, el comment a la misma pregunta critica su uso porque sería muy lento (para bucles grandes por supuesto) ... sin embargo ... para bucles que no son grandes, no creo que haya distensión ... probaré el código y dejaré conoce los resultados ....

el uso se ilustra bien en el example

+0

¿Lo has probado? ¿Qué quieres decir con válido? ¿Cuál es la pregunta? –

+0

bueno en realidad ... las cosas son silenciosas y desordenadas en mi código en este momento ... –

+0

@Jayesh, consulte la respuesta editada. Cometí un error en el código de demostración. – iammilind

Respuesta

0

Re-Edit:

Mi respuesta anterior era correcta. He intentado su código, está dando error de compilador. No puede declarar objetos como ese, ya que i no puede seguir siendo una constante de tiempo de compilación (ya que tiene la intención de haceri++). El parámetro template siempre debe ser constantes de tiempo de compilación. Aquí está the demo.

También tenga en cuenta que, el bucle de desenrollado se realiza también para bucles normales, como parte de la optimización por los compiladores. No está limitado a template s.

+1

es probable que lo haya hecho bien la primera vez ... Su demostración no es la misma que el ejemplo que da @Jayesh. En su código, crea una instancia de 'A' con' N', que de hecho es una constante de tiempo de compilación. En el ejemplo de OP, intenta crear una instancia de la plantilla usando 'i', que es una variable regular. Eso no puede funcionar, porque el compilador no puede instanciar clases de tipo desconocido en el momento de la compilación. Entonces, el código del OP no es válido y no se compilará. – eran

+1

@eran, gracias por señalar el error. He vuelto a modificar la respuesta. – iammilind

+0

gracias .... en realidad no traté de usarlo ahora pero ahora lo hice ... y me dio un error también ...... –

7

Hay una solución stadard para esto. Convierta la iteración en recursión.

template<int i> 
void Device::createSubDomains() 
{ 
    SubDomain<i> tmp(member); 
    // some operations on tmp 
    createSubDomains<i-1>(); 
} 
template<> 
void Device<-1>::createSubDomains() 
{ 
    // End of recursion. 
} 

Nota: no se puede utilizar un tiempo de ejecución if(i!=0) createSubDomains<i-1>();.

2017 Nota: ahora se puede utilizar un tiempo de compilación if constexpr(i!=0) createSubDomains<i-1>();

+0

yaa .. lo sabía ... también funciona ..... pero cuando vi el ejemplo de for loop en wiki solo tenía que preguntar ........ gracias por la respuesta de todos modos ... si lo usaré o no depende de algunas otras implementaciones en la clase ... tendré que probarlo y ver ... te dejaré saber cuál elijo y por qué ... –

2

A pesar de que ya se aceptó @iammilind 's respuesta, permítanme proponer otro, porque su razonamiento de por qué no se i tiempo de compilación constante es no era correcto.

Suponga que tiene

template<unsigned int MAX> struct SubDomain {...}; 
    ... 

y desea declarar una instancia de ella ...

SubDomain<i> tmp(member); 

continuación i debe haber un comúnmente denominado tiempo de compilación constante. ¿Que es eso?


Pedantería

La norma asigna el término nontype template argument a argumentos de plantilla que no son tipos (D'OH).

14.3.2 plantilla no de tipo argumentos [temp.arg.nontype]

Una plantilla-argumento para un no-tipo, no molde plantilla-parámetro deberá ser uno de:
- una expresión constante constante de tipo integral o de enumeración; o
- ... [más seguimiento, pero no son relevantes]

derecho en el primer punto contiene una referencia para futuras investigaciones: an integral constant-expression. Esto nos lleva a

5,19 Las expresiones constantes [expr.const]

En varios lugares, C + + requiere expresiones que se evalúan como una constante integral o enumeración: como matriz límites (8,3 .4, 5.3.4), como expresiones de caso (6.4.2), como longitudes de campo de bit (9.6), como inicializadores de enumerador (7.2), como inicializadores de miembros estáticos (9.4.2), y como integrantes o enumeración argumentos de plantilla sin tipo (14.3).

Entonces, la clave es:

Una constante-expresión integral puede implicar sólo literales (2.13), enumeradores, variables const o miembros de datos estáticos de tipos integrales o de enumeración inicializados con expresiones constantes (8.5), plantilla no de tipo parámetros de tipo integral o de enumeración, y tamaño de expresiones.


aplicación Pedantería

Si miramos hacia atrás en su bucle:

for (int i=... 
    ... 
    SubDomain<i> 

entonces ahora podemos observar que i no está permitido allí. ¿Por qué? Porque i NO es un const variable.

El lector que observa ahora podría pensar que se puede eludir esta:

for (int i=... 
     ... 
     const int I = i; 
     SubDomain<I> 

Pero es esto realmente permitido?Negativo, I = i no es una expresión de constante integral , porque i no lo es. Ayuda a darse cuenta de que la regla para expresiones constantes integrales se aplica recursivamente.

Por ejemplo, el siguiente es un código válido:

template <int> void foo() {}  
int main() { 
    const int ccI = 0; 
    const int ccJ = ccI*2; 
    const int ccK = ccJ/4;  
    foo<ccK>(); 
} 

Pero si hacer sólo una parte de la cadena no constante, entonces ccK no se considera integrante constante más:

template <int> void foo() {}  
int main() { 
      int ccI = 0; 
    const int ccJ = ccI*2; // not compile time constant 
    const int ccK = ccJ/4; // same 

    foo<ccK>();    // error 
} 


Sumario

Así, en hu hombre forma legible, argumentos de plantilla que no son tipos, pero los valores (entero), debe ser en tiempo de compilación constante:

  • el inicializador de un tiempo de compilación constante sólo se debe involucrar a otros en tiempo de compilación-constantes
  • un valor literal es una compilación constante de tiempo
  • un valor de enumeración es una compilación constante de tiempo
  • la función de llamadas no dan compilación constantes de tiempo (por algunas razones avanzadas)
Cuestiones relacionadas