Exercises — noexcept specifier
5.2.30 · D4· Coding › C++ Programming › noexcept specifier
Poore page mein, yaad rakho woh ek contract jisse hum sab kuch derive karte hain: koi bhi exception ek noexcept function se escape nahi kar sakti — isko todo aur runtime std::terminate call kar lega.
Level 1 — Recognition
Goal: ek declaration padho aur batao yeh kya promise karta hai. Abhi koi reasoning chains nahi.
Recall Solution L1.1
(i) true — akela noexcept matlab noexcept(true) hota hai.
(ii) true — explicit noexcept(true).
(iii) false — noexcept(false) explicitly kehta hai "may throw".
(iv) false — ordinary function ka default may-throw hota hai, yani noexcept(false).
Picture karo: noexcept function par ek stamp hai. Sirf (i) aur (ii) par "sealed, no leaks" wala stamp hai.
Recall Solution L1.2
(i) Specifier — yeh signature void f() ke baad aata hai; yeh ek promise hai.
(ii) Operator — noexcept(f()) ek expression mein baitha hai aur ek bool produce karta hai.
(iii) Dono. Outer noexcept( ... ) specifier hai (follows void g()); inner noexcept(f()) operator hai jo woh bool compute karta hai jo ise fill karta hai.
Rule of thumb: function head ke baad → specifier; expression ke andar → operator.
Level 2 — Application
Goal: real expressions par noexcept operator evaluate karo.
Recall Solution L2.1
Operator poochta hai: "kya is expression mein har operation known non-throwing hai?" Yaad karo expr unevaluated hai — kuch bhi run nahi hota.
- (i) true —
safeparnoexceptka stamp hai. - (ii) false —
riskykoi promise nahi karta, isliye operator assume karta hai ki yeh throw kar sakta hai. - (iii) true — dono calls
noexcepthain, aurint + intthrow nahi kar sakta. - (iv) false — ek throwing operation (
risky()) poore expression ko poison kar deti hai. Yeh saari sub-operations par ek AND hai.
Recall Solution L2.2
Nahi, kabhi print nahi hoga. liar ne noexcept promise kiya, phir ek exception ko escape hone diya. Jis moment exception liar se bahar nikalne ki koshish karta hai, runtime std::terminate call kar leta hai — main ke try/catch tak control wapas jaane se pehle.
catch ek toote hue promise ke downstream mein hai, isliye is throw ke liye woh unreachable hai. Program abort ho jaata hai.
Exception handling in C++ se compare karo jahan bina noexcept waali function exception ko us catch mein unwind hone deti.
Level 3 — Analysis
Goal: trace karo kyun contract toot raha hai (ya nahi) aur consequence predict karo.
Recall Solution L3.1
Ek hi sawaal matter karta hai: kya koi exception function boundary cross karta hai?
- (i) terminate — throw directly escape ho jaata hai.
- (ii) fine — throw andar hi catch bhi ho jaata hai; kuch escape nahi hota.
noexceptpromise escape ke baare mein hai, sirfthrowki presence ke baare mein nahi. - (iii) terminate —
catch(int)barethrow;se re-throw karta hai, aur woh re-thrown exception ab escape ho jaata hai. - (iv) fine —
if (false)kabhi nahi liya jaata; koi exception kabhi produce nahi hoti, isliye kuch escape nahi hota. (Promise runtime behaviour ke baare mein hai; ekthrowjo kabhi run nahi hota, kabhi isse nahi toodta.)
Recall Solution L3.2
C++11 se, Destructors implicitly noexcept hote hain (yani ~S() noexcept chahe tumne likha na ho). Toh is destructor ne secretly contract sign kar liya — aur phir throw karta hai.
Runtime result: jab use() ke end mein s destroy hoti hai, throw ek implicitly-noexcept function se escape karta hai → std::terminate.
Language ne yeh kyun force kiya: agar ek destructor throw karta jab stack pehle se kisi doosri exception se unwind ho raha hota, toh do exceptions ek saath in-flight hote — undefined chaos. Throwing destructors ko ban karna (implicit noexcept ke zariye) us hole ko band karta hai.
Level 4 — Synthesis
Goal: noexcept ko move semantics aur containers ke saath combine karo performance explain karne ke liye.
Recall Solution L4.1
Neeche ki figure do rows dikhati hai; yahan woh hai jo yeh words mein depict karti hai taaki tum image ke bina follow kar sako.

