c++ - que - matriz de cadenas en c
¿Cómo puedo declarar un vector miembro de la misma clase? (1)
¿Por qué diablos funciona la siguiente pieza de código?
struct A {
std::vector<A> subAs;
};
A es un tipo incompleto, ¿verdad? Si hubiera un vector de A * s, lo entendería. Pero aquí no entiendo cómo funciona. Parece ser una definición recursiva.
Este paper fue adoptado en C ++ 17, lo que permite utilizar tipos incompletos en ciertos contenedores STL. Antes de eso, era un comportamiento indefinido. Para citar del documento:
En base a la discusión sobre la reunión de Issaquah, logramos el consenso para proceder * con el enfoque - "Contenedores de tipos incompletos", pero limitamos el alcance a
std::vector
,std::list
ystd::forward_list
, como el primer paso.
Y en cuanto a los cambios en el estándar (énfasis mío):
Se puede usar un tipo
T
incompleto al crear unvector
si el asignador cumple los requisitos de compleción del asignador (17.6.3.5.1). T debe completarse antes de que se haga referencia a cualquier miembro de la especialización resultante del vector.
Entonces, ahí lo tiene, si deja el std::allocator<T>
predeterminado std::allocator<T>
en su lugar al crear la instancia de std::vector<T, Allocator>
, entonces siempre funcionará con un tipo T
incompleto de acuerdo con el documento; de lo contrario, depende de que tu Allocator sea instanciable con un tipo T
incompleto.
A es un tipo incompleto, ¿verdad? Si hubiera un vector de A * s, lo entendería. Pero aquí no entiendo cómo funciona. Parece ser una definición recursiva.
No hay recursión allí. En una forma extremadamente simplificada, es similar a:
class A{
A* subAs;
};
Técnicamente, aparte del size
, la capacity
y posiblemente el allocator
, std::vector
solo necesita mantener un puntero a una matriz dinámica de A
a través de su asignador. (Y el tamaño de un puntero se conoce en tiempo de compilación).
Entonces, una implementación puede verse así:
namespace std{
template<typename T, typename Allocator = std::allocator<T>>
class vector{
....
std::size_t m_capacity;
std::size_t m_size;
Allocator m_allocator;
T* m_data;
};
}