c++ scope language-lawyer c++14

c++ - ¿Es redundante la regla 3 en la sección 3.3.7/1 de N3936?



scope language-lawyer (1)

Hace poco respondí una pregunta relacionada con una infracción del borrador del estándar C ++ 14: N4140, sección 3.3.7 alcance del salón , párrafo 1 regla 2 que dice:

Un nombre N usado en una clase S se referirá a la misma declaración en su contexto y cuando se vuelva a evaluar en el alcance completo de S. No se requiere diagnóstico para una violación de esta regla.

en ese momento la regla 3 también parecía relevante y dice:

Si reordenar las declaraciones de miembros en una clase produce un programa válido alternativo bajo (1) y (2), el programa está mal formado, no se requiere diagnóstico.

Mi reacción inicial es que la regla 3 parece redundante y en realidad solo es una aclaración de la regla 2 y no cubre ningún caso que no esté cubierto. Una reordenación que resulte en un programa válido alternativo también tendría que violar la regla 2 .

Entonces, ¿la regla 3 redundante o hay algunos casos extremos que requieren ambas reglas?


De acuerdo con el Informe de defectos 1875: Reordenar las declaraciones en el alcance de la clase regla 3 es redundante y la solución propuesta es eliminar la regla 3 , dice:

La necesidad de la regla n. ° 3 no está clara; parece que cualquier reordenamiento válido tendría que violar la regla n. ° 2 para producir una interpretación diferente. Tomado literalmente, la regla n. ° 3 también se aplicaría a simplemente reordenar los miembros de datos no estáticos sin dependencias de nombres. ¿Se puede simplemente eliminar?

y la solución propuesta es:

Elimine el tercer elemento de 3.3.7 [basic.scope.class], párrafo 1 y renumere los elementos siguientes

Aunque este informe de defectos parece confirmar mi sospecha inicial, me queda la sensación de que tal vez la regla 3 es un poco más amplia después de todo. La Sección 3.3.7 incluye el siguiente ejemplo:

enum { i = 1 }; class X { char v[i]; // error: i refers to ::i // but when reevaluated is X::i int f() { return sizeof(c); } // OK: X::c char c; enum { i = 2 }; };

que viola tanto la regla 2 como la 3 pero una pequeña modificación:

enum { i = 1 }; class X { enum { i = 2 }; char v[i]; // no longer refers to ::i // but reordering can cause it to refer to ::i again int f() { return sizeof(c); } // OK: X::c char c; };

parece que ya no viola la regla 2 pero parece violar la regla 3 . Considero que este ejemplo de código es problemático ya que una reordenación de los miembros podría causar que el código vuelva a estar en violación de la regla 2, pero no se requiere un diagnóstico para indicar esto, lo que hace que este código sea bastante frágil.

Actualizar

Por lo que entiendo, la regla 3 no se aplica a este ejemplo mencionado por Casey en el comentario:

class X { int a; int b; };

porque a pesar de que hay más de un pedido válido, este caso no entra dentro de las reglas 1 y 2 que la regla 3 requiere:

programa válido alternativo bajo (1) y (2)