1
votes

Comment appeler explicitement le destructeur sur un membre d'élément basé sur un modèle

Le code suivant (coller à godbolt si vous le souhaitez) compile

 #include <vector>
 struct node {
     std::vector<node> children;
 };

 void foo(node* bar) {
     bar->children.~std::vector<node>();
 }

Mais si j'utilise un modèle, le compilateur obtient une erreur de syntaxe lorsque je référence explicitement le type de modèle. Pourquoi et existe-t-il une solution de travail?

struct array {
    ~array();
};

struct node {
    array children;
};

void foo(node* bar) {
    bar->children.~array();
}


8 commentaires

Pourquoi avez-vous besoin de faire cela?


D'accord, 42 secondes et j'ai obtenu un -1. Je demande l'illumination C ++. Regardez-le comme un puzzle. Mais il y a un cas d'utilisation pour cela. Je souhaite intégrer une variable membre basée sur un modèle dans une structure Gtk / GObject pré-allouée par le constructeur. Je dois donc invoquer explicitement ctor et dtor.


Eh bien, pourquoi appelleriez-vous le destructeur explicitement?


@Lothar Vous avez donc plus ou moins une simple faute de frappe: coliru.stacked-crooked.com/a/ fd88157baf3c1bf8


@Lothar De plus, votre question ne fournit pas un exemple reproductible minimal , le message d'erreur exact est manquant.


Question éventuellement pertinente: Comment appeler explicitement un destructeur qualifié d'espace de noms? .


@Lothar quel est le cas d'utilisation réel? L'appel explicite d'un destructeur n'est valide que pour quelque chose qui a été alloué avec placement-new . Allouez-vous un bloc de mémoire brute et appelez-vous placement-new pour le constructeur vector sur ce bloc? Cela n'a pas de sens dans le code fourni.


Oui, j'utilise placement-new. Et comme je l'ai dit, j'utilise des objets C ++ avec des objets GObject (c'est ce que Gtk utilise).


3 Réponses :


3
votes

Clang est plus utile avec le message d'erreur: `

 <source>:7:20: error: '~' in destructor name should be after nested name specifier
 bar->children.~std::vector<node>();`

Donc, fondamentalement, vous devrez vous fier à ADL (je ne suis pas un gourou, alors peut-être que c'est le mauvais nom pour le truc vous utilisez pour le faire fonctionner :)) ici, et appelez: bar->children.~vector();


0 commentaires

0
votes

Selon [class.dtor] / 14 :

Dans un appel de destructeur explicite, le destructeur est spécifié par un ~ suivi d'un type-name ou decltype-specifier qui désigne le type de classe du destructeur.

Supprimez donc le std :: dans l'appel explicite. Cependant, l'appel explicite d'un destructeur n'est requis que dans certains cas, comme l'utilisation de placement new pour allouer de la mémoire. Consultez cette FAQ réponse .


0 commentaires

3
votes

À partir de C ++ 17 , vous pouvez utiliser std :: destroy_at :

template<class T>
void destroy_at(T* p) { p->~T(); }

Avant C ++ 17 , une telle fonction peut être facilement implémentée manuellement (en dehors de l'espace de noms std , bien sûr) comme:

std::destroy_at(&bar->children);

L'utilisation est à mon humble avis beaucoup plus agréable que d'appeler explicitement destructor, ce qui pose des problèmes avec les espaces de noms. Voir, par exemple, Comment appeler explicitement un destructeur qualifié d'espace de noms? .


0 commentaires