F
Foothold
Back to archive
FAQ #Systems Easy

Namespaces

croft October 01, 2026

Namespaces exist because names are a shared, finite resource, like phone numbers in a country. Here's the same idea from a few angles.


Imagine a school where there are two students named “Alex.” The teacher can’t say just “Alex” — is it Alex Smith or Alex Chen? Everyone needs a disambiguator: the family name.
That’s it. A namespace is a family name for a set of names.
namespace graphics { void draw(); } // graphics::draw namespace physics { void draw(); } // physics::draw
draw alone is ambiguous — same name, two different functions, just like two Alexes. graphics::draw and physics::draware the family names. Nothing about the functions changed; only how you address them.
The real world mostly solved this too. The OS has std::chrono::milliseconds and boost::chrono::milliseconds. Both people are named Milliseconds.

The :: is the separator, not the address
A full path looks like a URL:
std :: vector < int > ↑ ↑ ↑ area family the name code name
:: is just a separator meaning “look inside.” And critically, it means search only here, not “search this and then search upward.” Compare:
std::vector — exactly this one thing, no ambiguity, ever
using namespace std; — “assume anything unresolved might be in std” — you’re guessing


** How this connects to containers**


This is the part that trips people up, so it’s worth being precise.
A container is a template. A template is a name that produces a family of types. So vector is a type name that lives inside a namespace, which is why it always arrives with its family name attached:

std::vector<int> a; // std::vector<int> + variable name a std::map<std::string, std::vector<int>> b; // namespaces nest
no problem
Three things glued together, and the reason the middle one is namespaced is that containers are the most reimplemented thing in the language. Every library has a vector, a map, a set, a string, a queue. Nobody agreed on one, so everyone namespace-protected theirs and the pre-committee solution was the std:: prefix.
So when you see std::vector<int>, read it as: “the vector from the standard library’s family of containers, holding int.” Drop std:: and you’ve told the compiler nothing about which vector.


The part that surprises people


Namespaces are erased. They exist only during compilation. At runtime a std::vector<int> and a my::vector<int>are just two types, with no trace of their namespace in memory, in the binary, or in a debugger.
Consequence: you can’t “look inside” a namespace at runtime, and namespaces can’t be opened, closed, or changed. They’re purely a compile-time naming convention. This is why using namespace std; is often criticized — it’s a source-level shortcut that changes how the compiler resolves names, never what the program does.

Observations

No observations logged on this node yet.

Submit