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, usingale 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 objbę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 usingmusiał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 swapfunkcji 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::obj2i 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 .