Je n’ai aucune intention d’utiliser ceci dans du code réel. Je promets.
La norme garantit-elle que l’espace de noms std
sera trouvé lorsqu’un argument de fonction est de type container::iterator
et container::iterator
n’est pas une typedef
pour un type intégré?
Par exemple
#include #include int main() { std::set s; find(s.begin(), s.end(), 0); //do I have a guarantee that std::find will be found? }
En d’autres termes, la classe d’iterators peut-elle être définie dans un tel espace de noms que std
ne sera pas pris en compte par ADL?
Merci d’avance.
Je crois que la réponse est non dans le cas le plus général, mais oui dans la plupart des applications pratiques.
Selon la norme ISO C ++, §3.4.2 / 2, il existe une notion d ‘”espace de nommage associé” pour un argument, défini de manière à inclure
Si T est un type de classe (y compris les unions), ses classes associées sont les suivantes: la classe elle-même; la classe à laquelle il appartient, le cas échéant ; et ses classes de base directes et indirectes. Ses espaces de noms associés sont les espaces de noms dans lesquels ses classes associées sont définies.
Cela suggère que si le type d’iterator est vraiment un type nested dans un conteneur tel que std::set
, un espace de noms associé à cet iterator dans l’appel à find
serait std
, puisque std::set
est une classe associée et que std
est l’espace de noms contenant l’ set
. La norme indique alors que (§3.4.2 / 2a)
Si la recherche ordinaire non qualifiée du nom trouve la déclaration d’une fonction membre de la classe, les espaces de nom et les classes associés ne sont pas pris en compte. Sinon, l’ensemble des déclarations trouvées par la recherche du nom de la fonction est l’union de l’ensemble des déclarations trouvées à l’aide de la recherche ordinaire non qualifiée et de l’ensemble des déclarations trouvées dans les espaces de noms et les classes associées aux types d’argument .
Cela voudrait dire que vous trouveriez effectivement la fonction de find
dans le namespace std
Cependant, cela n’est pas garanti pour fonctionner en général. Nous avons également de la spécification (§3.4.2) que
Les noms de typedef et using-declarations utilisés pour spécifier les types ne consortingbuent pas à cet ensemble.
Ainsi, comme vous l’avez mentionné dans votre question, si le type d’iterator est une sorte de typedef
, il n’est pas garanti que cela fonctionne correctement. Mais à part cela, il semble que si vous savez que le type n’est pas un typedef, il doit être dans un namespace std
de namespace std
ou nested dans une classe dans un namespace std
de namespace std
et doit être récupéré pour ADL. Mais ne le fais pas! 🙂
Le type exact de ::iterator
etc., pour les conteneurs standard est défini par l’implémentation . Par conséquent, rien ne l’empêche en principe de faire typedef
de typedef
pour quelque chose en dehors de std::
(par exemple, un pointeur normal).
Je ne trouve rien dans la norme qui suggère que l’ADL fonctionnera toujours dans ce cas, donc – à moins que quelqu’un me corrige – je vais devoir dire que la réponse est: non, vous ne pouvez pas supposer cette find
sera trouvée via ADL.