Question

If we have a function in the global namespace and an overload with different argument types in another namespace, it seems that C++Builder compiler doesn't find the function from the global namespace.

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 gives the following errors:

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

Visual C++ 2012 compiles this without errors.

I have understood that the function in global namespace should be found even when there exists a function with the same name and different argument types.

Have I missed something, or is this a bug in C++Builder?

Was it helpful?

Solution

It looks like a compiler bug to me. In both cases, ADL should kick in. In the first case, it looks in namespace A, including names in namespace A that were only declared in class a, and finds A::swap. In the second case, it looks in the global namespace (since that is where b is defined), including names in the global namespace that were only declare in class b, and finds ::swap.

Of course, it starts with unqualified name lookup, which will only find C::swap in both cases. Apparently, C++Builder somehow marks ::swap as hidden in this case, and fails to consider it in ADL. In the case of ADL, however, both the global namespace and namespace A should be treated equally.

The full rules are in §3.4.2. It's pretty heavy going, but for simple cases like yours, the implications are clear.

OTHER TIPS

Members of local scope with same name as global always hide global one so Call it like,A::a::swap(first.dataA, second.dataA);.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top