3

§3.4.6/1:

In a using-directive or namespace-alias-definition, during the lookup for a namespace-name or for a name in a nested-name-specifier only namespace names are considered.

Basically, what I'm asking is: "why is this paragraph necessary?"

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Mao
  • 1,065
  • 8
  • 12

2 Answers2

2

Defect report 373: Lookup on namespace qualified name in using-directive gives an example of why the wording matters:

namespace X {
  namespace Y {
    struct X {
      void f()
      {
        using namespace X::Y;
        namespace Z = X::Y;
      }
    };
  }
}

Which X is being referred to in using namespace X::Y the struct or the namespace? Without that wording in 3.4.6 it would be ambiguous.

This actually lead to the change in the wording from:

When looking up a namespace-name in a using-directive or namespace-alias-definition, only namespace names are considered.

to what we have today because the original wording did not cover the nested-name-specifier.

The ambiguity is with the nested-name-specifier which if we look at the draft C++11 standard the grammar in section 5.1.1 General is as follows:

nested-name-specifier:
    ::opt type-name ::
    ::opt namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier templateopt simple-template-id ::

and the following paragraphs which I won't copy since they are large do not restrict nested-name-specifier to a namespace.

As far as I can tell section 7.3.1 Namespace definition sufficiently restricts namespace-name to prevent ambiguities.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • I'm having some difficulty understanding the ambiguity. The _using-directive_ and the _namespace-alias-definition_, both refer to a namespace, not a class name. – Mao Sep 26 '14 at 12:33
1

Clang's unit tests for namespace using and alias directives is exactly the answer to your question:

clang-cc -fsyntax-only -verify %s

struct ns1 {}; // This is not a namespace, although a namespace has ns1 as a name
void ns2();
int ns3 = 0;

namespace ns0 {
  namespace ns1 {
    struct test0 {};
  }
  namespace ns2 {
    struct test1 {};
  }
  namespace ns3 {
    struct test2 {};
  }
}

using namespace ns0;

namespace test3 = ns1; // don't get confused
namespace test4 = ns2;
namespace test5 = ns3;

using namespace ns1; // don't get confused
using namespace ns2;
using namespace ns3;

test0 a;
test1 b;
test2 c;

This issue has also been discussed in n3160 defect report

Marco A.
  • 43,032
  • 26
  • 132
  • 246