Namespaces

Every name in a C++ program lives in a namespace, even when none is written: the global namespace. std is one namespace, and a project puts its own names into one or two more so that a function called parse in your library does not collide with a parse in another one.

The tool is small: a block that wraps declarations, the :: operator to name something inside it, and two forms of using that save typing. The lesson ends with the ambiguity that a careless using directive produces, because that is the failure namespaces exist to prevent.

Declare and qualify

A namespace is a named block. Everything declared inside it is reachable from outside with the namespace name and the scope operator, so math::square is the full name of the function and square alone is not visible in main.

The program calls the function twice, once in its full form and once via an alias reference. The namespace does not create an object or cost anything at run time: it only changes how the compiler looks names up.

Namespaces can be reopened. A library declares its functions in several headers, each one writing namespace math { ... } again, and the compiler joins the pieces into one namespace.

#include <iostream> namespace math { int square(int value) { return value * value; } } int main() { std::cout << math::square(6) << '\n'; std::cout << math::square(9) << '\n'; }

g++ -std=c++23 -Wall -Wextra declare.cpp -o declare
./declare

36
81

using declarations and directives

using math::square; makes one name visible in the current scope. It is a declaration, it is local to the block or file it appears in, and it cannot silently bring in a second name later.

using namespace math; makes every name of the namespace visible. It is shorter and broader: a name that is added to math later is visible too, which is why a using directive belongs in a .cpp file and not in a header.

The program uses both forms in main. The call cube(3) resolves through the directive, and square(4) through the declaration; both print the same way.

#include <iostream> namespace math { int square(int value) { return value * value; } int cube(int value) { return value * value * value; } } int main() { using math::square; using namespace math; std::cout << square(4) << ' ' << cube(3) << '\n'; }

g++ -std=c++23 -Wall -Wextra using.cpp -o using_demo
./using_demo

16 27

Nested namespaces

A namespace can contain another one, and the short form namespace app::text { ... } declares both levels at once since C++17. The full name of the function below is app::text::width.

Nesting is how a project keeps its parts apart: app::text, app::net, app::storage. A name in app::text is not visible in app::net without qualification, so two parts can both have a function called parse.

The program uses the long qualified name once and a using declaration for the second call, which shows that the nested name is just a longer path to the same function.

#include <iostream> namespace app::text { int width(const char* value) { int count = 0; while (value[count] != '\0') { ++count; } return count; } } int main() { std::cout << app::text::width("hello") << '\n'; using app::text::width; std::cout << width("namespace") << '\n'; }

g++ -std=c++23 -Wall -Wextra nested.cpp -o nested
./nested

5
9

The anonymous namespace

An unnamed namespace gives its contents internal linkage: the names are visible in the rest of the translation unit and nowhere else. Two files can therefore each have a secret() in an unnamed namespace without a duplicate-symbol error at link time.

The program is three files. unit_a.cpp and unit_b.cpp both define an unnamed-namespace secret with a different value, and main.cpp calls the two public functions that use them. The linker sees only a_value and b_value.

This is the modern replacement for static functions at file scope. It is the right place for a helper that no other file should call, and the compiler can still inline it freely.

unit_a.cpp

namespace { int secret() { return 1; } } int a_value() { return secret(); }

unit_b.cpp

namespace { int secret() { return 2; } } int b_value() { return secret(); }

main.cpp

#include <iostream> int a_value(); int b_value(); int main() { std::cout << a_value() << ' ' << b_value() << '\n'; }

g++ -std=c++23 -Wall -Wextra main.cpp unit_a.cpp unit_b.cpp -o internal
./internal

1 2

Two directives, one name

A using directive makes every name of a namespace visible, and two directives can make the same short name visible twice. The compiler then has two candidates that are equally good and refuses to choose.

The program below defines print in two namespaces and calls it unqualified after both directives. GCC lists the two candidates and the line of the call, and the fix is to qualify the call or to use a using declaration for one of the two.

This is the error that namespaces are meant to prevent. It appears at the call site, not at the declaration, which is why a using directive in a header is considered bad practice: it spreads the ambiguity into every file that includes the header.

#include <iostream> namespace one { void print() { std::cout << "one\n"; } } namespace two { void print() { std::cout << "two\n"; } } using namespace one; using namespace two; int main() { print(); }

g++ -std=c++23 -Wall -Wextra ambiguous.cpp -o ambiguous

ambiguous.cpp: In function 'int main()':
ambiguous.cpp:24:10: error: call of overloaded 'print()' is ambiguous
24 | print();
| ~~~~~^~
ambiguous.cpp:24:10: note: there are 2 candidates
ambiguous.cpp:5:6: note: candidate 1: 'void one::print()'
5 | void print()
| ^~~~~
ambiguous.cpp:13:6: note: candidate 2: 'void two::print()'
13 | void print()
| ^~~~~

Exercises

  1. Put the two print functions back in one file and call one::print() and two::print() with full names. Does the program compile without a using directive?
  2. Add a third namespace app::text::wide with a function width and call it from main. Which name do you need to qualify?
  3. Replace using namespace math in using.cpp with using math::cube and compile. Which call stops working, and why?

Questions

A new set of questions in a new order every time. Choose one answer for each, then check.

  1. What is a namespace for?

    Answer

    Grouping names so libraries do not collide

    The qualified name is unique even when two libraries use the same short name.

  2. What is the difference between a using declaration and a using directive?

    Answer

    A declaration brings one name, a directive brings all of them

    using std::cout; names one entity, and using namespace std; makes every name visible.

  3. What does :: do?

    Answer

    It qualifies a name with its namespace or class

    The scope operator tells the compiler where to look for the name.

  4. What is an anonymous namespace used for?

    Answer

    Giving a name internal linkage in one source file

    The names inside it are unique to the translation unit, which replaces the old static declaration.

  5. What does this program print? #include <iostream> namespace one { int square(int v) { return v * v; } } namespace two { int square(int v) { return v * v * v; } } int main() { std::cout << one::square(6) << ' ' << two::square(4); }

    Answer

    36 64

    The qualified calls reach the two functions, and the results are 36 and 64.

  6. What does this program print? #include <iostream> namespace math { int square(int v) { return v * v; } int cube(int v) { return v * v * v; } } int main() { using math::square; std::cout << square(4) << ' ' << math::cube(3); }

    Answer

    16 27

    The declaration brings square into scope, and the cube call stays qualified; the results are 16 and 27.

  7. What does this program print? #include <iostream> namespace outer { namespace inner { int value = 5; int square() { return 9; } } } int main() { std::cout << outer::inner::value << ' ' << outer::inner::square(); }

    Answer

    5 9

    The nested namespace is reached through both names, and the two members print 5 and 9.

  8. What does this program print? #include <iostream> namespace { int local() { return 1; } } int other() { return 2; } int main() { std::cout << local() << ' ' << other(); }

    Answer

    1 2

    The anonymous namespace gives local() internal linkage, and the program prints both values.

  9. Two namespaces are opened with using-directives and both define print(). What does the compiler report for print();? namespace one { void print() {} } namespace two { void print() {} } using namespace one; using namespace two; int main() { print(); }

    Answer

    call of overloaded 'print()' is ambiguous

    Both namespaces are open through directives, and the unqualified call finds two candidates.

  10. Why is using namespace std; avoided in a header?

    Answer

    It leaks into every file that includes the header

    A header is included by many files, and the directive would change name lookup in all of them.

The code on this page was built with g++ 15.2.0 and run on Alpine Linux 3.24.3 (x86_64) in a Docker container. The programs whose section shows a compiler error were compiled until that error and were not run.

Article author: Arthur Isaev