resueltos que poo polimorfismo persona objetos objeto herencia ejercicios ejemplo crear constructores codigo clase c++ templates c++11 overload-resolution conversion-operator

que - poo c++



Ambigüedad que involucra al operador de conversión con plantilla y al constructor de copia implícita (1)

clang y gcc difieren en comportamiento para el siguiente código:

struct foo { foo(int); }; struct waldo { template <typename T> operator T(); }; int main() { waldo w; foo f{w}; }

Este código es aceptado por clang, con el constructor foo(int) siendo llamado. Sin embargo, gcc se queja de una ambigüedad entre el constructor foo(int) y los constructores de copia y movimiento generados implícitamente:

test.cpp: In function ''int main()'': test.cpp:15:12: error: call of overloaded ''foo(<brace-enclosed initializer list>)'' is ambiguous foo f{w}; ^ test.cpp:15:12: note: candidates are: test.cpp:3:5: note: foo::foo(int) foo(int); ^ test.cpp:1:8: note: constexpr foo::foo(const foo&) struct foo ^ test.cpp:1:8: note: constexpr foo::foo(foo&&)

¿Quién tiene la razón?

También es interesante observar que si foo f{w} se cambia a foo f(w) (tenga en cuenta el cambio de llaves entre paréntesis), tanto gcc como clang dan un error. Esto me hace esperar que el comportamiento de gcc para el ejemplo anterior (es decir, dar un error) sea correcto, de lo contrario habría una extraña inconsistencia entre las formas de inicialización () y {} .

EDITAR : siguiendo la sugerencia de Kerrek SB , intenté delete el constructor de copia de foo :

struct foo { foo(int); foo(const foo&) = delete; };

El comportamiento sigue siendo el mismo.


Para la inicialización de la lista, si el elemento de la lista tiene un elemento (aquí, w ) y se considera un constructor de una clase X con el parámetro "referencia a const / volátil X", no se consideran las conversiones definidas por el usuario. Por lo tanto, no se puede usar el constructor de copia y movimiento de foo . Entonces el constructor foo(int) es inequívocamente elegido.

Entonces Clang está correcto aquí.

EDITAR: Para la gente de Estándares aquí, vea 13.3.3.1p4