namespace math {
int add(int a, int b) { return a + b; }
}
int r = math::add(2, 3);
C++
Topics in this category
Casting & Conversions
Compilation & Linking
Concepts & Constraints
Concurrency
Const Correctness
Constexpr & Compile-Time
Coroutines
Enums & Enum Classes
Exception Handling
I/O Streams
Lambda Expressions
Memory Management
Modern C++
Move Semantics
Namespaces
OOP & Classes
Operator Overloading
Preprocessor & Macros
RAII & Smart Pointers
Ranges & Views
C++
Namespaces
A namespace is a named scope that groups related declarations (functions, classes, variables) to prevent name collisions between different libraries or modules. Qualifying names with the namespace (ns::name) disambiguates them. Namespaces are essential for organizing large codebases and avoiding clashes with third-party or standard-library names.
Real-world example
Two libraries each define a Logger class; putting them in namespaces avoids the collision.
Compilation & Linking
Namespaces
Namespaces
using namespace std; brings all names from std into the current scope so you can omit the std:: prefix. It's discouraged, especially in headers, because it pollutes the global/namespace scope everywhere the header is included, risking name collisions and ambiguities. Prefer explicit std:: or targeted using-declarations in narrow scopes.
using std::cout; // targeted, safer
// avoid: using namespace std; in headers
Real-world example
A using namespace std in a widely-included header causes a surprising ambiguity with a user 'count' function.
Compilation & Linking
Namespaces
Namespaces
A using-declaration (using std::vector;) brings a single name into scope. A using-directive (using namespace std;) brings all names from a namespace into scope. Using-declarations are more precise and safer; using-directives are broad and collision-prone. Prefer using-declarations, scoped as narrowly as possible.
using std::string; // declaration: just string
using namespace std; // directive: everything in std
Real-world example
A function uses a targeted using-declaration for std::swap to enable ADL while keeping scope clean.
Namespaces
Compilation & Linking
Namespaces
An unnamed namespace gives its contents internal linkage—they're visible only within the current translation unit, like static at file scope but working for types too. It's the modern C++ way to make helper functions, constants, or types local to a .cpp file, avoiding linker collisions with same-named symbols elsewhere.
namespace {
int helper() { return 42; } // internal linkage
}
Real-world example
File-local helpers go in an anonymous namespace so they don't clash with helpers in other files.
Compilation & Linking
Namespaces
Namespaces
ADL (Koenig lookup) means that when calling an unqualified function, the compiler also searches the namespaces of the argument types for matching functions. This lets operators and functions like swap or begin be found in the type's own namespace without qualification, which is why 'using std::swap; swap(a,b);' enables customized swaps.
namespace lib { struct T{}; void f(T); }
lib::T t;
f(t); // ADL finds lib::f
Real-world example
ADL lets user-defined operator<< in a type's namespace be found by generic streaming code.
Operator Overloading
Namespaces
Namespaces
Namespaces can be nested to reflect module structure. C++17 added a compact syntax using :: to declare nested namespaces in one line, avoiding multiple nested braces. Names are accessed with the full qualified path (outer::inner::name).
namespace a::b::c { // C++17 nested shorthand
int x;
}
int y = a::b::c::x;
Real-world example
A project uses nested namespaces like company::product::detail to organize its code.
Namespaces
Compilation & Linking
Namespaces
A namespace alias creates a shorter name for a long or nested namespace, improving readability without a broad using-directive. It's commonly used for deeply nested namespaces or to switch implementations by aliasing one namespace to a chosen name.
namespace fs = std::filesystem;
fs::path p = "/tmp";
Real-world example
Aliasing std::filesystem to fs keeps code concise while remaining explicit.
Namespaces
Modern C++
Namespaces
An inline namespace's members are treated as if they were in the enclosing namespace (accessible without the inner qualifier), while still being distinct for linkage/ABI. It's primarily used for library versioning: a library can put its current API in an inline namespace (e.g., v2) so users write ns::name but the symbols are versioned for ABI compatibility.
namespace lib {
inline namespace v2 { void f(); }
}
lib::f(); // resolves to lib::v2::f
Real-world example
A library exposes lib::f while internally versioning symbols via inline namespaces for ABI stability.
Compilation & Linking
Namespaces
Namespaces
The global namespace is the outermost scope, containing names not placed in any namespace. You refer to a global name explicitly with a leading :: (e.g., ::func), which is useful to disambiguate from a same-named name in the current namespace. Minimizing what lives in the global namespace reduces collisions.
::printf("hi"); // global-scope function explicitly
Real-world example
A leading :: disambiguates the global ::size from a member or namespace-scoped size.
Namespaces
Compilation & Linking
Namespaces
Namespaces partition names by module/library/component, preventing collisions, communicating ownership and structure, and allowing a 'detail' sub-namespace for internal helpers not meant for public use. Combined with headers and build structure, they make large projects navigable and reduce coupling between components.
namespace app::net::detail { /* internal helpers */ }
Real-world example
Public APIs live in app::net while implementation helpers are hidden in app::net::detail.
Compilation & Linking
Namespaces
Namespaces