2010-11-17 23 views
10

Me rindo en este ...dynamic_cast confusión

$ 5.2.7/2- "Si T es un tipo de puntero, v a bordo otro valor p de un puntero a completa Tipo de clase, y el el resultado es un valor de tipo T. Si T es un tipo de referencia , v será un lvalue de un tipo de clase completo, y el resultado es un valor l del tipo al que hace referencia T. "

De acuerdo con lo anterior, el siguiente código debe estar bien formado.

struct A{}; 
struct B : A{}; 

int main(){ 
    B b; 
    A a, &ar1 = b; 

    B& rb1 = dynamic_cast<B&>(ar1); // Does not $5.2.7/2 apply here? 
    B& rb2 = dynamic_cast<B&>(a); // and also here? 
} 

Pero no lo es. Todos los compiladores se quejan de la operando a dynamic_cast no ser polimórfica de acuerdo con

$ 5.2.7/6- De lo contrario, v deberá ser un puntero a o un lvalue de un tipo polimórfico (10.3).

Así que mi pregunta es ¿qué significa $ 5.2.7/2? ¿Por qué entran $ 5.2.7/6 aquí?

Respuesta

3

"De lo contrario" en este caso significa, "a menos que se apliquen las condiciones en 5.2.7/5".

Puede decir esto porque/2 impone un requisito en el programa con respecto al operando del dynamic_cast (tenga en cuenta que el idioma "deberá" de "v será un lvalue" frente al "es" lenguaje de "el resultado es un lvalue "). Al igual que en otros lugares de la norma, expresar un requisito no significa necesariamente que sea el único requisito. Otras cláusulas pueden establecer requisitos adicionales. En este caso,/6 estados un requisito adicional que sólo se aplica en ciertos casos, en función de T y el tipo estático de v.

/3,/4,/5 le informamos sobre el valor del resultado , y son completamente consistentes con el requisito en/2. Ninguno de ellos comienza con "De lo contrario". Entonces, para mí, es bastante obvio que no forman una cadena "else if" que comienza en/2.

Algunos corchetes o algo así podrían aclarar esto (es decir, que "de lo contrario" en/6 se aplica al "si" en/5, y no a "si" en/2,/3, o/4) . Pero ese no es el estilo de la casa.

Aparte de todo lo demás, el "de lo contrario" en/5 lógicamente no se puede aplicar significativamente a las condiciones en/2./1 dice que T debe ser "puntero o referencia para completar el tipo de clase, o cvvoid*"./2 cubre dos casos: tipos de puntero y tipos de referencia. Eso es todo. No hay "de lo contrario" a/2 (a menos que dijera "de lo contrario, un compilador conforme debe emitir un diagnóstico", pero eso está implícito)

+0

¿hay algún otro caso en el que 'de lo contrario' en la Norma se use de una manera * potencialmente * incierta – Chubsdad

+0

@Chubsdad: lo espero. –

+0

¿Cuál es la diferencia b/w 'shall' y 'will' como se usa en el estándar? – Chubsdad

9

Bueno, todos los requisitos en 5.2.7 se deben observar juntos. No puede simplemente detenerse después de 5.2.7/2 y comenzar a escribir código que supuestamente satisface todo "hasta 5.2.7/2". Todo el 5.2.7 define la especificación de dynamic_cast.

El requisito polimórfico se destaca porque es condicional. Cuando utiliza dynamic_cast para actualizaciones, el requisito polimórfico no se aplica (de hecho, dynamic_cast es equivalente a static_cast en actualizaciones). El requisito polimórfico solo se aplica cuando usa dynamic_cast para downcasts o crosscasts.

La especificación de dynamic_cast se organiza secuencialmente, lo que significa que primero se ocupa de casos más simples y luego avanza a aplicaciones más complicadas. Se supone que debes leerlo paso a paso, hasta que cubra tu situación específica. Todo lo que lee a lo largo de ese camino se aplica acumulativamente, y "de lo contrario" significa: "si aún no hemos cubierto su caso, continúe leyendo".

+2

Mmmm. Bueno. Pero, ¿qué significa "de lo contrario"? – sharptooth

+0

exactamente mi pregunta. El usuario de 'de lo contrario' en muchas otras partes del Estándar proporciona un tipo de procedimiento algorítmico 'paso a paso'. – Chubsdad

+0

Gracias AndreyT. Creo que Steve lo expresó de una manera convincente. El "de lo contrario" se aplica a 5.2.7/5 en lugar de a todas las cláusulas anteriores. Espero que tales confusiones tengan una forma de llegar al comité estándar para la direccionalidad potencial. – Chubsdad

4

Para hacer un downcast como en su ejemplo, Struct A necesita ser polimórfico y tener RTTI. Aquí está una versión ajustada que funciona, a un punto:

struct A{virtual void f(){}}; 
struct B : A{}; 

int main(){ 
    B b; 
    A a, &ar1 = b; 

    B& rb1 = dynamic_cast<B&>(ar1); // Does not $5.2.7/2 apply here? 
    //B& rb2 = dynamic_cast<B&>(a); // and also here? 
} 

Mediante la adición de un Portal por lo que es polimórfico, RTTI está habilitada para la clase, lo que permite downcasts.

Tenga en cuenta que su segundo ejemplo no puede funcionar, ya que está enviando un pod (a) a una referencia a un pod, que no está permitido.


Actualización:

El código no está permitido bajo 5.2.7.5 y no es ni permitido en 5.2.7.6. Mi ajuste lo hace funcionar en 5.2.7.6

+0

Gracias Alex. Sin embargo, esa no es mi pregunta. – Chubsdad