Vous pouvez contourner ce problème en ayant une classe HugoCopy
explicite comme ce qui suit
class HugoCopy;
class Hugo {
public:
Hugo() { ... }
Hugo(HugoCopy const&);
explicit Hugo(Hugo const&) { ... }
};
struct HugoCopy {
HugoCopy(Hugo const& hugo)
:hugo(hugo)
{ }
Hugo const& hugo;
};
Hugo::Hugo(HugoCopy const&) { ... }
Maintenant, la sémantique suivante appliquent
Hugo a;
Hugo b = a; // forbidden
Hugo c(a); // allowed
Hugo d = HugoCopy(a); // allowed
Hugo f() {
Hugo a;
return a; // forbidden
return HugoCopy(a); // allowed
}
Vous pouvez également utiliser une fonction de conversion
class Hugo {
public:
Hugo() { ... }
explicit Hugo(Hugo const&) { ... }
};
struct HugoCopy {
HugoCopy(Hugo const& hugo)
:hugo(hugo)
{ }
operator Hugo const&() { return hugo; }
private:
Hugo const& hugo;
};
Cela repose sur un coin subtil de la langue C++ ge. Donc, si vous utilisez ceci, vous savez mieux ce que vous faites ou vous ne le faites pas: Il appelle d'abord la fonction de conversion sur HugoCopy (ou dans le premier cas, le constructeur de Hugo
) pour obtenir un Hugo
/Hugo const&
, et puis initialise l'objet de destination Hugo
avec cet objet Hugo
. GCC n'aime pas le code, mais Clang et Comeau/EDG l'acceptent selon la sémantique ci-dessus.
Quel est le problème avec le code tel quel? – Puppy
Y a-t-il une sorte d'erreur? – jwueller
Pourquoi le constructeur de votre copie est-il explicite? Et pourquoi dire: "Je veux que mon constructeur de copie soit explicite mais je veux aussi effectuer des copies implicites"? Le but de rendre un constructeur explicite est d'empêcher la conversion implicite, mais un constructeur de copie ne "convertit" vraiment rien, il est là pour supporter l'initialisation, le passage d'argument, etc. –