Страницы

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

понедельник, 6 января 2020 г.

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

#cpp #функции


Почему в следующем коде 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;
}

    


Ответы

Ответ 1



Поиск неквалифицированных имен (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 не выполняется вообще. Поэтому и здесь будет та же самая ошибка.

Ответ 2



Можете добавить using в swap: void swap(smth &s) { using std::swap; swap(x, s.x);//ok }

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

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