2017-04-26 5 views
0

Je travaille actuellement sur 'Effective Modern C++' pour mettre à jour mes connaissances du langage, et je viens juste de terminer le point 27, qui traite des fonctions de surcharge qui prennent de l'avance (ou le livre les appelle) références. En utilisant le code suivant je l'ai écrit:Résolution des arguments/paramètres de la fonction en C++

#include <iostream> 

template <typename T> 
void func(T&& param) { 
    std::cout << "forwarding reference version\n"; 
} 

void func(int param) { 
    std::cout << "int version\n"; 
} 

int main() { 
    func(29); 
} 

S'il vous plaît quelqu'un peut-il expliquer pourquoi la version int est appelée, même si 29 est un rvalue et donc le modèle devrait instancier à « void Func (int & & param) » et appel devrait être à la version de transfert? De toute évidence, c'est ce que c'est, et il me manque manifestement de la compréhension, mais des éclaircissements sur ce point seraient utiles. Je comprends que la norme dit dans le cas de signatures de fonctions identiques, une fonction non-basée sur le modèle devrait être préférée, mais (dans mon esprit au moins) cela ne s'applique pas ici? Merci beaucoup.

Cordialement, Phil

+0

Remarque 'func (int &&)' n'est pas une meilleure correspondance que 'func (int)'. Si vous avez ces deux types de non-modèles, l'appel est ambigu. – aschepler

+0

Parce que sûrement le modèle de correspondance void func (int && param) serait meilleur que void func (int param) - ils ne sont pas les mêmes. Ou suis-je juste un idiot? Entièrement possible j'admets :-) – PhilPotter1987

+0

@aschepler: ah, je vois, c'est là que mon manque de compréhension est. J'ai supposé qu'ils seraient différents et surchargeables - n'ont pas réellement essayé cela. S'il vous plaît poster cela comme une réponse et je serai heureux d'accepter. – PhilPotter1987

Répondre

5

L'appel func(29) correspond à la fonction void func(int) sans conversions nécessaires. Ceci est connu comme la conversion d'identité pour la résolution de surcharge, qui est dans la catégorie de classement Exact Match.

Les règles de classement pour meilleure fonction viable dans [over.match.best] spécifient quand les fonctions correspondent mieux que d'autres fonctions pendant la résolution de surcharge.

Une conversion d'identité n'est jamais une pire séquence de conversion que toute autre séquence de conversion, selon [over.ics.rank], donc void func(int) ne peut jamais être battu sous les 5 premières règles. Règle 6 est:

F1 est définie comme une meilleure fonction qu'une autre fonction viable F2 si tous les arguments

[...]

F1 n'est pas une spécialisation de modèle de fonction et F2 est une spécialisation de modèle de fonction, [...]

Ainsi, une conversion d'identité non-template gagne toujours sur n'importe quelle instanciation de modèle.