Vlad from Moscow
Vlad from Moscow

Reputation: 311038

Extending a namespace in an inline namespace that initially was defined in the enclosing namespace of the inline namespace

I would like to check myself whether I understand correctly the following quote below from the C++ 20 Standard (English is not my native language).

Section 9.7.1 Namespace definition:

2 In a named-namespace-definition, the identifier is the name of the namespace. If the identifier, when looked up (6.4.1), refers to a namespace-name (but not a namespace-alias) that was introduced in the namespace in which the named-namespace-definition appears or that was introduced in a member of the inline namespace set of that namespace, the namespace-definition extends the previously-declared namespace. Otherwise, the identifier is introduced as a namespace-name into the declarative region in which the named-namespacedefinition appears.

That is may a namespace be defined in a namespace and then extended in one of its inline namespace? Or vice versa. May a namespace be defined in an inline namespace and then be extended in its enclosing namespace?

Here is a demonstrative program.

#include <iostream>

inline namespace N1
{
    inline namespace N2
    {
        namespace N3
        {
            void f( int ) { std::cout << "f( int )\n"; }
        }
    }

    namespace N3
    {
        void f( char ) { std::cout << "f( char )\n"; }
    }        
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

The program output is

f( int )
f( char )

However for this program the compiler issues an error saying that reference to 'N3' is ambiguous.

#include <iostream>

inline namespace N1
{
    namespace N3
    {
        void f( int ) { std::cout << "f( int )\n"; }
    }

    inline namespace N2
    {
        namespace N3
        {
            void f( char ) { std::cout << "f( char )\n"; }
        }        
    }
}

int main()
{
    N3::f( 10 );
    N3::f( 'A' );
}

Upvotes: 2

Views: 258

Answers (2)

Brian Bi
Brian Bi

Reputation: 119239

may a namespace be defined in a namespace and then extended in one of its inline namespace?

No. In your second example, when the compiler sees the definition of N3 inside N2, the lookup of N3 finds the N3 that was declared outside N2, but that N3 was not "introduced in the namespace in which the named-namespace-definition appears" (since it's not inside N2), or "introduced in a member of the inline namespace set of that namespace" since the inline namespace set of N2 is the set of transitively inline namespaces inside N2. Thus, this new definition of N3 doesn't extend the previous one.

May a namespace be defined in an inline namespace and then be extended in its enclosing namespace?

Yes. In your first example, N3 when looked up finds N2::N3 which was "introduced in a member of the inline namespace set" since N2 is part of the inline namespace set of N1.

We can understand the rationale for this apparent asymmetry as follows: in the second example, when N3 is initially defined, it's being defined as a member of N1 and not a member of any inline namespace of N1. Later, when N2::N3 is being defined, if it were to extend N1::N3, it would be retroactively making N3 a member of N2, which goes against common sense and is therefore disallowed. In the first example, N3 is initially defined as a member of the inline namespace N2 and there is no issue with extending it with the second definition later. (Though I cannot see an obvious reason why this is useful.)

Upvotes: 2

Max Langhof
Max Langhof

Reputation: 23701

I'll try to rewrite the standard wording in a less dense (but possibly less precise) way:

  1. We are lexically inside namespace X.

  2. We encounter something that looks like namespace Y { ... }.

  3. We look up Y. If Y is not a namespace name, move on1.

  4. Was Y introduced (directly) in X? If so, move to point 6.

  5. Was Y introduced in a namespace that is part of the inline set2 of namespaces of X? If yes, move to 6. If not, move on1.

  6. Y does extend the namespace we found in step 3.

1 "Move on" in the sense of "ignore the cited standard paragraph".
2 The inline namespace set of N is the transitive closure of all inline namespaces in N.

may a namespace be defined in a namespace and then extended in one of its inline namespace?

No. We only consider the directly enclosing namespace (N3 is extended in N1 in your first example, and in N2 in your second one) and its inline namespaces. This is why your second example does not work: N2 (or its inline set of namespaces) does not contain any previous definition of N3.

May a namespace be defined in an inline namespace and then be extended in its enclosing namespace?

Yes.

The examples you show are consistent with the standard wording.

Upvotes: 2

Related Questions