with initialize argument c++ c++11 overload-resolution brace-initialization

argument - c++ initialize class with parameters



¿El compilador piensa que “A(A y)” acepta valores por un momento? (1)

Es una peculiaridad del lenguaje. La primera f coincide mejor porque su A no requiere conversión para coincidir con el tipo de argumento ( A ), pero cuando el compilador intenta realizar la llamada, el hecho de que no se pueda encontrar un constructor de copia adecuado hace que la llamada falle. El lenguaje no permite tener en cuenta la viabilidad de la llamada real al realizar el paso de resolución de sobrecarga.

Cita estándar coincidente más cercana ISO / IEC 14882: 2011 13.3.3.1.2 Secuencias de conversión definidas por el usuario [over.ics.user]:

A la conversión de una expresión de tipo de clase en el mismo tipo de clase se le otorga el rango de concordancia exacta, y a la conversión de una expresión de tipo de clase en una clase base de ese tipo se le asigna un rango de conversión, a pesar del hecho de que una copia / movimiento se llama al constructor (es decir, una función de conversión definida por el usuario) para esos casos.

Para el caso de inicialización de la lista, probablemente deba ver: 13.3.3.1.2 Secuencias de conversión definidas por el usuario [over.ics.user]

Cuando los objetos de clase de clase no agregada T están inicializados en lista (8.5.4), la resolución de sobrecarga selecciona el constructor en dos fases:

- Inicialmente, las funciones candidatas son los constructores de la lista de inicializadores (8.5.4) de la clase T y la lista de argumentos consiste en la lista de inicializadores como un solo argumento.

- Si no se encuentra un constructor de lista de inicializadores viable, la resolución de sobrecarga se realiza de nuevo, donde las funciones candidatas son todas las constructoras de la clase T y la lista de argumentos consta de los elementos de la lista de inicializadores.

Debido a que la resolución de sobrecarga tiene que ver los constructores viables en cada caso para f(A) f(B) , debe rechazar la secuencia que trata de unir A() a A(A&) pero B(const A&) todavía es viable.

Tengo este codigo

struct A { A(); A(A&); }; struct B { B(const A&); }; void f(A); void f(B); int main() { f(A()); }

Para mi sorpresa esto falla con GCC y Clang. Clang dice por ejemplo

Compilation finished with errors: source.cpp:8:10: error: no matching constructor for initialization of ''A'' f(A()); ^~~ source.cpp:1:21: note: candidate constructor not viable: expects an l-value for 1st argument struct A { A(); A(A&); }; ^ source.cpp:1:16: note: candidate constructor not viable: requires 0 arguments, but 1 was provided struct A { A(); A(A&); }; ^ source.cpp:4:13: note: passing argument to parameter here void f(A);

¿Por qué eligen la primera f , cuando la segunda f funciona bien? Si quito la primera f , entonces la llamada tiene éxito. Lo que es más extraño para mí, si uso la inicialización de llaves, también funciona bien

int main() { f({A()}); }

Todos llaman al segundo f .