194 votes

Qu'est-ce que la "recherche dépendante de l'argument" (ADL, ou "recherche Koenig")?

Quelles sont quelques bonnes explications sur ce qu'est la recherche dépendante d'un argument? Beaucoup de gens l'appellent aussi Koenig Lookup.

J'aimerais de préférence savoir:

  • Pourquoi est-ce une bonne chose?
  • Pourquoi est-ce une mauvaise chose?
  • Comment ça marche?

(Remarque: il s'agit d'une entrée de la FAQ C ++ de Stack Overflow .)

253voto

Alok Save Points 115848

Koenig de Recherche est également connue comme Argument Dépendante de Recherche en C++ et la plupart de la Norme compilateurs C++ en charge.

Le C++11 standard § 3.4.2/1 membres:

Lorsque le suffixe-expression dans un appel de fonction (5.2.2) est un franc-id, d'autres espaces de noms pas considérés lors de l'habituelle non qualifiés de recherche (3.4.1) peuvent être recherchés, et dans les espaces de noms, de noms-portée ami déclarations de fonction (11.3), non visible peut être trouvé. Ces modifications à la recherche dépendent des types d'arguments (et pour le modèle arguments de modèle, l'espace de noms du modèle l'argument).

En termes plus simples, Nicolai Josuttis états1:

Vous n'avez pas à qualifier l'espace de noms de fonctions, si un ou plusieurs types d'arguments sont définis dans l'espace de nom de la fonction.

Un exemple de code simple:

namespace MyNamespace
{
    class MyClass {};
    void doSomething(MyClass);
}

MyNamespace::MyClass obj; // global object


int main()
{
    doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}

Dans l'exemple ci-dessus il n'y a ni using-declaration ni using-directive , mais le compilateur identifie correctement le nom non qualifié doSomething() que la fonction déclarée dans l'espace de noms MyNamespace par l'application de l' Koenig algorithme.

Comment ça fonctionne?
L'algorithme indique au compilateur de ne pas seulement regarder une portée locale, mais aussi les espaces de noms qui contiennent de l'argument type. Ainsi, dans le code ci-dessus, le compilateur trouve que l'objet obj, ce qui est l'argument de la fonction doSomething(), appartient à l'espace de noms MyNamespace. Ainsi, il semble à l'espace de noms pour localiser la déclaration d' doSomething().

Quel est l'avantage d' Koenig Lookup?
Le simple exemple de code ci-dessus montre au-dessus de la Koenig Algorithme fournit la commodité et la facilité d'utilisation pour le programmeur. Sans Koenig Algorithme il y aurait une surcharge sur le programmeur, à plusieurs reprises spécifier les noms entièrement qualifiés, ou plutôt de les utiliser de nombreux, à l'aide de déclarations.

Pourquoi la critique de l' Koenig Algorithm?
La dépendance par rapport au Koenig Algorithme peut conduire à des problèmes sémantiques,et attraper le programmeur hors garde parfois.

Prenons l'exemple de std::swap, qui est une bibliothèque standard de l'algorithme pour échanger deux valeurs. Avec l'Koenig algorithme il faut être prudent lors de l'utilisation de cet algorithme, car:

std::swap(obj1,obj2);    

ne peut pas afficher le même comportement que:

using std::swap;
swap(obj1, obj2);

Avec l'ADL, la version de swap fonction est appelée dépendra de l'espace de noms des arguments passés.
S'il existe un espace de noms A et si A::obj1, A::obj2 & A::swap() , alors que le deuxième exemple se traduit par un appel à l' A::swap() ce qui pourrait ne pas être ce que l'utilisateur veut.

De plus, si pour une raison tout à la fois:
A::swap(A::MyClass&, A::MyClass&) et std::swap(A::MyClass&, A::MyClass&) sont définies, puis le premier exemple appellera std::swap(A::MyClass&, A::MyClass&) , mais la seconde ne sera pas compiler, car swap(obj1, obj2) d'être ambigu.

Trivia:
Pourquoi est-il appelé Koenig Lookup?
Parce qu'il a été conçu par l'ancien AT&T et Bell Labs chercheur et programmeur,Andrew Koenig.


Bonnes Lectures:

Herb Sutter est à la Recherche d'un Nom sur GotW
Standard C++03/11 [de base.de recherche.argdep]: 3.4.2 Argument dépendant de recherche de nom.


