1

如果我们在全局命名空间中有一个函数,并且在另一个命名空间中有一个具有不同参数类型的重载,那么 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 中的一个错误?

4

2 回答 2

2

对我来说,它看起来像一个编译器错误。在这两种情况下,ADL 都应该发挥作用。在第一种情况下,它在 namespace 中查找A,包括 namespaceA中仅在 class 中声明的名称a,然后找到A::swap。在第二种情况下,它在全局命名空间中查找(因为这b是定义的位置),包括全局命名空间中仅在 class 中声明的名称b,并找到::swap.

当然,它从非限定名称查找开始,在这两种情况下都只会找到 C::swap。显然,C++Builder::swap在这种情况下以某种方式标记为隐藏,并且在 ADL 中没有考虑到它。然而,在 ADL 的情况下,全局命名空间和命名空间 A 应该被平等对待。

完整的规则在 §3.4.2 中。这很繁重,但是对于像您这样的简单案例,其含义是显而易见的。

于 2013-07-12T10:01:20.757 回答
0

与全局同名的本地范围的成员总是隐藏全局的,所以称之为,A::a::swap(first.dataA, second.dataA);

于 2013-07-12T09:48:18.253 回答