Top row (Fast, teal): "old buffer" mein left side par char teal boxes 0 1 2 3; move label waala orange arrow right side par "new buffer" mein char teal boxes ki taraf point karta hai. Kyunki Fast ka move constructor noexcept hai, moving kabhi throw nahi kar sakta, isliye vector safely har element ko move karta hai (cheap — bas ownership steal karta hai; dekho Move semantics).
Bottom row (Slow, plum): left mein "old buffer (kept intact)" mein char filled plum boxes; right mein "new buffer (copies)" mein char empty outlined boxes ki taraf plum arrow copy label ke saath point karta hai — outlines signal karte hain ki originals gutted nahi hue, duplicate hue hain. Ek caption padhta hai: agar koi Slow copy throws, originals untouched → strong guarantee held.
Reallocation par std::vector ko apne N existing elements purane buffer se naye mein transfer karne hote hain, aur woh Strong exception guarantee chahta hai: agar kuch bhi throw kare, vector exactly waise hi rhe jaise pehle tha.
Fast: iska move constructornoexcepthai, isliye moving mid-transfer kabhi throw nahi kar sakta. Vector saare elements move karta hai.Slow: iska move throw kar sakta hai, isliye vector iske bajaaye copy karta hai. Copying har original ko untouched chhodti hai.
Critical edge case — "copy" exactly kaise rollback karta hai. Maano vector N elements copy kar raha hai aur element k ki copy throw karti hai:
- Naye buffer mein already likhی gayi
k−1copies ko cleanup karna hoga. Vector un partially-constructed naye elements ko destroy karta hai (unke Destructors run karke — jonoexcepthain, isliye cleanup khud throw nahi kar sakta). - Woh naye buffer ka raw storage free karta hai.
- Old buffer abhi bhi fully intact hai (copy isse read karta hai, kabhi modify nahi karta), isliye vector simply use karna jaari rakhta hai aur exception caller ko re-throw karta hai. Result: vector bilkul waise dikhta hai jaise reallocation attempt se pehle tha — strong guarantee.
Move yeh rollback kyun nahi kar sakta. Agar vector ne iske bajaaye move kiya hota aur element k ka move throw karta, toh pehle k−1 originals already gutted hain (unka content chura liya gaya hai). Unhe wapas move karna phir throw kar sakta hai, aur koi untouched source bacha nahi. Koi safe rollback nahi hai — yahi reason hai ki vector tabhi move karne ki himmat karta hai jab move noexcept ho. Yahi std::move_if_noexcept decide karta hai: move karo agar move noexcept hai, warna copy karo.
Recall Solution L4.2
template<class T>
void mySwap(T& a, T& b)
noexcept( noexcept(T(std::move(a))) && // move-construct can't throw
noexcept(a = std::move(b)) ) // move-assign can't throw
{
T tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}Ise padhna: outer noexcept(...) specifier hai (promise); do inner noexcept(...) operators hain jo bools produce karte hain. && demand karta hai ki move-construction aur move-assignment dono non-throwing hon. Agar koi bhi throw kar sakta, toh poora promise false ho jaata hai — honest, koi landmine nahi. Body exactly wahi do operations use karti hai, isliye promise exactly reality se match karta hai.
Level 5 — Mastery
Goal: edges par design karo aur reason karo — propagation, type identity, overload resolution, aur subtle escapes.
Recall Solution L5.1
- (i)
noexcept(base())truehai (base parnoexceptstamp hai), isliyemidnoexcept(true)hai. - (ii)
noexcept(mid())abtruehai (midnoexcept(true)par resolve hua), isliyetopnoexcept(true)hai. - (iii)
noexcept(top())isliye true hai.
Promise propagate hota hai: kyunki leaf base non-throwing hai, poori chain true inherit karti hai. base ko may-throw mein flip karo aur uske upar har conditional false mein collapse ho jaata hai — property operator ke through upar flow karti hai.
Recall Solution L5.2
Guiding rule: noexcept promise ko narrow karta hai, isliye conversions sirf "safe" direction mein allowed hain — ek stronger promise weak ki jagah kaam kar sakta hai, kabhi ulta nahi.
- (a) Legal.
nothrowzyada promise karta hai (kabhi throw nahi) than a plain function pointer require karta hai (may throw). Jahan may-throw expect ho, wahan no-throw function dena safe hai — tum over-delivering kar rahe ho. Ekvoid(*)() noexceptvoid(*)()mein implicitly convert hota hai. - (b) Illegal — compile error.
p2promise karta hai ki iska targetnoexcepthai, lekinplainaisa koi promise nahi karta.&plainwahan store karna type system ki nazar mein ek silent lie hogi jo woh refuse karta hai.void(*)()sevoid(*)() noexceptmein koi conversion nahi hai. - (c) Overload B select hota hai (
void(*)() noexcept).¬hrowki typevoid(*)() noexcepthai, jo B se exactly match karta hai (koi conversion nahi), jabki A se sirf noexcept→may-throw conversion ke baad match karta hai. Exact match conversion ko beat karta hai, isliye overload resolution B pick karta hai.
Big picture: kyunki noexcept type ka part hai, void() aur void() noexcept distinct types hain. Isliye generic code (jaise std::function, callback tables, ya template dispatch) kisi callable ki noexcept-ness par branch kar sakta hai — information type mein survive karti hai, sirf comment mein nahi.
Recall Solution L5.3
(a) Haan, independent. Yeh alag sawaalon ke jawab dete hain:
- constexpr ka sawaal: "kya yeh compile time par run ho sakta hai?"
noexceptka sawaal: "kya yeh runtime par throw kar sakta hai?"
Tumhare paas dono mein se koi ek, dono, ya koi nahi ho sakta. Yahan square ke paas dono hain.
(b)
constexprsquare(5)ko compilation ke dauran25mein fold karne deta hai (array sizes, template args, etc. mein usable).noexceptcallers konoexcept(square(5)) == truequery karne deta hai aur compiler ko iske liye exception-cleanup machinery skip karne deta hai.
Yeh orthogonal tools hain jo same signature mein baithte hain.
Recall Solution L5.4
Destructor implicitly noexcept hai, isliye agar logAppend throw kare, exception escape hoga → std::terminate. Fix: ise escape mat hone do — ise destructor ke andar hi swallow kar lo:
struct Guard {
~Guard() noexcept { // promise honestly rakho
try { logAppend("closed"); }
catch (...) { /* log failure ignored — cannot crash us */ }
}
};Yeh correct kyun hai: throw ab contained hai (andar hi caught ho gaya), isliye kuch escape nahi hota aur noexcept promise hold karta hai. Yeh canonical pattern hai: destructors aur doosre "must-not-throw" operations jo internally risky kaam karte hain unhe khud sab kuch catch karna chahiye. L3.1(ii) yaad karo: andar-caught throw kabhi contract violate nahi karta.
Recall Self-test checklist
Khud ko L1→L5 rate karo.
Kya main noexcept(false) padh sakta hoon aur jaanta hoon ki iska matlab may-throw hai? ::: L1 done.
Kya main noexcept(safe() + risky()) evaluate kar sakta hoon aur jaanta hoon ki operand unevaluated hai? ::: L2 done.
Kya main decide kar sakta hoon ki kya ek body terminate trigger karti hai yeh poochh kar "kya yeh escape karta hai?" ::: L3 done.
Kya main vector ke move-vs-copy branch ko strong guarantee ke zariye explain kar sakta hoon? ::: L4 done.
Kya main explain kar sakta hoon ki noexcept function pointer plain mein convert kyun hota hai lekin vice versa nahi? ::: L5 done.