【问题标题】:Function not found from global namespace if there's an overload with different argument types如果存在具有不同参数类型的重载,则从全局命名空间中找不到函数
【发布时间】:2026-02-06 09:15:02
【问题描述】:

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

【问题讨论】:

  • 也可以用 MinGW 编译。

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


【解决方案1】:

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

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

完整的规则在 §3.4.2 中。这是相当沉重的,但对于 像你这样的简单案例,含义很清楚。

【讨论】:

  • XE 是几个旧版本。如果此问题尚未在以后的版本中修复,则需要在 QC 中归档以便修复。
  • @RemyLebeau 我无权访问任何版本的 CodeBuilder,因此无法进行测试。由编译器的用户社区使用最新版本来验证这一点,如果错误仍然存​​在,请发送错误报告。
【解决方案2】:

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

【讨论】:

  • 然而,他的代码中没有同名的成员。