Dirección de una función sobrecargada
Además de las expresiones de llamada a función, donde toma lugar la resolución de sobrecarga, el nombre de una función sobrecargada puede aparecer en los siguientes contextos:
En cada contexto, el nombre de una función sobrecargada puede estar precedido por el operador dirección-de &
y puede encerrarse en un conjunto redundante de paréntesis.
En todos estos contextos, la función seleccionada del conjunto de sobrecarga es la función cuyo tipo coincide con el puntero a la función, la referencia a la función o el puntero al tipo de función miembro que espera el objetivo: el objeto o la referencia que se está inicializando, el lado izquierdo de la asignación, función o parámetro de operador, el tipo de retorno de una función, el tipo de destino de una conversión o el tipo de parámetro de plantilla, respectivamente.
Los tipos de parámetros y el tipo de retorno de la función deben coincidir exactamente con el objetivo, no se consideran conversiones implícitas (por ejemplo, una función que devuelve un puntero a una clase derivada no se seleccionará al inicializar un puntero a la función que devuelve un puntero a una clase base).
Si el nombre de la función nombra una plantilla de función, entonces, primero, se realiza la deducción de argumento de plantilla, y si tiene éxito, produce una especialización de plantilla única que se agrega al conjunto de sobrecargas a considerar. (desde C++20) Si más de una función del conjunto coincide con el objetivo, y al menos una función no es de plantilla, las especializaciones de plantilla se eliminan de la consideración. Para cualquier par de funciones que no son de plantilla donde una es más restringida que otra, la función menos restringida se elimina del conjunto (desde C++20). Si todos los candidatos restantes son especializaciones de plantilla, las menos especializadas se eliminan si hay más especializadas disponibles. Si queda más de un candidato después de los retiros, el programa está mal formado.
[editar] Ejemplo
int f(int) { return 1; } int f(double) { return 2; } void g( int(&f1)(int), int(*f2)(double) ) {} template< int(*F)(int) > struct Templ {}; struct Foo { int mf(int) { return 3; } int mf(double) { return 4; } }; struct Emp { void operator<<(int (*)(double)) {} }; int main() { // 1. inicialización int (*pf)(double) = f; // selecciona int f(double) int (&rf)(int) = f; // selecciona int f(int) int (Foo::*mpf)(int) = &Foo::mf; // selecciona int mf(int) // 2. asignación pf = nullptr; pf = &f; // selecciona int f(double) // 3. argumento de función g(f, f); // selecciona int f(int) para el primer argumento // e int f(double) para el segundo // 4. operador definido por el usuario Emp{} << f; // selecciona int f(double) // 5. valor de retorno auto foo = []() -> int (*)(int) { return f; // selecciona int f(int) }; // 6. conversión auto p = static_cast<int(*)(int)>(f); // selecciona int f(int) // 7. argumento de plantilla Templ<f> t; // selecciona int f(int) }
[editar] Referencias
- El estándar C++11 (ISO/IEC 14882:2011):
- 13.4 Dirección de una función sobrecargada [over.over]
- El estándar C++98 (ISO/IEC 14882:1998):
- 13.4 Dirección de una función sobrecargada [over.over]