Поиск Кенига или Аргумент-зависимый поиск описывает, как компилятор ищет в C ++ неквалифицированные имена.
Стандарт C ++ 11 § 3.4.2 / 1 гласит:
Когда постфиксным выражением в вызове функции (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
-декларации, ни using
-директивы, но все же компилятор правильно определяет неквалифицированное имя doSomething()
как функцию, объявленную в пространстве имен MyNamespace
, применяя Koenig поиск .
Как это работает?
Алгоритм говорит компилятору не только смотреть на локальную область видимости, но также на пространства имен, которые содержат тип аргумента. Таким образом, в приведенном выше коде компилятор обнаруживает, что объект obj
, являющийся аргументом функции doSomething()
, принадлежит пространству имен MyNamespace
. Таким образом, он ищет в этом пространстве имен объявление doSomething()
.
В чем преимущество поиска Кенига?
Как показывает простой пример кода выше, поиск по Кенигу обеспечивает удобство и простоту использования для программиста. Без поиска Кенига программисту потребовалось бы много времени, чтобы повторно указывать полностью определенные имена или вместо этого использовать многочисленные using
-декларации.
Почему критика поиска Кенига?
Чрезмерная зависимость от поиска Кенига может привести к семантическим проблемам и иногда застать программиста врасплох.
Рассмотрим пример 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, Эндрю Кениг .
Дальнейшее чтение:
1 Определение поиска Кенига определено в книге Джозуттиса, Стандартная библиотека C ++: Учебное пособие и справочник .