Функция не найдена в глобальном пространстве имен, если есть перегрузка с различными типами аргументов

Если у нас есть функция в глобальном пространстве имен и перегрузка с другими типами аргументов в другом пространстве имен, то кажется, что компилятор C ++ Builder не находит функцию из глобального пространства имен.

namespace A
{
class a {
friend void swap(a& first, a& second) { }
};
}

class b {
friend void swap(b& first, b& second) { }
};

namespace C
{
class c {
A::a dataA;
b dataB;

friend void swap(c& first, c& second)
{
swap(first.dataA, second.dataA); // no problem
swap(first.dataB, second.dataB); // VC++12 compiles, C++Builder XE doesn't
}

friend void swap2(c& first, c& second) // no problem with a different name
{
swap(first.dataA, second.dataA);
swap(first.dataB, second.dataB);
}
};
}

C ++ Builder выдает следующие ошибки:

E2357 Reference initialized with 'b', needs lvalue of type 'c'
E2342 Type mismatch in parameter 'first' (wanted 'c &', got 'b')

Visual C ++ 2012 компилирует это без ошибок.

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

Я что-то пропустил, или это ошибка в C ++ Builder?

1

Решение

Это похоже на ошибку компилятора для меня. В обоих случаях ADL должен
удар. В первом случае, это выглядит в пространстве имен A,
включая имена в пространстве имен A которые были объявлены только в
учебный класс aи находит A::swap, Во втором случае это выглядит в
глобальное пространство имен (так как это где b определено),
включая имена в глобальном пространстве имен, которые были объявлены только
в классе bи находит ::swap,

Конечно, он начинается с поиска безоговорочного имени, который будет
найти C :: swap только в обоих случаях. Судя по всему, C ++ Builder как-то
Метки ::swap как скрытый в этом случае, и не может рассмотреть это
в ADL. В случае ADL, однако, оба глобальных пространства имен
и пространство имен A должно рассматриваться одинаково.

Полные правила приведены в §3.4.2. Это довольно тяжело, но для
простые случаи, такие как ваш, последствия очевидны.

2

Другие решения

Члены локальной области с тем же именем, что и у глобальной, всегда скрывают глобальную, поэтому называйте ее какA::a::swap(first.dataA, second.dataA);,

0