Address of an overloaded function
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
Fest sélectionnée pour le type de fonctionFTdu type cible siF(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.
- ↑ 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 :
|
(depuis C++20) |
-
Si plus d'une fonction dans
Ssubsiste, toutes les spécialisations de modèle de fonction dansSsont éliminées siScontient également une fonction non-template.
|
(depuis C++20) |
-
Toute spécialisation de fonction template donnée
spec
est éliminée si
Scontient 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]