7

From the C++11 standard, §7.3.3[namespace.udecl]/1:

A using-declaration introduces a name into the declarative region in which the using-declaration appears.

using-declaration:

using typenameopt nested-name-specifier unqualified-id ;
using :: unqualified-id ;

The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears.

What do they mean by the name being declared in the declarative region where the using-declaration occurs?

Does this mean the same as introducing that name into the declarative region where the using-declaration occurs?

Also is there a difference between declaring a name and declaring the entity that the name denotes?

Example:

namespace N { static int i = 1; } /* Declares an entity denoted by 
    the name i in the declarative region of the namespace N. 
    Introduces the name into the declarative region of the namespace N.
    Declares the name i in the declarative region of the namespace N? */
using N::i; /* Declares the name i in the declarative region of the
    global namespace. Also introduces that name into the declarative
    region of the global namespace? Also declares the entity that the
    name i denotes? */ 
Supremum
  • 542
  • 7
  • 23
  • 2
    Now that I'm answering your third question on this topic, I think I'm finally understanding this! – Barry Jul 29 '15 at 20:39
  • @Barry I'm patiently waiting for Supremum's exploration of the standard to touch Clause 14. Ah, what a barrage of questions and bug reports that will be! :-) – bogdan Jul 29 '15 at 21:53
  • @Supremum I hope you're not taking the comment above the wrong way - it's friendly banter. You're raising interesting issues, some of them not obvious at all. Keep asking! – bogdan Jul 29 '15 at 21:58
  • So far: 10 non-rejected bugs in clang (3 fixed) and 13 non-rejected bugs in gcc (8 confirmed, 0 fixed). So far I have mostly looked in chapter 3 and 7 :P – Supremum Jul 29 '15 at 22:21
  • Thanks for the help Barry. I'm much less confused now. I realised however that the c++ standard can't be 100 % precise in its terms, and I shouldn't take everything too literally. Its good to understand the terms used, but there is a limit in the precision of them. I should probably focus more on making my own mental model of the c++ standard. That is usually how I learn things, explaining it in my own terms. – Supremum Jul 29 '15 at 22:32

2 Answers2

6

From first principles, an entity is, from [basic]

a value, object, reference, function, enumerator, type, class member, bit-field, template, template specialization, namespace, parameter pack, or this. [...] Every name that denotes an entity is introduced by a declaration.

Declarations declare things. To be declared means that it was introduced by a declaration, from [basic.scope.declarative]

Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.

The names declared by a declaration are introduced into the scope in which the declaration occurs, except that the presence of a friend specifier (11.3), certain uses of the elaborated-type-specifier (7.1.6.3), and using-directives (7.3.4) alter this general behavior.

None of those exceptions are relevant here, since we're talking about using-declarations and not using-directives. Let me alter your example somewhat so as to avoid the global namespace:

namespace N {        //  + declarative region #1
                     //  |
    static int i;    //  | introduces a name into this region
                     //  | this declaration introduces an entity
}                    //  +

So to start with, N::i is an entity that is declared in namespace N and introduced into the scope of N. Now, let's add a using-declaration:

namespace B {        //  + declarative region #2
                     //  |
    using N::i;      //  | declaration introduces a name i
                     //  | but this is not an entity
}                    //  +

From [namespace.udecl], we have:

If a using-declaration names a constructor (3.4.3.1), it implicitly declares a set of constructors in the class in which the using-declaration appears (12.9); otherwise the name specified in a using-declaration is a synonym for a set of declarations in another namespace or class.

The using-declaration using N::i does not name a constructor, so rather than having the name i be a new entity, it is instead a synonym for N::i.

So basically, both is are names introduced in and declared in their respective namespaces. In N, i declares an entity with static linkage, but in B, i declares a synonym to that entity - not a new entity.

Barry
  • 286,269
  • 29
  • 621
  • 977
0

What do they mean by the name being declared in the declarative region where the using-declaration occurs?

I'll try and answer this with an example of my understanding of it (Refer to my comments in the depicted code):

// "namespace X {}" introduces a declarative region of the namespace X
namespace X {
  //The name SomeObject is now introduced into the declarative region X
  // It is only visible in that declarative region
  using Y::SomeObject;
}//Declarative region X ENDS here
// SomeObject NOT visible here

Below is an example where the (compiler) error makes it clear where the name is not visible:

#include <iostream>

namespace A
{
  struct X{};
}

namespace B
{
  struct X{};
}

namespace C
{
  using A::X;

  void foo(X){}
}

namespace D
{
  using B::X;

  void foo(X){}
}

void foo(X){} //FAILS TO COMPILE - DELIBERATE!!!

int main() 
{
    return 0;
}
Werner Erasmus
  • 3,988
  • 17
  • 31