Les iterators de conteneurs personnalisés garantissent-ils à ADL de prendre en compte namespace std?

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.