Comment puis-je déclarer un vecteur membre de la même classe?

Pourquoi le code suivant fonctionne-t-il?

struct A { std::vector subAs; }; 

A est un type incomplet, non? S’il y avait un vecteur de A *, je comprendrais. Mais ici je ne comprends pas comment ça marche. Cela semble être une définition récursive.

Ce document a été adopté en C ++ 17, qui permet d’utiliser des types incomplets dans certains conteneurs STL. Avant cela, c’était le comportement indéfini. Pour citer l’article:

Sur la base de la discussion à la réunion d’Issaquah, nous avons atteint le consensus pour procéder * avec l’approche – «Conteneurs de types incomplets», mais limiter la scope à std::vector , std::list et std::forward_list , comme le premier pas.

Et pour ce qui est des modifications apscopes à la norme (c’est moi qui souligne):

Un type T incomplet peut être utilisé lors de l’instanciation du vector si l’ allocateur satisfait aux exigences d’allocation-complétude (17.6.3.5.1). T doit être complet avant que tout membre de la spécialisation de vecteur résultant soit référencé.

Donc, vous l’avez, si vous laissez le std::allocator par défaut en place lors de l’instanciation du std::vector , alors il fonctionnera toujours avec un type T incomplet selon l’article. sinon, votre Allocator sera instanciable avec un type T incomplet.


A est un type incomplet, non? S’il y avait un vecteur de A *, je comprendrais. Mais ici je ne comprends pas comment ça marche. Cela semble être une définition récursive.

Il n’y a pas de récursivité. Sous une forme extrêmement simplifiée, c’est similaire à:

 class A{ A* subAs; }; 

Techniquement, hormis la size , la capacity et éventuellement l’ allocator , std::vector n’a besoin que d’un pointeur vers un tableau dynamic de A qu’il gère via son allocateur. (Et la taille d’un pointeur est connue au moment de la compilation.)

Ainsi, une implémentation peut ressembler à ceci:

 namespace std{ template> class vector{ .... std::size_t m_capacity; std::size_t m_size; Allocator m_allocator; T* m_data; }; }