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

Я знаю, что такое 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. сначала обнаруживается пользовательский 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 в текущую область, которая имеет более высокий приоритет поиска.


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


person Rick    schedule 09.05.2020    source источник


Ответы (1)


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&), тогда вызов будет неоднозначным ...

person songyuanyao    schedule 09.05.2020
comment
Ждать. Нет приоритета между обычным неквалифицированным поиском имени и ADL? - person Rick; 09.05.2020
comment
@Rick Нет. Оба результата предварительно сформированы, и результаты помещаются в набор перегрузки, затем выполняется разрешение перегрузки, чтобы выбрать лучший. - person songyuanyao; 09.05.2020
comment
@Rick Насчет разрешения перегрузки? Короче говоря, если и Foo::swap, и std::swap являются равно жизнеспособными альтернативами, то побеждает не шаблонный вариант. - person songyuanyao; 09.05.2020
comment
Я знаю, что побеждает не шаблонный. Извините, не могли бы вы рассказать мне немного больше о шаблоне? Могу ли я получить специализированный шаблон, созданный std::swap, внедренный в глобальную область видимости во время компиляции? - person Rick; 09.05.2020
comment
введено в глобальную или текущую область видимости, где указано using std::swap? - person Rick; 09.05.2020
comment
@Rick Я предпочитаю думать, что имя (а не std::swap и его реализация) вводится в текущую область видимости, тогда поиск имени может найти его в текущей области. - person songyuanyao; 09.05.2020