Если у нас есть функция в глобальном пространстве имен и перегрузка с другими типами аргументов в другом пространстве имен, то кажется, что компилятор 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?
Это похоже на ошибку компилятора для меня. В обоих случаях ADL должен
удар. В первом случае, это выглядит в пространстве имен A
,
включая имена в пространстве имен A
которые были объявлены только в
учебный класс a
и находит A::swap
, Во втором случае это выглядит в
глобальное пространство имен (так как это где b
определено),
включая имена в глобальном пространстве имен, которые были объявлены только
в классе b
и находит ::swap
,
Конечно, он начинается с поиска безоговорочного имени, который будет
найти C :: swap только в обоих случаях. Судя по всему, C ++ Builder как-то
Метки ::swap
как скрытый в этом случае, и не может рассмотреть это
в ADL. В случае ADL, однако, оба глобальных пространства имен
и пространство имен A должно рассматриваться одинаково.
Полные правила приведены в §3.4.2. Это довольно тяжело, но для
простые случаи, такие как ваш, последствия очевидны.
Члены локальной области с тем же именем, что и у глобальной, всегда скрывают глобальную, поэтому называйте ее какA::a::swap(first.dataA, second.dataA);
,