Overload resolution: how is it not ambiguous?

Let's assume we have this code, copied from a separate question:

namespace x 
{
    void f()
    {
    }

    class C 
    {
        void f() 
        {
            using x::f;
            f();         // <==
        }
    };
}

      

The name f

on the specified line is uniquely related to x::f

(at least according to gcc and clang). Why is it x::f

preferable x::C::f

in this case? Shouldn't that be ambiguous since both names are visible?

+3


source to share


3 answers


Because the declaration using

brings x::f

to the area f

that is narrower than the area C

. An unqualified search looks at the scope of the local block, finds a match, and stops before looking at the broader scope of the class. There is no argument-dependent search since there are no function arguments, so no further scopes are considered.



+10


source


@MikeSeymour's answer is in place; here are the relevant standard quotes (C ++ 11, emphasis mine):

13.3.1.1.1 / 3:

In unqualified function calls, the name is not specified by the operator ->

or .

and has the more general form of the primary expression. The name is looked up in the context of a function call according to the normal rules for looking up the name in function calls (3.4). The function declarations found by this search are a set of candidate functions. Due to the rules of name lookup, the set of candidate functions consists of (1) completely non-member functions, or (2) all of the member functions of some class T

.
...

3.4.1 / 1:



In all the cases listed in 3.4.1, the search scopes look for the declaration in the order shown in each of the relevant categories; the name search ends as soon as an ad for the name is found. If the declaration is not found, the program is poorly formed.

3.4.1 / 8

The name used in the definition of the member function (9.3) of the class X

following the declarator-id ... function is declared in one of the following ways:

  • before using it in the block in which it is used or in the closing block (6.3), or
  • must be a member of a class X

    or be a member of a base class X

    (10.2) or
  • ...

From 3.4.1 / 8, we can see that the declaration for the name f

(for example, the declaration using x::f;

) in the block in which it was used is specified earlier than f

as a member of the class C

. According to 3.4.1 / 1, the previous one is selected, so all searches are allowed up to the x::f

one entered by the ad using

.

+7


source


I think these quotes from the C ++ Standard would be relevant:

From C ++ standard (7.3.3. Usage declaration)

13 Since a use-declaration is a declaration, restrictions on declarations with the same name in the same declarative region (3.3) also apply to use-declarations.

AND (3.3.7. Class)

4) A name declared inside a member function obscures the declaration of the same name whose scope extends or ends with a member of the function class.

+1


source







All Articles