0

I ont un cas où recherche et la résolution de surcharge se comporte différemment:résolution de surcharge, le nom des pointeurs de consultation et la fonction

  • pour la classe définie par l'utilisateur vs types intégrés vs std :: string
  • pour appel direct vs appel pointeur fonction

Je ne peux pas comprendre ce que les parties exacte de la norme justifient ces diffé les clôtures.

Considérons le code suivant 11 C++:

#include <iostream> 
#include <string> 

using namespace std; 

struct Test1 {}; 
struct Test2 {}; 

template<typename T> 
int f(T t) { return 0; } 

int f(Test1 t) { return 10; } 
int f(int y) { return 20; } 

template<typename T> 
int use1() { return f(T()); } 

template<typename T> 
int use2() { auto fp = static_cast<int(*)(T)>(&f); return (*fp)(T()); } 

int f(Test2 t) { return 30; } 
int f(string s) { return 40; } 
int f(double y) { return 50; } 

int main() { 
    cout << "use1<float>: " << use1<float>() << endl; 
    cout << "use1<Test1>: " << use1<Test1>() << endl; 
    cout << "use1<int>: " << use1<int>() << endl; 
    cout << "use1<Test2>: " << use1<Test2>() << endl; 
    cout << "use1<string>: " << use1<string>() << endl; 
    cout << "use1<double>: " << use1<double>() << endl; 
    cout << endl; 
    cout << "use2<float>: " << use2<float>() << endl; 
    cout << "use2<Test1>: " << use2<Test1>() << endl; 
    cout << "use2<int>: " << use2<int>() << endl; 
    cout << "use2<Test2>: " << use2<Test2>() << endl; 
    cout << "use2<string>: " << use2<string>() << endl; 
    cout << "use2<double>: " << use2<double>() << endl; 
    return 0; 
} 

sortie est (même avec g ++ ++ 6.3 et 5.0.0 bruit tronc):

use1<float>: 0 
use1<Test1>: 10 
use1<int>: 20 
use1<Test2>: 30 
use1<string>: 0 
use1<double>: 0 

use2<float>: 0 
use2<Test1>: 10 
use2<int>: 20 
use2<Test2>: 0 
use2<string>: 0 
use2<double>: 0 

Questions :

  1. Pourquoi use1<string> est différent de use1<Test2>? Les deux types sont déclarés "en haut", les deux surcharges f() sont déclarées en bas.
  2. Pourquoi use1<Test2> est différent de use1<double>? Les surcharges f() correspondantes sont sur les lignes adjacentes, y a-t-il quelque chose de spécial dans le traitement des types intégrés?
  3. Pourquoi use1<Test2> est différent de use2<Test2>? Le type d'un pointeur à utiliser dans use2 semble correspondre au contexte appelant dans use1.

Répondre

0

Recherche de nom en deux phases. Au point où use1 est défini, trois surcharges de f sont visibles via une recherche normale. Au moment de l'instanciation, des surcharges supplémentaires peuvent être trouvées - mais seulement par une recherche dépendant de l'argument. Test2 est dans l'espace de noms global, donc f(Test2) est trouvé par ADL; tandis que string est dans l'espace de noms std, et donc f(string) (qui n'est évidemment pas dans l'espace de noms std) n'est pas trouvé par ADL. double n'a aucun espace de noms associé, et ADL ne démarre pas du tout.

Dans use2, f n'est pas un nom dépendant, et donc la recherche de deuxième phase n'est pas effectuée du tout - seules les surcharges visibles au moment de la définition sont prises en compte.

+0

Merci beaucoup! En ce qui concerne use2: existe-t-il un moyen d'utiliser 2 pour obtenir un pointeur de fonction contenant l'adresse de la même surcharge de f() résolue en cours d'utilisation1 ? – salmin

+0

Je ne peux pas penser à un moyen de "dépendre" d'un nom. La norme envisage uniquement la deuxième phase de recherche lorsque le nom est utilisé dans un appel de fonction directe, 'name (some_args)', et pas dans d'autres cas où une résolution de surcharge peut devoir être effectuée. –