2009-03-13 20 views
8

Si está utilizando una plantilla en C++ que toma un valor entero como parámetro, ¿hay algún requisito en una variable entera utilizada como parámetro que sea diferente de si la variable se usó como parámetro en una llamada a función?¿Cuáles son los requisitos para los parámetros de plantilla C++?

Esta es una continuación de la pregunta here. Específicamente quiero abordar si hay una diferencia de variables WRT declaradas como "extern const int" para funciones o plantillas.

Veo que para algunas cajas de plantilla el valor del parámetro sería necesario en tiempo de compilación. Es esto siempre cierto? ¿Hay alguna manera de especificar, tal vez solo para ciertos usos del valor del parámetro, que el valor se use en tiempo de ejecución?

Respuesta

3

Siempre es el caso que el valor de int se necesita en tiempo de compilación.

Dado que cada instancia de plantilla es una pieza separada de código compilado (incluso para los parámetros de la plantilla entera) ese entero necesita estar disponible cuando se compila (y se debe garantizar que nunca cambia).

Esta es también la razón por la cual es una buena idea no usar parámetros de plantilla enteros cuando va a utilizar una gran cantidad de valores únicos: puede terminar rápidamente con un enorme archivo ejecutable.

13

Lo siguiente es del estándar.

14.3.2.1:

Una plantilla-argumento para un no-tipo, no molde plantilla-parámetro será uno de:

  • una constante-expresión integral de integral o enumeración tipo; o
  • el nombre de un parámetro de plantilla sin tipo; o
  • la dirección de un objeto o función con vinculación externa, incluidas plantillas de función e ID de plantilla de función pero excluyendo miembros de clase no estáticos, expresada como & id-expression donde & es opcional si el nombre hace referencia a una función o array, o si el template-parameter correspondiente es una referencia; o
  • un puntero al miembro expresado como se describe en 5.3.1.

5.19.1:

En varios lugares, C++ requiere expresiones que se evalúan como una constante integral o enumeración: como límites de la matriz (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 miembro estáticos (9.4.2), y como argumentos de plantilla de tipo no integral o enumeración (14.3).

constant-expression: 
      conditional-expression 

Una constante-expresión integral puede implicar sólo literales (2.13), los enumeradores, variables const o miembros de datos estáticos de tipos integrales o de enumeración inicializados con expresiones constantes (8,5), los parámetros de plantilla no de tipo de integral o enumeración tipos y tamaño de expresiones. Los literales flotantes (2.13.3) solo pueden aparecer si se convierten a tipos integrales o de enumeración. Solo se pueden usar las conversiones de tipos a tipos integrales o de enumeración .En particular, excepto en el tamaño de las expresiones, no se usarán funciones, objetos de clase, punteros o referencias, y no se usarán operadores de asignación, incremento, decremento, llamada de función o coma.

Con respecto a su anterior puesto que creen que la esencia en la parte "las variables const ... inicializado con ..." (y no creo que inicializa el exterior que cuenta).

4

Tiene que ser una expresión constante integral. Eso se explica por el documento estándar en 5.19:

Una constante-expresión integral puede implicar sólo literales (2.13), encuestadores, variables const o miembros de datos estáticos de tipo integral o de enumeración inicializados con expresiones constantes (8,5), no tipo de parámetros de plantilla de tipo integral o de enumeración, y tamaño de expresiones. Los literales flotantes (2.13.3) solo pueden aparecer si se convierten a tipos integrales o de enumeración. Solo se pueden usar conversiones de tipos a tipos integrales o de enumeración.

Tenga en cuenta que "integral" es otro término para "entero", pero no es lo mismo que "int". "char" por ejemplo tiene un entero/tipo integral, pero no es el tipo int, obviamente. Así concretamente, se permite

  • 10 or 10L or anything like that
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • por supuesto, cualquier otro parámetro de plantilla como se detalló anteriormente

la siguiente Cualquiera de los que pueden ser utilizado como un argumento de plantilla para un parámetro que tiene un tipo integral de th e tipo correspondiente. Algunas conversiones todavía se aplican sin embargo. Entonces, si quiere un int y pasas un char, automáticamente promueve el char al int. Lo mismo si proporciona un enumerador y quiere un int.

Así que por estas normas, si usted tiene

extern const int SomeName; 

y no ver una definición por la que inicializa esa constante con una expresión constante integral, no puede ser utilizado como un argumento de plantilla. Pero puede usarse como un argumento de función, por supuesto. No es necesario conocerlos en tiempo de compilación porque no son parte de un tipo. En el momento de nombrar a una especialización de plantilla, los argumentos que ha utilizado se convierten en parte del tipo:

MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>! 

Tenga en cuenta que no son otros formas de pasar SomeName como argumento. Sin embargo, todos los cuales pueden no ser aceptados por un parámetro de plantilla entero. Puede aceptar lo anterior mediante un parámetro de referencia, por ejemplo

template<const int& V> struct NowItWorks { }; 

y sería aceptar la SomeName de arriba. Ahora, en lugar de un valor, se ha elegido una ubicación particular que es única en todo el programa (ya que la variable tiene el enlace extern).

Cuestiones relacionadas