如果存在具有不同参数类型的重载,则无法从全局命名空间找到函数

时间:2013-07-12 09:40:36

标签: c++ namespaces c++builder c++builder-xe name-lookup

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

2 个答案:

答案 0 :(得分:2)

对我来说,它看起来像编译器错误。在这两种情况下,ADL应该 在第一种情况下,它在名称空间A中查找, 包括名称空间A中仅在其中声明的名称 类a,找到A::swap。在第二种情况下,它看起来 全局命名空间(因为这是定义b的地方), 包括仅声明的全局命名空间中的名称 在课程b中,找到::swap

当然,它以非限定名称查找开始,这将是 在这两种情况下只能找到C :: swap。显然,C ++ Builder不知何故 在这种情况下将::swap标记为隐藏,并且无法考虑它 在ADL。但是,在ADL的情况下,都是全局命名空间 和命名空间A应该平等对待。

完整规则见§3.4.2。这是非常沉重的,但是 像你这样的简单案例,其含义很明显。

答案 1 :(得分:0)

与全球同名的本地范围成员始终隐藏全局范围,因此请将其称为A::a::swap(first.dataA, second.dataA);