Historique de la question : L'ADL (Argument Dependent Lookup), également connu sous le nom de Koenig lookup, est apparu pour la première fois en C++ pour supporter la surcharge des opérateurs (en particulier operator<< et operator>> pour les types utilisateurs). L'objectif est de trouver correctement les fonctions lors du mélange des espaces de noms et des types utilisateurs.
Problème : Le mécanisme standard de recherche de fonctions peut "ignorer" une fonction si elle est déclarée dans un autre namespace que le point d'appel. L'ADL résout ce problème : le compilateur prend en compte l'espace de noms des types des arguments de la fonction pour résoudre les noms. Ce même mécanisme peut parfois conduire à un choix inattendu de surcharge ou à des ambiguïtés.
Solution : Lorsque l'on appelle une fonction dont les arguments sont des objets de namespaces utilisateurs, le compilateur recherche les fonctions surchargées appropriées non seulement dans le scope actuel, mais aussi dans tous les espaces de noms liés aux types des arguments.
Exemple de code :
namespace lib { struct Widget {}; void do_something(const Widget&) { std::cout << "Widget" << std::endl; } } using lib::Widget; void call(const Widget& w) { do_something(w); // do_something est trouvé via l'ADL }
Caractéristiques clés :
Si une fonction avec le même nom est déclarée dans deux namespaces et qu'un objet du second est passé, laquelle sera appelée ?
La fonction de l'espace de noms de l'argument, si elle correspond aux arguments, sera choisie grâce à l'ADL :
namespace A { struct S {}; void f(const S&) { std::cout << "A!"; } } namespace B { struct S {}; void f(const S&) { std::cout << "B!"; } } A::S a; B::S b; f(a); // appellera A::f via l'ADL f(b); // appellera B::f via l'ADL
L'ADL fonctionne-t-il avec des fonctions template ?
Oui, si la fonction template est définie dans un namespace correspondant au type de l'argument, l'ADL la trouvera lors de l'appel avec ce type.
L'ADL fonctionnera-t-il pour les pointeurs de fonction ?
Non, l'ADL ne s'applique pas lors de l'obtention d'un pointeur vers une fonction (par exemple, en prenant son adresse). Seulement lors de l'appel direct de la fonction.
Le projet a connecté plusieurs bibliothèques tierces, où chaque namespace avait son propre print(). Le code principal utilisait print() avec des objets de différentes classes. En raison de l'ADL, le compilateur a commencé à "choisir" une fonction du mauvais espace de noms.
Avantages :
Inconvénients :
Utilisation d'un appel qualifié (spécifier le namespace explicitement) :
lib::do_something(w); // Clair !
Avantages :
Inconvénients :