Namespaces
Variants

Address of an overloaded function

From 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]