2010-11-24 11 views
23
struct A 
{ 
    A(const A& src); 
    A(const char* src); 
}; 
struct B 
{ 
    operator A(); 
    operator char*(); 
}; 
void test() 
{ 
    B v; 
    A s(v); 
} 

EDG/Comeau y MSVC permite el código, mientras que GCC 4.4.4, CLANG y BCC lo rechazan como ambiguo.¿Debería ser ambiguo o no? (modelos implícitos)

miembro del comité

A C++ respondió con este (inicialmente):

No es ambigua; el constructor A (const A &) es mejor que el constructor A (const char *). El const Un parámetro & se une directamente al resultado de la función de conversión, por lo que la secuencia de conversión se considera ser una conversión definida por el usuario siguió por una conversión identidad (13.3.3.1.4p1). El parámetro const char * es una conversión definida por el usuario seguida de una conversión de calificación , por lo que es peor.

Luego, siguió con esto.

En realidad, estaba equivocado. Si bien es cierto que la segunda secuencia de conversión en una secuencia de conversión definida por el usuario es un desempate, mirando más de cerca a 13.3.3.2p3, la siguiente a la última bala, revela que esta desempate sólo se aplica si las dos secuencias contienen la misma secuencia de conversión definida por el usuario y que no es el caso en este ejemplo. Debido secuencia conversión de un constructor utiliza B :: operador A() y el carbón otros usos b :: operador *(), no hay desempate entre los dos secuencias de conversión definidas por el usuario y son ambiguas.

Mi pregunta es esta.

13.3.3.2 p3 establece que,

Dos secuencias de conversión implícitas de la misma forma son secuencias conversión indistinguibles a menos que uno de los siguientes reglas se aplican.

Según mi entender, las palabras clave son "una de las siguientes reglas". No significa que la viñeta que indica "misma secuencia de conversión" anula todas las anteriores. Hubiera pensado que "el rango de S1 es mejor que el rango de S2" sería aplicable en su lugar?

+12

Buena prueba de que C++ tiene un poco demasiado complicado ... – Hexagon

+0

Dado que tiene un contacto de miembro de la comunidad de C++, ¿no debería simplemente pedirle que presente un problema? (o verifique si está archivado en http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html) –

+0

No dije que hay un problema, en realidad estoy tratando de entender el estándares. –

Respuesta

4

Sí, el resultado esperado es la ambigüedad en la medida de mi interpretación de la Cláusula 13.3.3.2

Matching argumento 'v' del tipo 'B' para los parámetros de cualquiera de los constructores sobrecargados de 'A' requiere una conversión definida por el usuario. Ambas secuencias son de rango de CONVERSIÓN.

Mi interpretación es que la siguiente cita de $ 13.3.3.2 se aplica

[...] por el usuario define la secuencia de conversión U1 es una mejor secuencia de conversión que otra definida por el usuario de conversión secuencia de U2 si contienen la misma función de conversión definida por el usuario o constructor y si la segunda secuencia de conversión estándar de U1 es mejor que el segundo estándar de conversión secuencia de U2.

Ambos invocan diferentes funciones de conversión en la clase 'B'. Por lo tanto, creo que la primera condición en sí no está satisfecha y, por lo tanto, el resultado esperado es Ambigüedad, ya que ninguna de las secuencias de conversión es mejor que la otra.

+0

Sí, esto es claramente ambiguo, por el motivo exacto que mencionas. No estoy seguro de por qué esto no es el aceptado swer. Señala directamente cómo y por qué es ambiguo. Sin embargo, está mal que tenga un rango de "conversión". Como dirás más tarde, tienes dos secuencias de conversión definidas por el usuario. Los rangos se dan a las secuencias de conversión estándar (coincidencia exacta, promoción, conversión). No hay ninguna noción de rango para la secuencia de conversión definida por el usuario. –

1

Descargo de responsabilidad: el estándar es realmente complejo en estas partes, por lo que puede estar completamente equivocado en mi comprensión.

Definición estándar de mejor función viable (13.3.3):

Teniendo en cuenta estas definiciones, un viable función F1 se define para ser un mejor función que la otra función viable F2 si para todos los argumentos i, ICSI (F1) es no una secuencia de conversión peor que ICSI (F2), y luego

[...]

  • el contexto es una inicialización por conversión definida por el usuario (ver 8.5, 012.13.3.1.5 y 13.3.1.6) y la secuencia estándar de conversión del tipo retorno de F1 al destino tipo (es decir, el tipo de la entidad está inicializando) es una secuencia mejor conversión que el estándar secuencia de conversión del tipo de devolución de F2 al tipo de destino.

Si he entendido bien, el tipo de objeto que está siendo construido tiene su importancia aquí, y eso haría que A::A(const A &) un mejor candidato.


Consulte Johannes comentarios para ver por qué esta respuesta es incorrecta: Este es de hecho ambigua por la razón señalada por Chubsdad.

+0

Definitivamente relevante, +1, pero de los 2 contextos mencionados, 13.3.1.5 se refiere solo a la inicialización de tipos que no son de clase (como 'int') y 13.3.1.6 se refiere solo a la inicialización de * referencias *. Entonces no creo que se apliquen aquí. –

+0

@j_random_hacker: sí pero 8.5 cubre la inicialización o casi todo lo demás – icecrime

+0

@icecrime: tiene razón, pero la trama se espesa: según 8.5/12, 'A s (v);' es * inicialización directa * - - ¿derecho? Luego se aplica la sexta viñeta de 8.5/14. Es demasiado grande para citar aquí, pero el punto clave es que no menciona las palabras "conversión definida por el usuario" - * a diferencia de * la próxima viñeta que cubre (algunos) casos de inicialización de copia. Así que no creo que el fragmento que citó se aplique aquí, y concluyo que 'A s (v);' es ambiguo pero 'A s = v;' debe seleccionar el 'A (const A &)' ctor. –

Cuestiones relacionadas