Namespaces: Organizing Code and Avoiding Collisions
Namespaces prevent name collisions in large codebases by grouping related declarations under a common name.
Defining Namespaces
namespace graphics {
class Shape {};
void draw(const Shape& s) {}
}
namespace physics {
class Shape {}; // Different from graphics::Shape
void simulate(const Shape& s) {}
}
graphics::Shape s1;
physics::Shape s2;
Nested Namespaces
namespace company {
namespace graphics {
namespace renderer {
class Pipeline {};
}
}
}
// C++17 shorthand:
namespace company::graphics::renderer {
class Pipeline {};
}
Using Declarations and Directives
using Declaration
Introduces specific name:
using std::cout;
using std::endl;
cout << "Hello" << endl; // No std:: prefix needed
using Directive
Imports entire namespace (use sparingly):
using namespace std; // BAD: Pollutes global namespace
// OK in implementation files with limited scope:
void func() {
using namespace std::chrono; // Limited to function scope
auto now = system_clock::now();
}
Best Practice: Avoid using namespace in headers—it forces pollution on all includers.
Argument-Dependent Lookup (ADL)
Also called “Koenig Lookup”: when calling a function, the compiler searches namespaces of argument types:
namespace lib {
struct Widget {};
void process(const Widget& w) {}
}
lib::Widget w;
process(w); // Finds lib::process via ADL (no lib:: needed!)
ADL Examples
std::vector<int> v;
std::sort(v.begin(), v.end()); // ADL finds std::sort
// Also works:
sort(v.begin(), v.end()); // ADL looks in std:: because iterators are in std::
ADL Pitfalls
namespace lib {
template<typename T>
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
}
int main() {
using std::swap; // Bring std::swap into scope
int a = 1, b = 2;
swap(a, b); // Calls std::swap (ADL + using declaration)
lib::CustomType x, y;
swap(x, y); // Calls lib::swap via ADL
}
Anonymous Namespaces
Provide internal linkage (like static in C):
namespace { // Anonymous namespace
int internal_helper() {
return 42;
}
}
// internal_helper is only visible in this translation unit
Use: Replace file-scope static:
// Old style:
static void helper() {}
// Modern C++:
namespace {
void helper() {}
}
Inline Namespaces (C++11)
Members of inline namespace are also members of enclosing namespace:
namespace lib {
inline namespace v2 {
void func() {}
}
namespace v1 {
void func() {}
}
}
lib::func(); // Calls lib::v2::func (inline namespace)
lib::v1::func(); // Explicitly call v1 version
Use Case: Versioning libraries while maintaining backward compatibility:
namespace mylib {
inline namespace v3 {
class Widget {}; // Current version
}
namespace v2 {
class Widget {}; // Old version still available
}
}
mylib::Widget w; // Uses v3
mylib::v2::Widget w2; // Uses v2
Namespace Aliases
Shorten long namespace names:
namespace fs = std::filesystem;
namespace chrono = std::chrono;
fs::path p = "/home/user";
auto now = chrono::system_clock::now();
Using in Class Scope
class Derived : public Base {
public:
using Base::Base; // Inherit constructors
using Base::method; // Bring method into Derived scope
};
The Global Namespace
Prefix :: refers to global namespace:
int value = 10; // Global
namespace lib {
int value = 20;
void func() {
std::cout << value; // 20 (lib::value)
std::cout << ::value; // 10 (global value)
}
}
Best Practices
- Never
using namespacein headers - Prefer
usingdeclarations over directives - Use anonymous namespaces instead of file-scope
static - Namespace names should be lowercase
- Avoid deeply nested namespaces (>3 levels)
- Use namespace aliases for long names
Conceptual Check
What is Argument-Dependent Lookup (ADL)?
Runtime Environment
Interactive Lab
1#include <iostream>
2
3namespace math {
4 struct Point { double x, y; };
5
6 double distance(const Point& p) {
7 return std::sqrt(p.x * p.x + p.y * p.y);
8 }
9}
10
11namespace {
12 void internal_helper() {
13 std::cout << "Internal function\n";
14 }
15}
16
17int main() {
18 math::Point p{3.0, 4.0};
19
20 // ADL: finds math::distance because p is math::Point
21 std::cout << "Distance: " << distance(p) << '\n';
22
23 internal_helper();
24
25 return 0;
26}
System Console
Waiting for signal...