c++ - tipos - puntero como argumento de plantilla sin tipo
punteros en c (2)
- No puede ser una variable, ya que las variables solo se configuran en tiempo de ejecución.
- No puede ser un
constexpr
, ya que el valor de una dirección no puede conocerse en tiempo de compilación; en la mayoría de los casos, solo se solucionará después de la reubicación antes de la ejecución. - Teóricamente podría ser una expresión aritmética (aunque no está permitida en el estándar), pero en el caso común de una dirección de un elemento de matriz, simplemente puede usar
&arr[i]
lugar dearr + i
.
Al responder a esta pregunta ASÍ , encontré en el Estándar (ya C ++ 03, todavía en C ++ 11) que solo puede usar direcciones como argumentos de plantilla sin tipo si son de la forma & id-expression
(más algunas excepciones).
Pero no pude responder por qué este es el caso.
14.3.2 Argumentos de plantilla sin tipo [temp.arg.nontype]
Un argumento de plantilla para un parámetro de plantilla que no sea de tipo y sin plantilla será uno de:
[...]
- una expresión constante (5.19) que designa la dirección de un objeto con almacenamiento estático> duración y enlace externo o interno o una función con enlace externo o interno , incluyendo plantillas de función e ids de plantilla de función pero excluyendo miembros de clase no estáticos, expresados (ignorando paréntesis) como & id-expression , excepto que & puede omitirse si el nombre se refiere a una función o matriz y debe omitirse si el parámetro de plantilla correspondiente es una referencia; [...]
(n3485, énfasis mío)
Ejemplo:
using TFoobar = int (*)();
template < TFoobar tp > struct foo_struct{};
int foobar() { return 42; }
constexpr TFoobar pFoobar = &foobar;
foo_struct < &foobar > o0; // fine
foo_struct < pFoobar > o1; // ill-formed
Supongo que tiene algo que ver con las fases de traducción, es decir, el compilador no sabe mucho sobre las direcciones. Sin embargo, ¿por qué no está permitido? ¿No debería ser posible para el compilador usar algo similar a la sustitución de macro para reemplazar pFoobar
con &foobar
?
Considere las clases Foo<&X>
y Foo<&Y>
, ambas con un miembro estático int Bar
. El vinculador debe poder decir si su programa tiene 1 o 2 objetos de Bar
. Ahora considere que el vinculador también es el responsable más probable de asignar valores a &X
e &Y
Mira el Estándar nuevamente. Como está escrito, el compilador no necesita comunicar la dirección real al vinculador. En cambio, pasa la id-expression
. Los enlazadores ya son bastante capaces de determinar si dos id-expression
son iguales, incluso antes de asignarles una dirección numérica.