unique_ptr <0 O ¿qué hace menos que el operador?

9

Estoy tratando con un código que no ha sido escrito por mí. Tengo esta afirmación:

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

Entonces, ¿qué p < 0significa en este contexto?
En la página de documentación , creo que mi caso es 16) y < nullptrdónde 0está nullptr.

Pero, ¿qué hace?

Sagid
fuente
1
Basado en el hecho de que, en x64, los punteros canónicos en el rango del kernel tienen el bit superior establecido, podría ser una forma (estúpida) de verificar si un puntero pertenece al espacio del kernel; sin embargo, si la respuesta a continuación es correcta, entonces no .
Michael Chourdakis
1
En WINAPI p==-1hay un identificador no válido. Dado que 2^64es un número ridículamente enorme, cualquier sentido pes siempre positivo. Por lo tanto, p<0busca un identificador no válido de WINAPI. Este no es un buen código.
ALX23z
@OP: ¿Podría aclarar un poco en qué contexto se usa este código? ¿Se usa en Linux o Windows? ¿El valor del puntero está relacionado con algún código WINAPI? Creo que si aclaraste eso, los comentarios anteriores pueden ser buenas respuestas.
nogal
@ ALX23z Pero, ¿un controlador WINAPI debería ser de tipo uint8_t*(o incluso de matriz uint8_t)? Creo que lo son void*, ¿no es así?
nogal
@walnut no son void*, tienen macro HANDLE_PTR o algo que es básicamente long*iirc.
ALX23z

Respuestas:

2

unique_ptr <0 O ¿qué hace menos que el operador?

Coincide con la sobrecarga (11) en cppreference operator<(const unique_ptr&, nullptr_t);. 0 se convierte implícitamente en std::nullptr_t. Según la documentación, el resultado es std::less<unique_ptr<T,D>::pointer>()(x.get(), nullptr).

El resultado es una implementación definida, pero incondicionalmente falsa en probablemente la mayoría de los sistemas. Presumiblemente en un sistema exótico donde nulo no tiene la representación binaria de 0, el resultado podría ser cierto.

Creo que mi caso es 16)

(16) es la misma otra alrededor manera: 0 > unique_ptr. El resultado es el mismo.

eerorika
fuente
¿Pero es 0considerado nullptrpor el compilador? Creo que eso es lo que se pregunta. Tampoco tiene sentido para mí, al menos.
instancia alterada
@alteredinstance 0 no se "considera" nullptr(o depende de lo que quiere decir por consideración). 0 se convierte implícitamente en std::nullptr_t.
Eerorika
Eso es lo que asumí. Me pregunto si hay alguna documentación sobre la conversión implícita de 0a nullptr, ya que solo he visto los dos compatibles con las comparaciones booleanas. Son comparables, pero tenía la impresión de que no son convertibles.
instancia alterada
@alteredinstance La conversión no ocurre al revés. int x = nullptrEstá mal formado.
Eerorika
2
@alteredinstance std::nullptr_tfue diseñado para ser utilizable con cualquier puntero nulo constante; no sólo nullptr. 0 (así como 0L, por ejemplo) son constantes de puntero nulo, por lo que es la intención de que puedan usarse para crear a std::nullptr_t.
Eerorika
2

Verifique que operator <no esté sobrecargado en algún lugar de su base de código. Esa parece ser la única forma en que (p < 0)podría ser true.

Ejemplo:

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;
}

Huellas dactilares:

1

demo en vivo

De lo contrario, como han dicho otros, se 0convierte implícitamente en std::nullptr_t, que seleccionaría la bool operator<(const unique_ptr<T, D>& x, nullptr_t)sobrecarga que llamaría a la std::less(p, 0)que volvería false(incluso en Windows con un -1valor de puntero).

rustyx
fuente
No necesariamente regresa false. Está definido por la implementación o no está especificado (no estoy seguro). Pero estoy de acuerdo en que probablemente regrese falseen la mayoría de las implementaciones (¿todas?). Ver también la respuesta de @eerorika
nogal
0

Esta expresión coincide con este operador de plantilla (0 se convierte a nullptr):

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

Esto devuelve lo std::less<unique_ptr<T,D>::pointer>()(p.get(), nullptr)que siempre es falso (como std::lesses un functor de orden estricto) ( demo ).

YSC
fuente
No siempre regresa false. Si lo hace está definido por la implementación o no especificado. Probablemente siempre regrese falseen la mayoría de las implementaciones actuales (¿todas?).
nogal
@walnut A menos que una pregunta explícitamente pregunte qué dice el Estándar (a través de la etiqueta de idioma-abogado, por ejemplo), trato de responder desde un punto de vista práctico. Toda la implementación práctica de std::lessretorno false.
YSC
Eso está bien, simplemente no encontré convincente su razonamiento (" como std :: less es un estricto functor de orden "). Puede ser un orden estricto sin volver false. La razón práctica sería que el valor del puntero cero está representado por la dirección más baja posible o algo por el estilo.
nogal