unique_ptr <0 OU que fait moins que l'opérateur?

9

J'ai affaire à du code qui n'a pas été écrit par moi. J'ai cette déclaration:

// p is type of std::unique_ptr<uint8_t[]>
if (p < 0) { /* throw an exception */ }

Alors qu'est-ce que cela p < 0signifie dans ce contexte?
Sur la page de documentation , je pense que mon cas est 16) y < nullptr, où 0est nullptr.

Mais qu'est-ce que ça fait?

Sagide
la source
1
Basé sur le fait que, en x64, les pointeurs canoniques dans la plage du noyau ont le bit supérieur défini, cela pourrait être un moyen (stupide codé en dur) de vérifier si un pointeur appartient à l'espace du noyau - si la réponse ci-dessous est correcte, alors non .
Michael Chourdakis
1
Dans WINAPI p==-1est un handle non valide. Puisqu'il 2^64s'agit d'un nombre ridiculement énorme, tout sensible pest toujours positif. p<0Vérifie donc le descripteur non valide de WINAPI. Ce n'est pas un bon code.
ALX23z
@OP: Pourriez-vous clarifier un peu dans quel contexte ce code est utilisé? Est-il utilisé sous Linux ou Windows? La valeur du pointeur est-elle liée à du code WINAPI? Je pense que si vous avez clarifié cela, les commentaires ci-dessus peuvent être de bonnes réponses.
noyer
@ ALX23z Mais un handle WINAPI doit-il être de type uint8_t*(ou même tableau de uint8_t)? Je pense que oui void*, n'est-ce pas?
noyer
@walnut ils ne sont pas void*ils ont la macro HANDLE_PTR ou quelque chose qui est fondamentalement long*iirc.
ALX23z

Réponses:

2

unique_ptr <0 OU que fait moins que l'opérateur?

Il correspond à la surcharge (11) sur cppreference operator<(const unique_ptr&, nullptr_t);. 0 se convertit implicitement en std::nullptr_t. Selon la documentation, le résultat est std::less<unique_ptr<T,D>::pointer>()(x.get(), nullptr).

Le résultat est défini par l'implémentation, mais inconditionnellement faux sur probablement la plupart des systèmes. Vraisemblablement sur un système exotique où null n'a pas la représentation binaire de 0, le résultat pourrait être vrai.

Je crois que mon cas a 16 ans)

(16) est le même inverse: 0 > unique_ptr. Le résultat est le même.

eerorika
la source
Mais est 0considéré nullptrpar le compilateur? Je pense que c'est ce qu'il se demande. Ça n'a pas de sens pour moi non plus, du moins.
alteredinstance
@alteredinstance 0 n'est pas "considéré" nullptr(ou dépend de ce que vous entendez par considération). 0 se convertit implicitement en std::nullptr_t.
eerorika
C'est ce que je supposais. Je me demande s'il existe une documentation sur la conversion implicite de 0to nullptr, car je n'ai vu que les deux compatibles avec les comparaisons booléennes. Ils sont comparables, mais j'avais l'impression qu'ils ne sont pas convertibles.
alteredinstance
@alteredinstance La conversion ne se produit pas dans l'autre sens. int x = nullptrest mal formé.
eerorika
2
@alteredinstance a std::nullptr_tété conçu pour être utilisable avec n'importe quelle constante de pointeur nul; pas seulement nullptr. 0 (ainsi que 0L par exemple) sont des constantes de pointeur nul, il est donc prévu qu'elles puissent être utilisées pour créer un std::nullptr_t.
eerorika
2

Vérifiez que ce operator <n'est pas surchargé quelque part dans votre base de code. Cela semble être le seul moyen (p < 0)possible true.

Exemple:

bool operator< (const std::unique_ptr<uint8_t[]>&, int) { return true; }

int main() {
    std::unique_ptr<uint8_t[]> p;
    std::cout << (p < 0) << std::endl;
}

Tirages:

1

démo en direct

Sinon, comme d'autres l'ont dit, 0convertit implicitement en std::nullptr_t, ce qui sélectionnerait la bool operator<(const unique_ptr<T, D>& x, nullptr_t)surcharge qui appellerait std::less(p, 0)qui retournerait false(même sur Windows avec une -1valeur de pointeur).

rustyx
la source
Il n'a pas nécessairement revenir false. Il est défini par l'implémentation ou non spécifié (je ne suis pas sûr.) Mais je suis d'accord qu'il reviendra probablement falsesur la plupart (toutes?) Les implémentations. Voir aussi la réponse de @eerorika
noyer
0

Cette expression correspond à cet opérateur de modèle (0 en cours de conversion nullptr):

template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);

Cela renvoie std::less<unique_ptr<T,D>::pointer>()(p.get(), nullptr)ce qui est toujours faux (comme std::lessc'est un foncteur d'ordre strict) ( démo ).

YSC
la source
Il n'a pas toujours revenir false. Que ce soit le cas est défini par l'implémentation ou non spécifié. Il revient probablement toujours falsesur la plupart (toutes?) Des implémentations actuelles.
noyer
@walnut À moins qu'une question ne demande explicitement ce que dit la norme (par le biais de la balise langue-avocat par exemple), j'essaie de répondre d'un point de vue pratique. Toute mise en œuvre pratique du std::lessretour false.
YSC
C'est bien, je n'ai tout simplement pas trouvé convaincant votre raisonnement (" car std :: less est un foncteur d'ordre strict "). Il peut s'agir d'une commande stricte sans retour false. La raison pratique serait que la valeur du pointeur zéro est représentée par l'adresse la plus basse possible ou quelque chose le long de ces lignes.
noyer