c++ - reales - libro de android studio en español pdf
¿Por qué no se permite la dirección del miembro no estático como parámetro de no tipo de plantilla? (2)
Primero, para usar punteros / referencias a subobjetos, necesitarías poder destrozarlos. Esa es una empresa bastante grande.
Segundo, y probablemente más importante, de N4198 :
La restricción de que la expresión constante debe nombrar un objeto completo se conserva para evitar problemas de aliasing con punteros a subobjetos:
struct A { int x, y; } a; template<int*> struct Z; using B = Z<&a.x + 1>; using C = Z<&a.y>; // Are B and C the same type?
Para citar a Richard Smith ,
La respuesta "sí" es problemática porque hay cosas que puede hacer con un puntero a [
ay
] que tendría un comportamiento indefinido si se realiza en un puntero más allá del final de [ax
] La respuesta "no" es problemática porque (en general Implementaciones) representan la misma dirección.
template <int * ip> struct test {};
struct q {
static int a;
int b;
constexpr q(int b_) : b(b_) {}
};
int i;
constexpr q q0(2);
int main()
{
constexpr test<&i> t1; // Works fine
constexpr test<&q::a> t2; // Works
constexpr test<&q0.b> t3; // Does not work; address of non-static member?
return 0;
}
La declaración de t3 en el fragmento de código anterior falla a pesar de que el argumento de la plantilla &q0.b
se conoce durante el tiempo de compilación. Algunos googlings revelaron que esto no está permitido por la norma (sección 14.3.2):
[Nota: las direcciones de los elementos de la matriz y los nombres o las direcciones de los miembros de la clase no estática no son argumentos de plantilla aceptables.
X <& s.m> x4; // error: dirección de membe no estática
Entonces, ¿por qué exactamente el estándar no lo permite de manera explícita a pesar de que las direcciones de los miembros no estáticos de las variables globales son únicas y conocidas durante el tiempo de compilación?
Reemplace su principal con este pedazo de código
int main(void)
{
constexpr static int bb = 5;
constexpr test<&bb> t;
return 0;
}
y recibirá el error bb no se puede utilizar como un argumento de plantilla porque no tiene vínculos (no debe confundirse con el personal relacionado con el enlazador).
No se puede acceder a los miembros de datos de clase a menos que se haga referencia a ellos a través del objeto, y no se pueden tener en cuenta durante la creación de instancias de plantilla, ya que los miembros de datos no tienen vinculación, es decir, no son símbolos definidos y, por lo tanto, no se pueden usar como argumentos de plantilla.
Dicho esto, haciendo una lectura puede verificar esto:
48: 00000000004006ac 4 OBJECT LOCAL DEFAULT 14 q0
68: 000000000060097c 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
69: 0000000000600978 4 OBJECT GLOBAL DEFAULT 23 q::a
pero no hay q0.b
definido. La alternativa sería nombrar (destrozar) a ninguno de los miembros de la clase estática que eliminaría las capacidades dinámicas del lenguaje.