web-dev-qa-db-fra.com

Résolution de surcharge à la recherche dans les espaces de noms

Le code suivant échoue comme prévu, car aucune surcharge de get n'est trouvée. En utilisant std::get résoudrait le problème.

#include <array>

int main()
{
    std::array<int, 2> ar{2,3};
    auto r = get<0>(ar);//fails, get was not declared in this scope
}

Cependant, l'introduction d'une version basée sur un modèle de get, même si elle ne correspond pas à l'appel de fonction, oblige le compilateur à utiliser le std::get version:

#include <array>

template <typename T>
void get(){};

int main()
{
    std::array<int, 2> ar{2,3};

    auto r = get<0>(ar);//returns 2
}

Je ne trouve aucune partie de la norme qui explique cela. Est-ce un bug dans les 3 compilateurs que j'ai testés (probablement pas), ou est-ce que je manque quelque chose?

Ce comportement a été testé dans

  • MSVC 15.9.2
  • Clang 8.0.0
  • GCC 9.0.0 (toujours une version expérimentale)

EDIT: Je connais ADL. Mais si ADL fait fonctionner le second code, pourquoi ne le fait-il pas dans la première partie?

34
LcdDrm

ADL n'est pas utilisé lorsque des arguments de modèle explicites sont impliqués, sauf si vous introduisez une déclaration de fonction de modèle au point d'appel. Vous utilisez une forme non qualifiée de get en utilisant un argument de modèle non type 0, Vous devez donc introduire une déclaration de fonction de modèle ou utiliser la version qualifiée de get comme std::get<0>(ar).

En standard [temp.arg.explicit]/8: (C'est moi qui souligne)

[Remarque: pour les noms de fonction simples, la recherche dépendante de l'argument (6.4.2) s'applique même lorsque le nom de la fonction n'est pas visible dans la portée de l'appel. En effet, l'appel a toujours la forme syntaxique d'un appel de fonction (6.4.1). Mais lorsqu'un modèle de fonction avec des arguments de modèle explicites est utilisé, l'appel n'a pas la forme syntaxique correcte, sauf s'il existe un modèle de fonction avec ce nom visible au moment de l'appel. Si aucun nom de ce type n'est visible, le l'appel n'est pas bien formé syntaxiquement et la recherche dépendante de l'argument ne s'applique pas. Si un tel nom est visible, la recherche dépendante de l'argument s'applique et des modèles de fonction supplémentaires peuvent être trouvés dans d'autres espaces de noms.

MODIFIER:

Comme @Yakk - Adam Nevraumont l'a souligné dans le commentaire, sans la présence de la déclaration de fonction modèle, l'expression get<0>(ar) sera analysée comme (get<0)>(ar), C'est-à-dire comme une série d'expressions de comparaison à la place d'un appel de fonction.

20
Jans