Koenig Lookup lub Argument Dependent Lookup opisuje, jak niekwalifikowane nazwy są wyszukiwane przez kompilator w C ++.
Standard C ++ 11, § 3.4.2 / 1, stwierdza:
Gdy wyrażenie postfiksowe w wywołaniu funkcji (5.2.2) jest niekwalifikowanym identyfikatorem, można przeszukiwać inne przestrzenie nazw nieuwzględniane podczas zwykłego wyszukiwania bez kwalifikacji (3.4.1), aw tych przestrzeniach nazw deklaracje funkcji zaprzyjaźnionych z zakresem przestrzeni nazw ( 11.3), które nie są widoczne w inny sposób. Te modyfikacje wyszukiwania zależą od typów argumentów (aw przypadku argumentów szablonu szablonu, przestrzeni nazw argumentu szablonu).
Mówiąc prościej, Nicolai Josuttis stwierdza 1 :
Nie musisz kwalifikować przestrzeni nazw dla funkcji, jeśli jeden lub więcej typów argumentów jest zdefiniowanych w przestrzeni nazw funkcji.
Prosty przykład kodu:
namespace MyNamespace
{
class MyClass {};
void doSomething(MyClass);
}
MyNamespace::MyClass obj; // global object
int main()
{
doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}
W powyższym przykładzie nie ma ani using
-declaration ani -directive, using
ale mimo to kompilator poprawnie identyfikuje niekwalifikowaną nazwę doSomething()
jako funkcję zadeklarowaną w przestrzeni nazw MyNamespace
, stosując wyszukiwanie Koeniga .
Jak to działa?
Algorytm mówi kompilatorowi, aby nie tylko sprawdzał zakres lokalny, ale także przestrzenie nazw zawierające typ argumentu. Zatem w powyższym kodzie kompilator stwierdza, że obiekt obj
będący argumentem funkcji doSomething()
należy do przestrzeni nazw MyNamespace
. Dlatego sprawdza tę przestrzeń nazw, aby zlokalizować deklarację doSomething()
.
Jaka jest zaleta wyszukiwania Koenig?
Jak pokazuje powyższy prosty przykład kodu, wyszukiwanie Koeniga zapewnia programiście wygodę i łatwość użycia. Bez wyszukiwania Koenig programista using
musiałby obciążać narzut, aby wielokrotnie określać w pełni kwalifikowane nazwy, lub zamiast tego używać wielu -deklaracji.
Skąd krytyka wyszukiwania Koeniga?
Nadmierne poleganie na wyszukiwaniu Koenig może prowadzić do problemów semantycznych i czasami zaskakiwać programistę.
Rozważmy przykład std::swap
, który jest standardowym algorytmem biblioteki do zamiany dwóch wartości. W przypadku wyszukiwania Koeniga należałoby zachować ostrożność podczas korzystania z tego algorytmu, ponieważ:
std::swap(obj1,obj2);
mogą nie zachowywać się tak samo jak:
using std::swap;
swap(obj1, obj2);
W przypadku ADL to, która wersja swap
funkcji zostanie wywołana, zależy od przestrzeni nazw przekazywanych do niej argumentów.
Jeśli istnieje przestrzeń nazw A
, a jeśli A::obj1
, A::obj2
i A::swap()
istnieje wówczas drugi przykład spowoduje wywołanie A::swap()
, który może nie być czego chce użytkownik.
Ponadto, jeśli z jakiegoś powodu oba A::swap(A::MyClass&, A::MyClass&)
i std::swap(A::MyClass&, A::MyClass&)
są zdefiniowane, to pierwszy przykład zostanie wywołany, std::swap(A::MyClass&, A::MyClass&)
ale drugi nie zostanie skompilowany, ponieważ swap(obj1, obj2)
byłby niejednoznaczny.
Drobnostki:
Dlaczego nazywa się to „wyszukiwaniem Koeniga”?
Ponieważ został opracowany przez byłego badacza i programistę AT&T i Bell Labs, Andrew Koeniga .
Czytaj dalej:
1 Definicja wyszukiwania Koeniga jest taka, jak zdefiniowano w książce Josuttisa, The C ++ Standard Library: A Tutorial and Reference .