Global namespace undefined ambiguity vs. nested namespace undefined ambiguity

Consider the following two pieces of code:

Fragment A

#include <iostream>

namespace
{
    bool foo = false;
}

bool foo = true;

int main()
{
    std::cout << foo << std::endl;
}

      

fragment B

#include <iostream>

namespace A
{
    namespace
    {
        bool foo = false;
    }

    bool foo = true;
}

int main()
{
    std::cout << A::foo << std::endl;
}

      

In Snippet A , foo

Usage internally is int main()

ambiguous, while Snippet B is not. Why is this so?


Related: Undefined Region of Undefined Space

+3


source to share


1 answer


The behavior of unnamed namespaces is specified in section 7.3.1.1 [namespace.unnamed] / p1:

An unnamed-namespace definition behaves as if it had been replaced with

inline_opt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

      

where inline

appears if and only when it appears in the unnamed-namespace-definition, all occurrences unique

in the translation block are replaced with the same identifier, and this identifier is different from all other identifiers in the entire program.

In particular, note that declarations within an unnamed namespace are made visible in the surrounding scope using a pointer directive using namespace unique;

.

In Snippet A, foo

is unqualified, so the compiler looks for unqualified names (ยง3.4.1 [basic.lookup.unqual]). Here is paragraph 2 of sub-clause:

2 Declarations from the namespace assigned with the using directive are made visible in the namespace that includes the using directive; see 7.3.4. For the purposes of the unqualified name validation rules described in 3.4.1, declarations from a namespace designated by a using-directive are considered members of that enclosing namespace.



Therefore, an unqualified name lookup finds both declarations foo

and the name is ambiguous.

In snippet B, A::foo

is qualified, so name lookup rules apply. Because A

is a namespace, the applicable subclause is ยง3.4.3.2 [namespace.qual]. In this case, the rule is specified in paragraph 2 of this subsection:

For a namespace X

and a name, the m

set for searching by names S(X,m)

is defined as follows: let S'(X,m)

be the set of all declarations m

in X

and the built-in set of namespaces X

(7.3.1). If S'(X,m)

not empty, S(X,m)

- S'(X,m)

; otherwise, it S(X,m)

is the union S(Ni,m)

for all namespaces Ni

assigned by directives in X

and its built-in namespace.

In other words, qualified name lookup considers namespaces assigned by directives only if the name is not found in the specified namespace and in its built-in namespace. Here, the name foo

is in the namespace A

, so the unnamed namespace assigned with the using directive is not considered and there is no ambiguity.

If you write ::foo

instead foo

in snippet A, then qualified search rules will apply instead, in which case there will be no ambiguity.

+5


source







All Articles