6
votes

Conversion implicite de Int vers Shared_ptr

Considérez le code ci-dessous: xxx

dans la première ligne dans Main () , l'entier 0 est converti en un < Code> STD :: Shared_ptr et l'appel f (0) réussit sans aucun problème. Cependant, en utilisant un modèle pour appeler la fonction rendre les choses différentes. La deuxième ligne ne compilera plus, l'erreur étant xxx

Mes questions sont les suivantes:

  1. Pourquoi le premier appel réussit-il et le second n'est-il pas? Y a-t-il quelque chose qui me manque ici?
  2. Je ne comprends pas aussi comment la conversion de int sur std :: partagé_ptr est effectuée dans l'appel f (0) , comme il ressemble à std :: partagé_ptr n'a que des constructeurs explicites.

    PS: une variante de cet exemple apparaît dans Scott Meyers ' Efficace Modern C ++ Item 8, comme moyen de protéger ces appels avec nullptr . < / p>


5 commentaires

@@ vsoftco Vous devriez mentionner qu'il fonctionne que pour f (0) , mis à part ne rien compiler, même erreur pour d'autres valeurs, même dans le premier appel.


Ceci Conseils à une explication - "Il existe des conversions implicites de NullPtr au pointeur Null Valeur de tout type de pointeur et tout pointeur au type de membre. Des conversions similaires existent pour toute valeur de type STD :: NullPTR_T ainsi que pour la macro Null, la constante de pointeur NULL. " Mais il serait intéressant de le voir expliquer avec des références standard et une plus grande clarté.


@Ruppeshyadav. Fini. En effet, c'est très étrange, semble être une sorte de conversion de pointeur implicite est en cours d'exécution.


Oui bien sûr, et les réponses seraient intéressantes.


Zéro est très convertible en C ++, des choses comme f (Faux) et F ('\ 0') doivent fonctionner aussi bien auparavant.


3 Réponses :


2
votes

par [conv.ptr] / 1 (citant N4296 ici):

a Null Pointer Constant EM> est un littéral entier (2.13.2) avec valeur zéro de valeur ou une prudence de type std :: nullptr_t code>. ... une constante de pointeur nulle du type intégré peut être convertie en une privale de type std :: nullptr_t code>. P> blockQquote>

partagée_ptr code> a un constructeur non explicite qui accepte std :: nullptr_t code> par [util.smartptr.shared.const] / 1: p >

constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }


0 commentaires

5
votes

std :: Shared_ptr a un constructeur qui prend STD :: nullptr_t , littéral 0 est une constante de pointeur NULL convertiable à std :: nullptr_t à partir du projet de section standard C ++ 4.10 [conv.ptr] ( l'accent mis la mine d'aller de l'avant ):

une constante de pointeur NULL est une expression constante intégrale (5.19) Privalue de type entier qui évalue à zéro ou à une prvalue de type std :: nullptr_t . Une constante de pointeur nulle peut être convertie en un type de pointeur; Le résultat est la valeur du pointeur NULL de ce type et est distingué de toutes les autres valeurs du pointeur ou de la fonction d'objet Type de pointeur. Une telle conversion s'appelle une conversion de pointeur nulle. Deux valeurs de pointeur nulle du même type doivent comparer égales. le Conversion d'une constante de pointeur nulle sur un pointeur à CV-qualifié le type est une conversion unique et non la séquence d'un pointeur conversion suivie d'une conversion de qualification (4.4). un null la constante de pointeur du type intégré peut être convertie en prjectif de type std :: nullptr_t . [Note: La pr devalue résultante n'est pas une nulle valeur du pointeur. -End note]

Dans votre deuxième cas p est en cours de déduire comme type int lequel bien que la valeur zéro n'est plus une constante de pointeur nulle et ne correspond donc pas au même cas.

comme t.c. souligne que le libellé a été modifié avec Dr 903 qui nécessite un littéral entier avec valeur zéro par opposition à une expression constante qui évalue à zéro:

Une constante de pointeur NULL est un littéral entier (2.14.2) avec valeur zéro ou une prvalue de type std :: nullptr_t. Une constante de pointeur nulle peut être converti en type pointeur; Le résultat est le pointeur nul valeur de ce type et se distingue de toutes les autres valeur de pointeur d'objet ou type pointeur de fonction.


2 commentaires

Pourrait vouloir utiliser un brouillon plus mis à jour (voir la réponse de @ Casey ci-dessous). IIRC "Expression constante intégrale (5.19) Privalue de type entier qui évalue à zéro" inclut de telles pierres précieuses telles que (3 * 5 + 8 - 7) / 4 - 4 et interagit étrangement avec une résolution de surcharge pour une résolution de surcharge Appels impliquant des arguments de modèle de type de type, de sorte qu'ils l'ont modifié à zéro littéral uniquement dans un dr.


@Benvoigt semble être comme ça, bien que je suis d'accord, je préférerais un zéro littéral. Peut-être soutenir les expressions constantes intégrées pour un moment étant comme une extension aiderait.



1
votes

Les sapins appellent F (0) sont compilés sous forme f (NullPtr), ce qui convient au compilateur (mais cela ne devrait pas être à mon avis). Le deuxième appel va créer une déclaration pour une fonction de travail sur tout Int, qui est illégal.

La chose drôle est que même ce code fonctionne: xxx


1 commentaires

Oui, cela a du sens après avoir lu les réponses ci-dessus. Le code f (3-3) est ok, car 3-3 ou 3 * 0 est une prempue évaluée à 0. "A Null La constante de pointeur est une expression constante intégrale (5.19) Privalue de type entier qui évalue à zéro ou à une prvalue de type STD :: nullptr_t. " D'autre part, int x = 0; f (x); ne fonctionnera plus, puisque x n'est plus une prvalue, mais un lvalue, mais pas un pointeur null absolument.