Namespaces
Variants

Address of an overloaded function

From es.cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Además de las expresiones de llamada a función , donde tiene lugar la resolución de sobrecarga , el nombre de una función sobrecargada puede aparecer en los siguientes 7 contextos:

# Contexto Objetivo
1 inicializador en una declaración de un objeto o referencia el objeto o referencia siendo inicializado
2 en el lado derecho de una expresión de asignación incorporada el lado izquierdo de la asignación incorporada
3 como argumento de llamada a función el parámetro de la función
4 como argumento de operador definido por el usuario el parámetro del operador
5 la sentencia return el valor de retorno de una función o conversión
6 conversión explícita o argumento de static_cast la conversión correspondiente
7 argumento de plantilla constante el parámetro de plantilla correspondiente

En cada contexto, el nombre de una función sobrecargada puede ir precedido por el operador de dirección & y puede estar encerrado en un conjunto redundante de paréntesis.

Si el tipo de destino contiene un tipo de marcador de posición , se realiza la deducción del tipo de marcador de posición, y la siguiente descripción utiliza el tipo deducido como tipo de destino.

(since C++26)

Contenidos

Selección de funciones

Cuando se toma la dirección de una función sobrecargada, se selecciona un conjunto S de funciones del conjunto de sobrecarga referido por el nombre de la función sobrecargada:

  • Si no hay un objetivo, se seleccionan todas las funciones no plantilla nombradas.
  • De lo contrario, una función no plantilla con tipo F se selecciona para el tipo de función FT del tipo objetivo si F (después de aplicar posiblemente la conversión de puntero a función ) (desde C++17) es idéntico a FT . [1]
  • La especialización (si existe) generada por la deducción de argumentos de plantilla para cada plantilla de función nombrada también se añade a S .

Si el objetivo es de tipo puntero a función o referencia a tipo función, S solo puede incluir funciones no miembro , funciones miembro de objeto explícito (desde C++23) y funciones miembro estáticas. Si el objetivo es de tipo puntero-a-función-miembro, S solo puede incluir funciones miembro de objeto implícito.

  1. ↑ En otras palabras, la clase de la cual la función es miembro se ignora si el tipo destino es un tipo puntero-a-función-miembro.

Eliminación de funciones

Después de formar el conjunto S , las funciones son eliminadas en el siguiente orden:

  • Todas las funciones con constraints asociados que no están satisfechos son eliminadas del S .
(desde C++20)
  • Si más de una función en S permanece, todas las especializaciones de plantilla de función en S son eliminadas si S también contiene una función no plantilla.
(desde C++20)
  • Cualquier especialización de plantilla de función dada spec es eliminada si S contiene una segunda especialización de plantilla de función cuya plantilla de función está más especializada que la plantilla de función de spec .

Después de tales eliminaciones (si las hay), exactamente una función seleccionada debe permanecer en S . De lo contrario, el programa está mal formado.

Ejemplo

int f(int) { return 1; }
int f(double) { return 2; }
void g(int(&f1)(int), int(*f2)(double)) { f1(0); f2(0.0); }
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 1er 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)
    // prevenir advertencias de "variable no utilizada" como si fuera [[maybe_unused]]
    [](...){}(pf, rf, mpf, foo, p, t);
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 202 C++98 el argumento de plantilla constante no era un contexto
para tomar la dirección de una función sobrecargada
lo es
CWG 250 C++98 las especializaciones de plantillas de función generadas con argumentos
de plantilla no deducidos no se seleccionaban del conjunto de sobrecarga
también seleccionadas
CWG 1153 C++98 no estaba claro si un tipo de función dado coincide con el tipo objetivo aclarado
CWG 1563 C++11 no estaba claro si la inicialización de lista es un contexto
para tomar la dirección de una función sobrecargada
aclarado

Referencias

  • Estándar C++23 (ISO/IEC 14882:2024):
  • 12.3 Dirección de función sobrecargada [over.over]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 12.5 Dirección de función sobrecargada [over.over]
  • Estándar C++17 (ISO/IEC 14882:2017):
  • 16.4 Dirección de función sobrecargada [over.over]
  • Estándar C++14 (ISO/IEC 14882:2014):
  • 13.4 Dirección de función sobrecargada [over.over]
  • Estándar C++11 (ISO/IEC 14882:2011):
  • 13.4 Dirección de función sobrecargada [over.over]
  • Estándar C++98 (ISO/IEC 14882:1998):
  • 13.4 Dirección de función sobrecargada [over.over]