Pourquoi C ++ 11 fait-il que les fonctions " delete
d" participent à la résolution de la surcharge ?
Pourquoi est-ce utile? Ou en d'autres termes, pourquoi sont-ils cachés au lieu d'être entièrement supprimés?
Réponses
Trop de publicités?La moitié de l'objectif de l' = delete
syntaxe est d'être en mesure d'empêcher les gens de l'appel de certaines fonctions avec certains paramètres. C'est principalement pour empêcher les conversions implicites dans certains scénarios spécifiques. Pour empêcher un particulier de surcharge, il doit participer à la résolution de surcharge.
La réponse que vous citez vous donne un parfait exemple:
struct onlydouble {
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
Si delete
supprimé la fonction entièrement, ce qui rendrait l' = delete
de la syntaxe équivalent à ceci:
struct onlydouble2 {
onlydouble2(double);
};
Vous pouvez faire ceci:
onlydouble2 val(20);
C'est légal, C++. Le compilateur va regarder tous les constructeurs; aucun d'entre eux prendre un type entier directement. Mais l'un d'eux peut prendre après une conversion implicite. Donc, il va appeler.
onlydouble val(20);
Ce n'est pas légal de C++. Le compilateur va regarder tous les constructeurs, y compris l' delete
d. Il va voir une correspondance exacte, via std::intmax_t
(qui correspondent exactement à celles tout entier littéral). Ainsi, le compilateur le sélectionner, puis délivrer immédiatement une erreur, car il a choisi un delete
d de la fonction.
= delete
signifie "je défends ce," non seulement, "Cela n'existe pas." C'est beaucoup plus relevé.
J'ai demandé pourquoi le C++ standard dit = supprimer signifie "je défends ce" au lieu de "cela n'existe pas"
C'est parce que nous n'avons pas besoin spécial de la grammaire dire: "cela n'existe pas." Nous en arrivons à ce implicitement, simplement en ne déclarant pas les en particulier "ce" en question. "Je défends cette" représente un concept qui ne peut être atteint sans la grammaire. Nous avons donc obtenu la grammaire de dire "je défends ce" et pas autre chose.
La seule fonctionnalité qui vous permettrait de gagner en ayant un explicite "cela n'existe pas" grammaire serait d'empêcher quelqu'un de plus tard, déclarant qu'elle existe. Et ce n'est pas utile assez pour le besoin de sa propre grammaire.
il n'y a aucune autre façon de déclarer que le constructeur de copie n'existe pas, et son existence peut causer absurde ambiguïtés.
Le constructeur de copie est un membre spécial de la fonction. Chaque classe toujours a un constructeur de copie. Tout comme ils ont toujours une copie de la cession de l'opérateur, constructeur de déplacement, etc.
Ces fonctions existent pas; la question est seulement de savoir si il est légal pour les appeler. Si vous avez essayé de dire qu' = delete
signifie qu'ils n'existent pas, alors la spécification aurait à expliquer ce que cela signifie pour une fonction n'existe pas. Ce n'est pas un concept que la spécification des poignées.
Si vous essayez d'appeler une fonction qui n'a pas été déclarés/encore définie, alors le compilateur générera une erreur. Mais il va d'erreur en raison d'une non défini identifiant, pas en raison d'une "fonction n'existe pas" d'erreur (même si votre compilateur rapports). Plusieurs constructeurs sont tous appelés par la résolution de surcharge, donc de leur "existence" est gérée à cet égard.
Dans tous les cas, il y a une fonction déclarée par l'identificateur, ou un constructeur/destructeur (également déclaré via identifiant, juste un type d'identificateur). La surcharge d'opérateur cache l'identificateur derrière sucre syntaxique, mais il est toujours là.
Le C++ spécification ne peut pas gérer la notion de "fonction qui n'existe pas." Il peut gérer une surcharge d'incompatibilité. Il peut gérer une surcharge de l'ambiguïté. Mais il ne sait pas à propos de ce qui n'existe pas. Donc, = delete
est définie en termes de très loin la plus utile "tentatives d'appel d'échec" plutôt que le moins utile de "faire semblant je n'ai jamais écrit cette ligne."
Et à nouveau, re-lecture de la première partie. Vous ne peut pas le faire avec la fonction "n'existent pas." C'est une autre raison pourquoi il est défini ainsi: parce que l'un des principaux cas d'utilisation de l' = delete
syntaxe est d'être en mesure de forcer l'utilisateur à l'utilisation de certains types de paramètres, explicitement exprimés, et ainsi de suite. En gros, pour déjouer les conversions de type implicites.
Votre suggestion ne serait pas le faire.
Le Travail de C++ Projet de 2012-11-02 ne pas fournir une justification de cette règle, juste quelques exemples
8.4.3 Supprimé définitions [dcl.fct.def.supprimer]
...
3 [ Exemple: On peut appliquer la non-initialisation par défaut et non intégrale de l'initialisation avec
struct onlydouble {
onlydouble() = delete; // OK, but redundant
onlydouble(std::intmax_t) = delete;
onlydouble(double);
};
- fin de l'exemple ]
[ Exemple: On peut empêcher l'utilisation d'une classe dans un certain nombre de nouvelles expressions par supprimés à l'aide de définitions d'un l'utilisateur déclaré nouvel opérateur pour la classe.
struct sometype {
void *operator new(std::size_t) = delete;
void *operator new[](std::size_t) = delete;
};
sometype *p = new sometype; // error, deleted class operator new
sometype *q = new sometype[3]; // error, deleted class operator new[]
- fin de l'exemple ]
[ Exemple: On peut faire une classe non copiables, c'est à dire déplacer seule, par supprimés à l'aide de définitions de la copie le constructeur et l'opérateur d'assignation de copie, et puis en fournissant des définitions par défaut du constructeur de déplacement et l'opérateur d'assignation de déplacement.
struct moveonly {
moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default;
~moveonly() = default;
};
moveonly *p;
moveonly q(*p); // error, deleted copy constructor
- fin de l'exemple ]