¿Cómo saber si un tipo genérico T tiene un constructor adecuado para su uso?
Estoy implementando una lista doblemente enlazada que tiene nodos centinelas como cabeza y cola, digamos que esta clase se llama “List”. “Node” es una estructura privada dentro de “List”. Esta clase tiene un método privado “Init” para inicializar los nodos de la cabeza y la cola, que se invoca en los constructores de “List”.
template<typename t="">
class List {
public:
List() {
Init();
}
...
private:
struct Node {
T data;
Node* prev;
Node* next;
// Constructores
};
size_t size;
Node* head;
Node* tail;
void Init() {
// Los códigos generan un problema si las instancias de T no tienen un constructor predeterminado.
head = new Node;
tail = new Node;
head->prev = nullptr;
head->next = tail;
tail->prev = head;
tail->next = nullptr;
size = 0;
}
};
Ahora, la pregunta es, si las instancias de “T” no tienen un constructor predeterminado, no puedo crear nodos centinelas utilizando “head = new Node;” y “tail = new Node;”. El operador “new” siempre asigna una parte de memoria y la construye. Al construir el objeto “Node”, debe usar algún constructor de “T” para inicializar el campo “data” en “Node”.
¿Hay alguna manera de inspeccionar qué constructores (excepto los constructores de copia y movimiento) de “T” puedo usar para construir la variable “data” de tipo “T”? ¿O solo puedo inicializar los campos “prev” y “next” en “Node”, dejando el campo “data” sin inicializar?
davy.ai
Si las instancias de
T
no tienen un constructor por defecto, la única forma de construir el campodata
enNode
es utilizar un constructor deT
. Si los constructores deT
no se conocen de antemano, la única opción es requerir que un constructor paraT
se pase al constructor deList
. Este constructor puede ser utilizado para construir el campodata
enNode
. Alternativamente, se puede dejar el campodata
sin inicializar y proporcionar un método separado para inicializarlo después de que el objetoNode
haya sido construido. Este método puede ser llamado desde el métodoInit
deList
.