Concepts / Accessing Names in Namespaces

Accessing Names in Namespaces

Qualification reaches a name through the namespace that contains it, as in std::cout and My_code::main.

  • Programming

Why Programs Need Separate Places for Names

Imagine a large program written by several teams. One team writes a function called main in their own part of the code, and another team's library also contains a name that looks identical. If every name were placed in one shared pool, the program would have no way to tell these apart. Namespaces solve this problem by giving names a place to live. This article is about the two everyday ways a program reaches a name that lives somewhere other than where the code currently sits.

A helpful way to picture a namespace is as a labeled drawer. Each drawer holds names, and the label on the drawer keeps names with the same spelling from getting mixed up when they belong to different drawers. A name stored in one drawer is not automatically visible from another drawer. To use it, you have to say which drawer it is in, or you have to set things up so that the drawer's contents can be looked at without repeating the label each time.

Where the Real main() Lives

The real main() is not wrapped in a named group the way My_code::main is. It lives in the global namespace, which is the outermost level of the program. It is not inside a named namespace, a class, or a function. Because it sits at the outermost level, it is reached without any namespace prefix. A name that is not inside any named group is effectively a global name, so the absence of a prefix tells you something about where a name is defined.

Global namespaceoutermost levelmainreal main()mainMy_code::mainMy_codenamed namespacecontainscontainscontains
What contains what? The real main() sits beside My_code in the global namespace, while My_code::main sits inside My_code.

Look at the diagram and notice that the name main appears twice. One entry is in the global namespace and the other is inside My_code. These are two different entries that happen to share a spelling. Keeping this picture in mind makes the next step easier to follow, because the question becomes which of the two entries a given prefix selects.

Reaching a Name Through Its Namespace

The most direct way to access a name that belongs to another namespace is to qualify it with the namespace's name. Qualification means writing the namespace name, then the scope operator, then the name you want. The full path tells the program exactly which drawer to open. The source uses two examples: std::cout, where cout is looked up inside the namespace called std, and My_code::main, where main is looked up inside the namespace called My_code. In both cases the prefix removes any doubt about which name is meant, even when a different name with the same spelling exists elsewhere.

stdnamespace name::scope operatorcoutname looked up inside stdthenthen
In std::cout, which part is the namespace, which is the name, and how does the scope operator connect them to find the right entity?
cpp
Notes on the code
  • std::cout names the cout entity inside the std namespace
  • My_code::main names the main entity inside the My_code namespace, not the real main()

Notice that the rule is the same for both lines. The program does not guess which cout or main you meant. The prefix before the scope operator names the drawer, and the name after it names the item inside that drawer.

Tracing a Qualified Lookup Step by Step

Worked example

Looking up My_code::main

A program contains a global main() and a My_code namespace that also contains a main. The code refers to My_code::main. Which entry does the program use?

  1. 1
    Read the prefix

    The prefix is My_code, so the program knows the search must happen inside the My_code namespace.

  2. 2
    Apply the scope operator

    The scope operator separates the namespace name from the name being requested, so the program looks for main inside My_code.

  3. 3
    Ignore the global entry

    The global main() is in a different drawer. Because the prefix chose My_code, that entry is not the one selected.

  4. 4
    Select the match

    The entry found is the main inside My_code, which is the one the diagram showed as a separate entry.

Result

My_code::main selects the main inside My_code unambiguously, even though a global main also exists.

What do you think happens?

Where does the real main() live: inside My_code, or in the global namespace?

  • Inside My_code

  • In the global namespace

Reveal answer
Answer:

In the global namespace

The real main() is not inside a named namespace, class, or function. It sits at the outermost level, which is why it needs no namespace prefix.

Opening a Drawer with a Using-Directive

Qualifying every name works, but it can become tedious when a program uses many names from the same namespace. To gain access to names in the standard-library namespace, the source introduces a using-directive, written as using namespace std;. Its role is to make names from that namespace available to the code without requiring the full qualified path each time. A using-directive is therefore a way of opening a drawer for the code that follows, rather than a way of moving the names out of the drawer.

Before
std::cout << "Hello";

cout is reached only through the full path std::cout

After

using namespace std; cout << "Hello";

after the using-directive, cout is visible as a bare name

std::coutprefix written on every usecoutbare name visible after thedirectiveMy_code::mainprefix names the drawerstdnamespace left unchanged
After a using-directive, how does writing cout differ from writing std::cout, and which names become visible without qualification?

Mistakes Beginners Make with Namespace Prefixes

  • Common mistake

    Assuming a name from one namespace is visible from another without any prefix or directive

    What it looks like

    Writing cout alone in a program that has no using-directive for std

    Why it fails

    A name stored in one drawer is not automatically visible from another drawer.

    Do this instead

    Qualify the name as std::cout, or add a using-directive if many names from std are needed.

  • Common mistake

    Thinking the real main() needs a prefix because it is the important function

    What it looks like

    Writing a prefix in front of the real main() as though it were inside a named group

    Why it fails

    The real main() lives in the global namespace, at the outermost level, so no prefix is used to reach it.

    Do this instead

    Refer to the real main() without any namespace prefix.

  • Common mistake

    Believing a using-directive moves names out of the standard-library namespace

    Why it fails

    The directive only makes names visible to the code that follows; the original namespace is left unchanged.

    Do this instead

    Think of the directive as opening a drawer for the code, not emptying it.

Practice: Choosing the Right Way to Reach a Name

EASY

A program has a global main() and a namespace called My_code that also contains a main. Explain in your own words how the program can tell which main is meant when the code writes My_code::main, and then say which main a bare call to main() refers to.

Hints
  • Look at which drawer the prefix names before deciding which entry is selected.
  • Recall where the real main() lives and whether it needs a prefix.

Key Takeaways in One Pass

  1. 1
    A name in another namespace is reached by qualifying it with the namespace name, the scope operator, and then the name, as in std::cout and My_code::main.
  2. 2
    The real main() lives in the global namespace, not inside a named namespace, class, or function, which is why it is used without a prefix.
  3. 3
    A using-directive gives access to standard-library names without the full qualified form each time, and it leaves the original namespace unchanged.

At a glance

  • A name in another namespace is reached by qualifying it with that namespace's name and the scope operator, as in std::cout and My_code::main.
  • The real main() lives in the global namespace, not inside a named namespace, class, or function, so it is reached without a prefix.
  • A using-directive makes standard-library names available without repeating the qualified form, and it leaves the original namespace unchanged.

Related concepts

More concepts starting with A