Проблема поиска имени ADL, используется std :: swap; swap (a, b), связанный с перегрузкой функции или функцией внутренней области видимости, скрывает функцию внешней области видимости? - PullRequest
1 голос
/ 09 мая 2020

Я знаю, что такое ADL, и я знаю, что в C ++ функция внутренней области видимости скрывает функции внешней области. То есть имена не перегружают области действия. Таким образом, перегрузка функций должна выполняться в той же области.

Итак, теперь мой вопрос для этого общего фрагмента кода:

#include <iostream>
#include <string>
using std::cout;
using std::endl;

namespace Foo{
    class Bar{
        friend void swap(Bar& a, Bar& b);
    };
    void swap(Bar& a, Bar& b){
        cout << "I am here" << endl;
    }
}

int main(int argc, char *args[]){
    Foo::Bar a, b;
    using std::swap; //These 2 lines
    swap(a, b);      //output is "I am here", Foo::swap is called
}

Наряду с ADL это:

  1. custom swap и std::swap видны и считаются перегруженными, а затем выбирается наилучшее совпадение? Сначала будет найдено

  2. custom swap поиск имени прекращается (std::swap скрыт)?


Если 1. истинно, как это работает? Перегрузка функции в двух разных областях? Это противоречит тому, что я писал в начале. using std::swap ввести std::swap в текущую область. А кастом swap находится в Foo::swap.

Кстати, этот ответ Что такое «поиск, зависящий от аргументов» (он же ADL или «поиск по Кенигу»)? , кажется, указывает на то, что они являются перегрузкой функций.

Далее, если по какой-то причине определены и A::swap(A::MyClass&, A::MyClass&), и std::swap(A::MyClass&, A::MyClass&), тогда в первом примере будет вызываться std::swap(A::MyClass&, A::MyClass&) , но второй не будет компилироваться, потому что swap(obj1, obj2) будет неоднозначным .

Если это перегрузка функций, почему мой swap(Bar& a, Bar& b) не имеет проблему двусмысленности, как он описывает? Он не прав?


если 2. верно, согласно C ++ Primer 5th 18.2.3 :

std::cin >> s;

эквивалентно:

operator>>(std::cin, s);

В этом примере, когда компилятор видит «вызов» operator>>, он ищет соответствующую функцию в текущей области , , включая области, содержащие оператор вывода. . Помимо , поскольку выражение >> имеет параметры типа класса, компилятор также просматривает пространство (пространства) имен, в котором определены типы cin и s. Таким образом, для этого вызова компилятор просматривает пространство имен std, которое определяет типы istream и string. Когда он выполняет поиск std, компилятор находит функцию оператора вывода string.

Таким образом, порядок поиска имени следующий: текущая область -> охватывающие области -> область пространства имен аргументов .

Тогда почему std::swap не скрывает пользовательский swap? using std::swap вводит std::swap в текущую область действия, которая имеет более высокий приоритет поиска.


Оба моих предположения кажутся неверными для некоторых пионтов, и я запутался. Нужна помощь. Заранее спасибо.

1 Ответ

1 голос
/ 09 мая 2020

1. верно. Для ADL ,

Эти имена функций ищутся в пространствах имен их аргументов в дополнение к областям действия и пространствам имен, рассматриваемым при обычном поиске неквалифицированных имен .

std::swap обнаруживается обычным неквалифицированным поиском имени, а Foo::swap обнаруживается ADL, они оба находятся в наборе перегрузки. Foo::swap - это нешаблонная функция, относящаяся к std::swap, которая является шаблоном с разрешением перегрузки .

F1 определяется как лучшая функция, чем F2, если неявные преобразования для всех аргументов F1 не хуже , чем неявные преобразования для всех аргументов F2, и

...

4) или, если не то, F1 - это не шаблонная функция, а F2 - это специализация шаблона

А про цитату из связанного ответа

, если по какой-то причине и A::swap(A::MyClass&, A::MyClass&), и std::swap(A::MyClass&, A::MyClass&) определены,

Фактически нет std::swap(A::MyClass&, A::MyClass&), это просто предположение, если есть не шаблон std::swap(A::MyClass&, A::MyClass&), то вызов будет неоднозначным .. .

...