Ответ 1
Lookup Koenig, или Argument Dependent Lookup, описывает, как неквалифицированные имена ищутся компилятором в C++.
Стандарт C++ 11 § 3.4.2/1 гласит:
Когда выражение postfix в вызове функции (5.2.2) является безусловным идентификатором, могут быть найдены другие пространства имен, не учитываемые во время обычного безусловного поиска (3.4.1), и в этих пространствах имен объявления функций друзей области видимости области пространства ( 11.3) может быть найдено не видимое иное. Эти модификации поиска зависят от типов аргументов (и для аргументов шаблона шаблона - пространства имен аргумента шаблона).
В более простых сроках Николай Йосуттис заявляет 1:
Вам не нужно указывать пространство имен для функций, если в пространстве имен функции определен один или несколько типов аргументов.
Простой пример кода:
namespace MyNamespace
{
class MyClass {};
void doSomething(MyClass);
}
MyNamespace::MyClass obj; // global object
int main()
{
doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}
В приведенном выше примере нет ни using
-declaration, ни using
-directive, но все же компилятор правильно идентифицирует неквалифицированное имя doSomething()
как функцию, объявленную в пространстве имен MyNamespace
путем применения поиска Кенига.
Как это работает?
Алгоритм говорит компилятору не только смотреть на локальную область видимости, но также на пространства имен, которые содержат тип аргумента. Таким образом, в приведенном выше коде компилятор обнаруживает, что объект obj
, являющийся аргументом функции doSomething()
, принадлежит пространству имен MyNamespace
. Таким образом, он смотрит на это пространство имен, чтобы найти объявление doSomething()
.
В чем преимущество поиска Кенига?
Как показывает приведенный выше пример простого кода, поиск по Кенигу обеспечивает удобство и простоту использования для программиста. Без поиска Кенига программисту потребовалось бы много времени, чтобы повторно указывать полностью определенные имена или вместо этого использовать многочисленные, using
-declaration s.
Почему критика поиска Кенига?
Чрезмерная зависимость от поиска Кенига может привести к семантическим проблемам и иногда застать программиста врасплох.
Рассмотрим пример std::swap
, который является стандартным библиотечным алгоритмом для обмена двумя значениями. С поиском Кенига нужно было бы быть осторожным при использовании этого алгоритма, потому что:
std::swap(obj1,obj2);
может не показывать такое же поведение как:
using std::swap;
swap(obj1, obj2);
В случае ADL, какая версия функции swap
будет вызвана, будет зависеть от пространства имен передаваемых ей аргументов.
Если существует пространство имен A
и если A::obj1
, A::obj2
& A::swap()
существуют, то второй пример приведет к вызову A::swap()
, который может не соответствовать желанию пользователя,
Кроме того, если по какой-либо причине определены как A::swap(A::MyClass&, A::MyClass&)
и std::swap(A::MyClass&, A::MyClass&)
, то первый пример вызовет std::swap(A::MyClass&, A::MyClass&)
но второй не будет компилироваться, потому что swap(obj1, obj2)
будет неоднозначным.
Общая информация:
Почему это называется "поиск Кенига"?
Потому что он был разработан бывшим исследователем и программистом AT & T и Bell Labs Эндрю Кенигом.
Дальнейшее чтение:
-
Стандарт C++ 03/11 [basic.lookup.argdep]: 3.4.2 Поиск имени в зависимости от аргумента.
1 Определение поиска Кенига определено в книге Йосуттиса "Стандартная библиотека C++: учебное пособие и справочник".