Exercises — Inline namespaces, anonymous namespaces
5.2.31 · D4· Coding › C++ Programming › Inline namespaces, anonymous namespaces
Do words jo hum baar baar use karenge, ek baar define kar lete hain taaki koi symbol unexplained na rahe:
Level 1 — Recognition
Exercise 1.1
Anonymous namespace ke andar ke names ki linkage kya hoti hai?
Recall Solution
Internal linkage. Ek unnamed namespace mein declare kiya gaya har naam sirf us TU mein visible hota hai jisne use declare kiya. Compiler aise behave karta hai jaise usne har TU ke liye ek unique hidden naam banaya ho plus ek implicit using directive, isliye do alag .cpp files kabhi ek doosre ki copies nahi dekh saktin.
Exercise 1.2
Neeche diye code mein, kaun sa ek word process ko lib::process() ke roop mein reachable banata hai?
namespace lib {
inline namespace v2 { void process(); }
}Recall Solution
Keyword ==inline==. Kyunki v2 ek inline namespace hai, iske members enclosing namespace lib mein leak ho jaate hain, isliye lib::process() resolve hokar lib::v2::process() ban jaata hai.
Exercise 1.3
True ya false: anonymous namespace ek header file ke andar kuch declare karne ke liye acha jagah hai.
Recall Solution
False. Ek header kaafi TUs mein #include hoti hai; har inclusion ek alag internal-linkage copy produce karta hai. Concrete nuksan ke liye Exercise 2.2 dekho.
Level 2 — Application
Exercise 2.1
Do files mein se har ek ek file-local helper define karti hai. Kya ye link hoga?
// a.cpp
namespace { int compute() { return 1; } }
// b.cpp
namespace { int compute() { return 2; } }Recall Solution
Haan, ye cleanly link hoga. Har compute ek alag invented unnamed namespace mein baitha hai (ek per TU), isliye linker do distinct symbols dekhta hai — koi clash nahi, One Definition Rule ka koi violation nahi. Agar dono global int compute() external linkage ke saath likhe hote, to linker "multiple definition of compute" report karta.
Exercise 2.2
Tumne namespace { int counter = 0; } util.h mein rakha aur use teen .cpp files mein include kiya, ek shared counter ki umeed mein. Asal mein kitne independent counter objects exist karte hain, aur kyun?
Recall Solution
Teen independent objects — ek per including TU. Unnamed namespace internal linkage force karta hai, aur internal linkage ka matlab hai har TU ko apni private copy milti hai. Ek file mein counter increment karna doosron ko affect nahi karta, aur binary teeno alag variables carry karta hai. Fix: shared counter ko external linkage ke saath rakho — header mein extern int counter; declare karo aur exactly ek .cpp mein define karo.
Exercise 2.3
Neeche diye versioned library mein, har call kahan resolve hogi?
namespace mathx {
namespace v1 { double area(double r){ return 3.14 * r * r; } }
inline namespace v2 { double area(double r){ return 3.14159 * r * r; } }
}
double a = mathx::area(2.0);
double b = mathx::v1::area(2.0);Recall Solution
mathx::area(2.0)→ inlinev2version, kyunkiv2mathxmein leak ho jaata hai. Value: .mathx::v1::area(2.0)→ explicit legacyv1. Value: . Default callers free meinv2par float karte hain; jov1pin karke bethe hain wo untouched rehte hain.

