Jump to content

Поиск имени в зависимости от аргумента

В C++ языке программирования поиск по аргументу ( ADL ) или поиск по имени, зависящий от аргумента , [1] применяется к поиску неполного имени функции в зависимости от типов аргументов , переданных при вызове функции . Такое поведение также известно как поиск Кенига , поскольку его часто приписывают Эндрю Кенигу , хотя он не является его изобретателем. [2]

Во время поиска, зависящего от аргумента, могут выполняться поиск в других пространствах имен, не рассматриваемых при обычном поиске, при этом набор пространств имен, подлежащих поиску, зависит от типов аргументов функции. В частности, набор объявлений, обнаруженных в процессе ADL и рассматриваемых для разрешения имени функции, представляет собой объединение объявлений, найденных при обычном поиске, с объявлениями, найденными при поиске в наборе пространств имен, связанных с типами аргументов функции. .

Пример ADL выглядит так:

namespace NS {

class A {};

void f(A& a, int i) {}

}  // namespace NS

int main() {
   NS::A a;
   f(a, 0);  // Calls NS::f.
}

Несмотря на то, что основной функция не находится в пространстве имен NS, а пространство имен NS не находится в области видимости, функция НС::f(A&, интервал) находится из-за объявленных типов фактических аргументов в операторе вызова функции.

Распространенным шаблоном в стандартной библиотеке C++ является объявление перегруженных операторов, которые будут найдены таким образом. Например, эта простая программа Hello World не скомпилировалась бы, если бы не ADL:

#include <iostream>
#include <string>

int main() {
  std::string str = "hello world";
  std::cout << str;
}

С использованием << эквивалентно вызову operator<< без std:: квалификатор. Однако в этом случае перегрузка оператора<<, которая работает для string находится в std пространство имен, поэтому для его использования требуется ADL.

Следующий код будет работать без ADL (который в любом случае к нему применяется):

#include <iostream>

int main() {
  std::cout << 5;
}

Это работает, потому что оператор вывода целых чисел является функцией-членом std::ostream класс, который является типом cout. Таким образом, компилятор интерпретирует это утверждение как

std::cout.operator<<(5);

который он может разрешить во время обычного поиска. Однако учтите, что, например, const char * перегружен operator<< является функцией, не являющейся членом в std пространство имен и, следовательно, требует ADL для правильного поиска:

/* will print the provided char string as expected using ADL derived from the argument type std::cout */
operator<<(std::cout, "Hi there")

/* calls a ostream member function of the operator<< taking a void const*,  
which will print the address of the provided char string instead of the content of the char string */ 
std::cout.operator<<("Hi there")

The std пространство имен перегружено, не является членом operator<< функция для обработки строк — еще один пример:

/*equivalent to operator<<(std::cout, str). The compiler searches the std namespace using ADL due to the type std::string of the str parameter and std::cout */
std::cout << str;

Как отмечает Кениг в личной заметке, [2] без ADL компилятор укажет на ошибку, сообщив, что не удалось найти operator<< поскольку в заявлении явно не указано, что оно находится в std пространство имен.

Интерфейсы

[ редактировать ]

Функции, найденные ADL, считаются частью интерфейса класса. В стандартной библиотеке C++ несколько алгоритмов используют неквалифицированные вызовы swap изнутри std пространство имен. В результате общий std::swap функция используется, если больше ничего не найдено, но если эти алгоритмы используются со сторонним классом, Foo, найденный в другом пространстве имен, которое также содержит swap(Foo&, Foo&), эта перегрузка swap будет использоваться.

Хотя ADL позволяет функциям, определенным вне класса, вести себя так, как если бы они были частью интерфейса этого класса, он делает пространства имен менее строгими и поэтому может требовать использования полных имен, когда в противном случае они не были бы необходимы. Например, стандартная библиотека C++ широко использует неквалифицированные вызовы std::swap поменять местами два значения. Идея состоит в том, что тогда можно определить собственную версию swap в собственном пространстве имен и будет использоваться в алгоритмах стандартной библиотеки. Другими словами, поведение

namespace N {

struct A {};

}  // namespace N

A a;
A b;

std::swap(a, b);

может совпадать, а может и не совпадать с поведением

using std::swap;
swap(a, b);

(где a и b относятся к типу N::A), потому что если N::swap(N::A&, N::A&) существует, второй из приведенных выше примеров вызовет его, а первый — нет. Более того, если по какой-то причине оба N::swap(N::A&, N::A&) и std::swap(N::A&, N::A&) определены, то первый пример вызовет std::swap(N::A&, N::A&) но второй не скомпилируется, потому что swap(a, b) было бы неоднозначно.

В общем, чрезмерная зависимость от ADL может привести к семантическим проблемам. Если одна библиотека, L1, ожидает неквалифицированных вызовов на foo(T) иметь одно значение и другую библиотеку, L2 ожидает, что у него будет другое, тогда пространства имен теряют свою полезность. Если, однако, L1 ожидает L1::foo(T) иметь одно значение и L2 делает то же самое, то конфликта нет, а вызывает foo(T) должен быть полностью квалифицирован (т. L1::foo(x) в отличие от using L1::foo; foo(x);), чтобы ADL не мешал.

  1. ^ «Рабочий проект стандарта языка программирования C++» (PDF) . JTC1/SC22/WG21 . 19 октября 2005 г. Глава 3.4.2 – Поиск имени в зависимости от аргумента – стр. 2. Архивировано из оригинала (PDF) 14 декабря 2005 г. Проверено 13 марта 2012 г.
  2. ^ Перейти обратно: а б «Личное замечание о поиске по аргументам» . 3 мая 2012 г. Архивировано из оригинала 17 марта 2018 г. . Проверено 7 февраля 2014 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 1039cb86fe3c3df573eb7629f42ebc06__1708151580
URL1:https://arc.ask3.ru/arc/aa/10/06/1039cb86fe3c3df573eb7629f42ebc06.html
Заголовок, (Title) документа по адресу, URL1:
Argument-dependent name lookup - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)