Ouaip c'est lui. Par curiosité, t'as posté sur clc++.m ou clc++ ? J'ai pas vu passez ton message ...
Version imprimable
Il est pourtant déjà référencé par google:http://groups.google.com/group/comp....4d4b6c1704f1f#
C'est bien ce que je disais il a pas posté là :p. Je regarde réguliémement que comp.lang.c++.moderated pas std ;)
Bah, faut dire qu'entre un titre pas clair ("Unvirtualization of virtual destructor" ?? Qu'est ce que ça veut dire ce truc ?), aucune mention de la différence de comportement avec une déclaration interne puis externe avec =default, pas de lien vers le thread sur comp.std.c++ et un exemple qui ne compile pas... c'était pas vraiment extraordinaire comme bug report :aie:
Edit : Ha, y a l'air d'avoir un moyen de réouvrir le bug. Je vais faire une nouvelle tentative pour passer le cerbère (parce que bon, il est quand même pas commode ce Paolo Carlini :D)
C'est Arch qui as posté sur comp.std.c++... et marqué un bug comme invalid pour une *, je trouve que c'est un peu de la mauvaise volonté quand même >< !
Titre : [C++0x] =default erases virtual declaration of a destructor.
Explication :
Je l'aurais bien saisi, mais je n'ai pas de compte gcc et j'ai la flemme d'en créer un maintenant. A tout hasard j'ai envoyé un mail à paolo.carlini en lui proposant les modifications ci-dessus et en lui disant qu'on en a discuté ici et sur comp.std.c++.Citation:
Following code
#include <iostream>
struct A {
virtual ~A()=default;
};
struct B : public A {
virtual ~B() {
std::cout << "B destructor\n";
}
};
int main() {
B* b = new B;
A* pA = b;
delete pA;
return 0;
}
outputs nothing, B destructor is not called as if A destructor was not considered as virtual.
However, following code works fine :
#include <iostream>
struct A {
virtual ~A();
};
A::~A()=default;
struct B : public A {
virtual ~B() {
std::cout << "B destructor\n";
}
};
int main() {
B* b = new B;
A* pA = b;
delete pA;
return 0;
}
It outputs "B destrucor".
Beaucoup de nouveau sur le file du bug, notemment le core issue 906 qui clarifie la situation.
Rappelle du lien ers le bug.
Pour ceux qui ont la flemme, mon code initial est illegal, la première solution d'Archi est la bonne.
[edit] Malheureusement, la question de savoir si la defaut-declared syntaxe à plus d'intérêt à être accepté virtual est un autre débat... Qui aura (peut-être ?) lieu sur comp.std.c++. Donc je met le sujet en résolue, à moins qu'on le tienne ouvert pour faire un compte rendu fr de ce qui se dit.
Effectivement, il semblerait qu'il y ait eu du changement depuis et que l'on ne puisse plus faire virtual ~type()=default. Il faut séparer déclaration virtuelle de définition par défaut. Dans la même veine, on ne devrait pas pouvoir faire une définition par défaut si l'accès n'est pas publique :calim2: ou pour un constructeur, s'il est explicit. Comme le dit Arzar, ces limitations diminuent l'intérêt des définitions par défaut...
J'ai continué la discussion dans le fil sur com.std.c++ car ça me parait un peu limitatif comme approche...
[HS]
Je me demandais aussi, comment se fait-il que le n3000, publier en novembre 2009, ne mentionne pas le core-issue, qui date quand même du 27 mai 2009 oO ?
Réécriture hative post retrait des concepts sans doute?
Heu sinon ça me déçoit grandement ce genre de changement qui rends la feature bancale (au moins syntaxiquement, ça fait de la répétition inutile).
Est-ce qu'il y a quelque part une trace de discussion qui leur a amené au point où ils proposent de permettre default uniquement sur une définition extérieure? (si j'ai bien compris)
Je viens de passer sur comp.std.c++, apparemment, le core-issue n'est pas la norme tant que celui-ci ne se trouve pas dans un draft.
En faite, l'équipe gcc a décidé de faire comme disait le core-issue, mais la norme elle n'as rien décidé.
Je rejoint S. Meyers pour dire qu'il y a un problème de "trivialité". En gros, l'esprit du core issue, c'est de dire qu'une fonction "defaulted on first-declaration" est trivial. Donc que lorsqu'on voit une définie avec des =default partout, il s'agit d'une classe potentiellement trivial.
Je trouve cette façon de voir la chose assez stupide. Comme beaucoup ici, je voyais =default un peu comme le moyen de ne plus mettre d'accolade vide... Pas d'écrire quelque chose qu'on n'aurait pas eut besoin d'écrire.
A part pour la beauté du geste, je me voit mal écrire 4 lignes qui ne changeront rien >< !
A vrai dire, avec les restrictions apportées par le core issue, je me demande quel serait l'avantage du =default...
Pour ne prendre que le destructeur (mais on pourrait faire la même remarque pour les autres fonctions qui sont susceptibles d'être déclarée par défaut):
Autrement dit, nous sommes, exactement, dans la même situation que maintenant, à part le fait que nous explicitons le fait qu'il a un comportement considéré comme par défaut dans le respect de la forme canonique de coplien qui s'applique.
- Si le destructeur doit détruire des objets pour lesquels on a eu recours à l'allocation dynamique, on se heurte au même problèmes que pour le comportement actuellement observé: comment le compilateur va-t-il déterminer qu'il doit bel et bien invoquer delete / delete[]
- S'il n'y a pas de membres pointeurs, mais qu'on ne peut pas déclarer le destructeur virtuel (du moins, si cela n'évite pas d'avoir à définir le destructeur), où est l'avantage :question:
- Si le destructeur doit être public, encore une fois, nous ne pourrons pas définir un destructeur non virtuel mais protégé
Alors, si on applique effectivement le core issue, est-il prérérable d'avoir
Code:MaClass::~MaClass() = default;
ouCode:
1
2
3 MaClass::~MaClass() { }
La troisième solution est, à mon sens, la plus mauvaise, mais, entre les deux autres, j'avoue ne pas savoir si je préfère l'une ou l'autre :PCode:
1
2
3 MaClass::~MaClass() = default { }
En réalité, le problème ne se pose que pour les first-line default-declared ou appelle ça comme tu veux. Sinon, tu peux très bien déclarer ou tu veux du moment ou tu ne met pas =default à la déclaration. Virtuel public ou protégé, même châtiment.Citation:
Envoyé par koala
Ta dernière proposition est invalide. Les deux premières sont valides, et "l'esprit" du core est la première écriture.
Déjà là, cela m'ennuie dans le sens où le fait que le destructeur ait un comportement par défaut (appel des destructeurs des membres de la classe) et le fait qu'il soit virtuel (et donc susceptible, grâce à la vtable, d'appeler le destructeur de la classe fille) sont deux points de vues tout à fait orthogonaux:
L'un n'empêche absolument pas l'autre, et le compilateur est tout à fait en mesure de faire la différence.
Il *devrait* donc être en mesure d'implémenter correctement un destructeur déclaré virtuel et par défaut :P
Je m'en doutais :DCitation:
Ta dernière proposition est invalide.
J'ai peut-être mal lu, pour le destructeur privé...Citation:
Les deux premières sont valides, et "l'esprit" du core est la première écriture.
j'avais cru comprendre (mais il faut laisser croire les béguines, hein) que le seul cas où il serait possible de ne pas devoir fournir l'implémentation du destructeur était le destructeur public non virtuel :oops:
J'ai du confondre avec le constructeur explicite (re :oops:), mais, là encore, comme il s'agit de deux concepts orthogonaux, je ne vois pas vraiment ce qui pourrait les empêcher de cohabiter
Quelque par, l'ajout d'un "=default" aux fonctions qui interviennent dans les formes canoniques ne représente, à l'extrême limite qu'un flag non exclusif à prendre en compte lors de l'analyse du code :P
J'avoue que avec les couleurs, les crochets et tout, c'est pas super lisible...
En gros :
En faite, le core 906 posent une sévère différence entre mettre =default dans la définition de la classe ou ailleurs.Code:
1
2
3
4
5
6
7
8
9
10 class illformed { ~illformed() = default; // Pas bien car private }; class correct { ~correct(); }; correct::~correct() = default; //pas de soucis
A vrai dire, je ne vois pas pourquoi ta class illformed serait mal formée...
Encore une fois, ce n'est pas parce que le destructeur est privé et qu'il impose donc certaines restrictions quant à son utilisation que son comportement ne peut pas être totalement trivial dans le sens où il se "contente" de détruire les différents membres dans l'ordre inverse de leur construction.
Encore une fois, l'attribut de visibilité n'est qu'un flag nécessaire pour déterminer dans quelle mesure on peut utiliser la fonction, alors que le comportement par défaut en est un qui permet au compilateur de déterminer qu'il doit fournir le code binaire "classique" (et clairement défini) pour la dite fonction.
C'est un peu comme si tu disais qu'il est interdit d'avoir une fonction qui soit à la fois virtuelle et privée: cela a si peu de sens (parce que ce sont deux concepts totalement orthogonaux) que la technique est régulièrement utilisée avec l'idiome NVI
Fiiiou, il y a eu pas mal de développement en quelques jours. :ccool:
Je retiens surtout l'intervention de Daniel Krügler (qui fait partie du comité) sur comp.std.c++
Les détails du comportement de la syntaxe en =default ne semblent donc pas encore définitivement fixés. Wait & See :DCitation:
Envoyé par Daniel Krügler