¿Cómo puedo declarar un vector miembro de la misma clase?


¿Por qué diablos funciona el siguiente 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.

Author: Peter Mortensen, 2017-01-28

1 answers

Este documento fue adoptado en C++17 que permite utilizar tipos incompletos en ciertos contenedores STL. Antes de eso, era un Comportamiento Indefinido. Para citar del documento:

Basado en la discusión sobre la reunión de Issaquah, logramos el consenso para proceder* con el enfoque - " Contenedores de Incompletos Types", pero limita el alcance a std::vector, std::list, y std::forward_list, como primer paso.

Y en cuanto a los cambios en la norma (énfasis mío):

Se puede utilizar un tipo incompleto T al instanciar vector si el el asignador cumple los requisitos de integridad del asignador (17.6.3.5.1). T se completará antes que cualquier miembro de la resultante se hace referencia a la especialización del vector.

Así que, ahí lo tienes, si dejas el predeterminado std::allocator<T> en su lugar al instanciar el std::vector<T, Allocator>, entonces siempre funcionará con un tipo incompleto T de acuerdo de lo contrario, depende de que su Asignador sea instanciable con un tipo incompleto T.


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 de size, capacity y, posiblemente,allocator, std::vector sólo necesita mantener un puntero a una matriz dinámica de A que administra 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;
    };

}
 32
Author: WhiZTiM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-21 11:30:13