1 La définition de Koenig Algorithme est tel que défini dans Josuttis du livre, Le C++ Standard Library: Un Tutoriel et de Référence.

81voto

Nawaz Points 148870

Dans Koenig de Recherche, si une fonction est appelée, sans le spécifier l'espace de noms, le nom d'une fonction est aussi de la recherche dans l'espace de noms(s) dans laquelle le type de l'argument(s) est définie. C'est pourquoi il est également connu comme Argument Dépendant de Recherche de nom, bref, l'ADL.

C'est à cause de Koenig Recherche, nous pouvons écrire ceci:

std::cout << "Hello World!" << std::endl;

Sinon, en l'absense de Koenig de Recherche, nous avons à écrire:

std::operator<<(std::operator<<(std::cout, "Hello World!"), std::endl);

ce qui est vraiment trop typying et le code est vraiment laid!

En d'autres termes, en l'absence de Koenig de Recherche, même un Bonjour tout le Monde, le programme s'annonce compliquée.

31voto

celtschk Points 9699

Peut-être qu'il est préférable de commencer avec la raison, et seulement ensuite à le faire.

Lorsque les espaces de noms ont été introduits, l'idée était d'avoir tout ce que définis dans des espaces de noms, de sorte que spearate bibliothèques n'interfèrent pas les uns avec les autres. Cependant, qui a introduit un problème avec les opérateurs. Regardez par exemple le code suivant:

namespace N
{
  class X {};
  void f(X);
  X& operator++(X&);
}

int main()
{
  // define an object of type X
  N::X x;

  // apply f to it
  N::f(N::x);

  // apply operator++ to it
  ???
}

Bien sûr, vous pourriez avoir écrit N::operator++(x), mais qui aurait vaincu le point de l'ensemble de la surcharge d'opérateur. Par conséquent, une solution devait être trouvée, qui a permis le compilateur de trouver operator++(X&) malgré le fait qu'il n'était pas dans le champ d'application. D'autre part, il reste ne devrait pas trouver un autre operator++ défini dans un autre, sans rapport avec l'espace de noms susceptibles de faire l'appel ambigu (dans cet exemple simple, vous n'en aurez pas d'ambiguïté, mais en plus complexe de l'examen,les eap vous pourriez). La solution a été Argument Dépendante de Recherche (ADL), appelé ainsi depuis la recherche dépend de l'argument (ou plus exactement, sur l'argument du type). Depuis que le programme a été inventé par Andrew R. Koenig, il est également souvent appelé Koenig de recherche.

Le truc, c'est que pour les appels de fonction, en plus de la recherche de nom (qui trouve les noms dans le champ d'application au moment de l'utilisation), il est procédé à une deuxième recherche dans les champs de tous les types de arguments passés à la fonction. Ainsi, dans l'exemple ci-dessus, si vous écrivez x++ dans la principale, il semble pour l' operator++ non seulement dans la portée globale, mais en plus dans le champ d'application lorsque le type d' x, N::X, a été définie, c'est à dire en namespace N. Et là, il trouve un mathing operator++, et, par conséquent, x++ fonctionne, tout simplement. Un autre operator++ défini dans un autre espace de noms, disons N2, ne sera pas trouvé, cependant. Depuis ADL n'est pas limitée à des espaces de noms, vous pouvez également utiliser f(x) au lieu de N::f(x) en main().

21voto

Pas tout, c'est bon, à mon avis. Les gens, y compris les éditeurs de compilateurs, ont été insultant parce qu'il a parfois malheureusement ce comportement.

L'ADL est responsable d'une refonte complète de la gamme de boucle en C++11. Pour comprendre pourquoi l'ADL peut parfois avoir des effets inattendus, considèrent que non seulement les espaces de noms, où les arguments sont définis, sont considérés comme, mais aussi les arguments des arguments de modèle de l'argumentation, de types de paramètres de types de fonctions / pointee types de types de pointeur de ces arguments, et ainsi de suite.

Un exemple d'utilisation de boost

std::vector<boost::shared_ptr<int>> v;
auto x = begin(v);

Il en est résulté une ambiguïté si l'utilisateur utilise le boost.plage de la bibliothèque, parce que les deux std::begin (par ADL à l'aide de std::vector) et boost::begin (par ADL à l'aide de boost::shared_ptr).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X