Level 3 — Analysis
Exercise 3.1
Explain karo, us cheez ke terms mein jo compiler conceptually insert karta hai, kyun ek unnamed namespace kabhi files ke across collide nahi kar sakta, jabki ek global naam kar sakta hai.
Recall Solution
Har TU ke liye compiler aise act karta hai jaise usne likha:
namespace __unique_per_TU { /* your names */ }
using namespace __unique_per_TU; // implicitInvented naam __unique_per_TU har .cpp mein alag hota hai. Isliye file A mein secret actually __uniqueA::secret hai aur file B mein __uniqueB::secret — alag fully-qualified names ⇒ alag linker symbols ⇒ koi collision nahi. Ek global naam ki ek shared fully-qualified spelling hoti hai aur external linkage hota hai, isliye do definitions ek hi symbol pe map hoti hain aur linker duplicate reject kar deta hai.
Exercise 3.2
Kya neeche unqualified draw(w) compile hoga? Argument-Dependent Lookup (ADL) use karke justify karo.
namespace ns {
inline namespace impl { struct Widget {}; void draw(Widget){} }
}
ns::Widget w;
draw(w); // no ns:: prefixRecall Solution
Haan. ADL kehta hai: ek unqualified function call resolve karne ke liye, argument types se associated namespaces bhi search karo. Widget ka associated namespace ns::impl hai. Kyunki impl inline hai, iske contents ns ke members maane jaate hain, isliye associated set effectively ns ko include karta hai, aur draw (jo impl/ns mein rehta hai) mil jaata hai. Agar impl ek plain (non-inline) namespace hota, to draw ADL ke through phir bhi milta kyunki wo Widget ke saath usi associated namespace mein hai — inline keyword ka asli fayda tab dikhta hai jab tum ns::draw(w) qualified call karo, jo sirf isliye kaam karta hai kyunki inline draw ko ns mein leak karta hai.
Exercise 3.3
Kyun inline keyword ko v2 se v3 par move karna source-level calls aur linker symbols dono ko sahi se re-route karta hai, bina caller code ko touch kiye?
Recall Solution
Do layers ek saath change hoti hain:
- Source resolution: unqualified naam
mathx::areaab jis bhi namespace meininlinehai wahan se leak hota hai.inlinekov3par move karo aur harmathx::areacall recompile hokarv3::areaban jaati hai — ek keyword diff, koi caller edits nahi. - Linker symbols (ABI): inline namespace naam mangled symbol mein bake ho jaata hai, jaise
_ZN5mathx2v34areaEdvs_ZN5mathx2v24areaEd. Isliye ek purani object file jov2ke against compile hui thi,v2symbol ko reference karti rehti hai; wo silentlyv3call nahi karne lagti. Version end-to-end encoded hai.
Level 4 — Synthesis
Exercise 4.1
Ek library net design karo jo experimental v3 ship kare jabki v2 default rahe, aur stable v1 callable rahe. Namespace skeleton likho aur batao in mein se har ek kahan resolve hoga: net::send(), net::v3::send(), net::v1::send().
Recall Solution
namespace net {
namespace v1 { void send(); } // legacy, opt-in
inline namespace v2 { void send(); } // current DEFAULT
namespace v3 { void send(); } // experimental, opt-in
}net::send()→net::v2::send()(sirfv2inline hai, isliye sirf wahi leak karta hai).net::v3::send()→ experimental version, sirf explicit qualification se reachable.net::v1::send()→ legacy version, explicit. Jabv3default banne ke liye ready ho toinlinekov2sev3par move karo; existingnet::send()calls recompile par migrate ho jaati hain,v1/v2ke pinned callers unaffected rehte hain.
Exercise 4.2
Tumhare paas ek header-based, single-file library hai jahan har symbol host program se clash avoid karne ke liye file-local hona chahiye, including ek helper struct Node. Explain karo kyun tum Node ke liye static use nahi kar sakte, aur sahi construct likho.
Recall Solution
static internal linkage sirf variables aur functions ko deta hai; ek type jaise struct Node ki is sense mein koi linkage nahi hoti jise static kiya ja sake — keyword simply class ko internal linkage dene ke liye allowed nahi hai. Uniform tool unnamed namespace hai, jo har cheez ko internal linkage deta hai, types bhi:
// helper.cpp (NOT a header — anonymous namespaces stay in .cpp)
namespace {
struct Node { int value; };
Node makeNode(int v) { return Node{v}; }
}Level 5 — Mastery
Exercise 5.1
Ek team namespace { int cache; } ek widely-included header mein likhti hai aur do symptoms report karti hai: (a) executable unexpectedly bada hai, aur (b) ek file mein cache pe writes doosri file mein invisible hain. Dono symptoms ko ek single root cause se diagnose karo, phir corrected design do.
Recall Solution
Root cause: internal linkage × N inclusions. Unnamed namespace cache ko internal-linkage banata hai, aur header, maan lo, N = 5 TUs include karte hain. Result: 5 independent cache objects.
- Symptom (a), bloat: 5 alag variables (aur us namespace ke koi bhi functions) emit hote hain, ek per TU.
- Symptom (b), no sharing: har TU apni khud ki copy read/write karta hai, isliye cross-file communication silently fail ho jaati hai. Corrected design — external linkage ke saath ek shared object:
// cache.h
extern int cache; // declaration only
// cache.cpp
int cache = 0; // single definition, external linkageAb exactly ek cache exist karta hai aur saare TUs use share karte hain. Rule of thumb: anonymous namespaces .cpp files mein rehte hain; shared state extern declaration + ek definition ke peeche rehti hai.
Exercise 5.2
Printed output predict karo. Phir explain karo ki kaun si mechanism (inline leak, ADL, ya per-TU uniqueness) har line exercise karti hai.
namespace app {
namespace v1 { int scale(int x){ return x * 2; } }
inline namespace v2 { int scale(int x){ return x * 10; } }
inline namespace v2 { struct Vec { int n; }; int norm(Vec v){ return v.n; } }
}
int main() {
app::Vec v{7};
std::cout << app::scale(3) << "\n"; // line A
std::cout << app::v1::scale(3) << "\n"; // line B
std::cout << norm(v) << "\n"; // line C (no app::)
}Recall Solution
Output:
30
6
7
- Line A → 30.
app::scaleinline leak ke throughv2::scalepar resolve hota hai, isliye . - Line B → 6. Explicit
app::v1::scalelegacy mein opt-in karta hai: . - Line C → 7.
norm(v)unqualified hai.Vecka associated namespaceapp::v2hai, jo inline hai (isliyeappbhi); ADLnormdhundhta hai. Yev.n = 7return karta hai.
Recall Master checklist
Anonymous namespace kaun si linkage deta hai? ::: Internal — per-TU private.
Anonymous namespaces kabhi nahi aane chahiye? ::: Headers mein (har include = ek alag copy).
inline namespace v2 ke saath lib::process() kahan resolve hota hai? ::: lib::v2::process().
Naya default version promote karne ke liye kaun sa keyword move karte hain? ::: inline.
Kya inline namespace naam mangled symbol mein jaata hai? ::: Haan — ye ABI-tagged hota hai.
Kya static kisi struct ko internal linkage de sakta hai? ::: Nahi; iske bajaye unnamed namespace use karo.