tour plusplus plus oficial documentacion c++ c++11 language-lawyer c++14

c++ - plusplus - Dado int** p1 y const int** p2 es p1== p2 bien formado?



c++ website (1)

Antes de C + + 14 este caso estaba mal formado y el caso más general con algunas excepciones también estaba mal formado. Esto está cubierto en el informe de defectos 1512: comparación de punteros versus conversiones de calificación , que dice:

De acuerdo con 5.9 [expr.rel] párrafo 2, que describe las comparaciones de punteros,

Las conversiones de puntero (4.10 [conv.ptr]) y las conversiones de calificación (4.4 [conv.qual]) se realizan en operandos de puntero (o en un operando de puntero y una constante de puntero nulo, o en dos constantes de puntero nulo, al menos uno de los cuales es no integral) para llevarlos a su tipo de puntero compuesto.

Esto parece hacer que el siguiente ejemplo esté mal formado,

bool foo(int** x, const int** y) { return x < y; // valid ? }

porque int ** no se puede convertir a const int **, de acuerdo con las reglas de 4.4 [conv.qual] párrafo 4. Esto parece demasiado estricto para la comparación de punteros, y las implementaciones actuales aceptan el ejemplo.

El informe de defectos señala que aunque esto no estaba bien formado, las implementaciones aceptaron tales comparaciones. Esta confirmación de clang indica que se trató como una extensión e indica que tanto gcc como EDG también lo tratan como una extensión, presumiblemente este también es el caso de Visual Studio.

Esto fue resuelto en el estándar por N3624: Core Issue 1512: comparación de punteros vs conversiones de calificación , que dice:

Este documento presenta las modificaciones al Borrador de Trabajo necesarias para resolver los problemas principales 583 y 1512. En particular, hace

[...]

y

void g(int **p1, const int**p2) { if (p1 == p2) { ... } }

bien formado.

También tenga en cuenta que en la reunión se aceptó que se tomó nota de que esto solo codifica la práctica existente.

Entre otros cambios al estándar, este párrafo se agregó al final de la sección 5 [expr] , que incluye el nuevo término cv-combinado tipo :

El tipo cv-combinado de dos tipos T1 y T2 es un tipo T3 similar a T1 cuya firma de calificación cv (4.4) es:

  • para cada j> 0, cv3, j es la unión de cv1, j y cv2, j;
  • si el cv3 resultante, j es diferente de cv1, j o ​​cv2, j, entonces const se agrega a cada cv3, k para 0 <k <j.

[Nota: dados los tipos similares T1 y T2, esta construcción asegura que ambos puedan convertirse a T3. -Finalizar nota] El tipo de puntero compuesto de dos operandos p1 y p2 con tipos T1 y T2, respectivamente, donde al menos uno es un puntero o puntero al tipo de miembro o std :: nullptr_t, es:

  • si tanto p1 como p2 son constantes de puntero nulo, std :: nullptr_t;
  • si p1 o p2 es una constante de puntero nulo, T2 o T1, respectivamente;
  • si T1 o T2 es "puntero a cv1 void" y el otro tipo es "puntero a cv2 T", "puntero a cv12 void", donde cv12 es la unión de cv1 y cv2;
  • si T1 es "puntero a cv1 C1" y T2 es "puntero a cv2 C2", donde C1 está relacionado con la referencia a C2 o C2 está relacionado con la referencia a C1 (8.5.3), el tipo cv-combinado de T1 y T2 o el tipo cv-combinado de T2 y T1, respectivamente;
  • si T1 es "puntero al miembro de C1 de tipo cv1 U1" y T2 es "puntero al miembro de C2 de tipo cv2 U2" donde C1 está relacionado con la referencia a C2 o C2 está relacionado con la referencia a C1 (8.5.3), el tipo cv-combinado de T2 y T1 o el tipo combinado cv de T1 y T2, respectivamente;
  • si T1 y T2 son puntero mixto de varios niveles similar y puntero a tipos de miembro (4.4), el tipo cv-combinado de T1 y T2;
  • de lo contrario, un programa que necesita la determinación de un tipo de puntero compuesto está mal formado.

[Ejemplo:

typedef void *p; typedef const int *q; typedef int **pi; typedef const int **pci;

El tipo de puntero compuesto de p y q es "puntero a const void"; el tipo de puntero compuesto de pi y pci es "puntero a const puntero para const int". -Final ejemplo]

Dada la siguiente función:

void g(int **p1, const int**p2) { if (p1 == p2) { } }

clang ( volver a la versión 3.0 ) produce esta advertencia ( ver en vivo ):

warning: comparison of distinct pointer types (''int **'' and ''const int **'') uses non-standard composite pointer type ''const int *const *'' [-Wcompare-distinct-pointer-types] if (p1 == p2) { } ~~ ^ ~~

El uso de -pedantic-errors convierte en un error. Ni gcc ( volver a 4.3.6 ) ni Visual Studio ( 2013 ) producen una advertencia, de acuerdo con el estándar, es la comparación:

p1 == p2

bien formado?

De manera más general, si dos punteros multinivel difieren en sus cv-calificaciones que no sean en el primer nivel, ¿la comparación se realiza mediante el operador de igualdad o los operadores relacionales bien formados?