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

En plus des expressions d'appel de fonction , où la résolution de surcharge a lieu, le nom d'une fonction surchargée peut apparaître dans les 7 contextes suivants :

# Contexte Cible
1 initializer dans une déclaration d'un objet ou référence l'objet ou la référence en cours d'initialisation
2 côté droit d'une expression d'assignation intégrée côté gauche de l'assignation intégrée
3 comme argument d'appel de fonction le paramètre de fonction
4 comme argument d'opérateur personnalisé le paramètre d'opérateur
5 l'instruction return la valeur de retour d'une fonction ou conversion
6 cast explicite ou argument static_cast le cast correspondant
7 argument de template constant le paramètre de template correspondant

Dans chaque contexte, le nom d'une fonction surchargée peut être précédé de l'opérateur d'adresse & et peut être entouré d'un ensemble redondant de parenthèses.

Si le type cible contient un type substitut , la déduction du type substitut est effectuée, et la description suivante utilise le type déduit comme type cible.

(since C++26)

Table des matières

Sélection des fonctions

Lorsque l'adresse d'une fonction surchargée est prise, un ensemble S de fonctions est sélectionné à partir de l'ensemble de surcharge référencé par le nom de la fonction surchargée :

  • S'il n'y a pas de cible, toutes les fonctions non template nommées sont sélectionnées.
  • Sinon, une fonction non template de type F est sélectionnée pour le type de fonction FT du type cible si F (après application éventuelle de la conversion de pointeur de fonction ) (depuis C++17) est identique à FT . [1]
  • La spécialisation (le cas échéant) générée par la déduction d'arguments de template pour chaque fonction template nommée est également ajoutée à S .

Si la cible est de type pointeur de fonction ou référence à une fonction, S ne peut inclure que des fonctions non membres , des fonctions membres à objet explicite (depuis C++23) et des fonctions membres statiques. Si la cible est de type pointeur vers une fonction membre, S ne peut inclure que des fonctions membres à objet implicite.

  1. En d'autres termes, la classe dont la fonction est membre est ignorée si le type cible est un type pointeur-vers-fonction-membre.

Élimination des fonctions

Après avoir formé l'ensemble S , les fonctions sont éliminées dans l'ordre suivant :

  • Toutes les fonctions avec des contraintes associées qui ne sont pas satisfaites sont éliminées de l'ensemble S .
(depuis C++20)
  • Si plus d'une fonction dans S subsiste, toutes les spécialisations de modèle de fonction dans S sont éliminées si S contient également une fonction non-template.
(depuis C++20)
  • Toute spécialisation de fonction template donnée spec est éliminée si S contient une seconde spécialisation de fonction template dont le modèle de fonction est plus spécialisé que le modèle de fonction de spec .

Après de telles éliminations (s'il y en a), exactement une fonction sélectionnée doit rester dans S . Sinon, le programme est mal formé.

Exemple

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. initialisation
    int (*pf)(double) = f; // sélectionne int f(double)
    int (&rf)(int) = f; // sélectionne int f(int)
    int (Foo::*mpf)(int) = &Foo::mf; // sélectionne int mf(int)
    // 2. assignation
    pf = nullptr;
    pf = &f; // sélectionne int f(double)
    // 3. argument de fonction
    g(f, f); // sélectionne int f(int) pour le 1er argument
             // et int f(double) pour le second
    // 4. opérateur défini par l'utilisateur
    Emp{} << f; // sélectionne int f(double)
    // 5. valeur de retour
    auto foo = []() -> int (*)(int)
    {
        return f; // sélectionne int f(int)
    };
    // 6. cast
    auto p = static_cast<int(*)(int)>(f); // sélectionne int f(int)
    // 7. argument de template
    Templ<f> t;  // sélectionne int f(int)
    // empêche les avertissements "variable inutilisée" comme avec [[maybe_unused]]
    [](...){}(pf, rf, mpf, foo, p, t);
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
CWG 202 C++98 l'argument template constant n'était pas un contexte
pour prendre l'adresse d'une fonction surchargée
c'est le cas
CWG 250 C++98 les spécialisations de template de fonction générées avec des arguments
template non déduits n'étaient pas sélectionnées dans l'ensemble de surcharge
également sélectionnées
CWG 1153 C++98 il n'était pas clair si un type de fonction donné correspondait au type cible clarifié
CWG 1563 C++11 il n'était pas clair si l'initialisation par liste était un contexte
pour prendre l'adresse d'une fonction surchargée
clarifié

Références

  • Norme C++23 (ISO/IEC 14882:2024) :
  • 12.3 Adresse de fonction surchargée [over.over]
  • Norme C++20 (ISO/IEC 14882:2020) :
  • 12.5 Adresse de fonction surchargée [over.over]
  • Norme C++17 (ISO/IEC 14882:2017) :
  • 16.4 Adresse de fonction surchargée [over.over]
  • Norme C++14 (ISO/CEI 14882:2014) :
  • 13.4 Adresse de fonction surchargée [over.over]
  • Norme C++11 (ISO/IEC 14882:2011) :
  • 13.4 Adresse de fonction surchargée [over.over]
  • Norme C++98 (ISO/CEI 14882:1998) :
  • 13.4 Adresse de fonction surchargée [over.over]