Страницы

Поиск по вопросам

понедельник, 11 февраля 2019 г.

Выбор кандидатов при вызове функций

Почему в следующем коде std::swap не рассматривается в качестве кандидата при вызове swap и приходится писать его полностью с пространством имён? Я ожидал, что обе функции (std::swap и smth::swap) попадут в кандидаты, а дальше выбор сделается на основе пареметров (как при перегрузке функций).
https://ideone.com/JGcZDR
#include
using namespace std;
struct smth { int x;
void swap(smth &s) { ////// error: no matching function for call to ‘smth::swap(int&, int&)’ ////// note: candidate: void smth::swap(smth&) ////// note: candidate expects 1 argument, 2 provided ////swap(x, s.x);
std::swap(x, s.x); } };
int main() { return 0; }


Ответ

Поиск неквалифицированных имен (unqualified name lookup) при вызове функции состоит из двух частей: обычного поиска и ADL-поиска.
Обычный поиск выполняется "изнутри наружу": из внутренней области видимости во все более и более охватывающие области видимости, пока хотя бы одно имя не найдено. Когда хотя бы одно имя найдено, обычный поиск немедленно прекращается
Какие области видимости просматриваются зависит от контекста. В вашем случае - это поим имени swap, использованного в определении функции-члена класса. Для такого контекста поиск выполняется в следующих областях видимости: локальная, класс smth, пространство имен ::. В процессе просмотра имя swap найдется в классе smth - это имя вашей же функции. Т.е. до поиска в глобальном пространстве имен дело не доходит вообще. ADL-поиск выполняется в пространствах имен, ассоциированных с типами аргументов вызываемой функции. Но в случае фундаментального типа int ADL не выполняется - у типа int нет ассоциированных пространств имен.
Более интересным был бы пример с
struct smth { std::string x;
void swap(smth &s) { swap(x, s.x); } };
В такой ситуации у типа std::string есть ассоциированное с ним пространство имен std. И ADL-поиск мог бы выполнить поиск в пространстве имен std (даже ваш using namespace std; не нужен) и найти там правильный std::swap. Однако особое правило unqualified name lookup говорит, что если обычный поиск нашел именно функцию-член класса, то ADL не выполняется вообще. Поэтому и здесь будет та же самая ошибка.

Комментариев нет:

Отправить комментарий