Question bank — Variadic templates — parameter packs, fold expressions
5.2.16 · D5· Coding › C++ Programming › Variadic templates — parameter packs, fold expressions
Deeper background ke liye parent dekho: Variadic templates (parent).
0. Pehle symbols ke naam (traps se pehle padho)
Neeche har item mein char chhote naam reuse hote hain. Ye sirf conventional letters hain, keywords nahi — tum inhe rename kar sakte ho. Yahan exactly bataya gaya hai ki har ek kya stand karta hai, ek concrete call ke saath taaki koi symbol mystery na rahe.

1. Do pictures jo tumhare dimag mein rehni chahiye
Poora topic ek distinction mein rehta hai: ek pack ko expand karna (uske elements ko ek row mein bichhaana) vs usse fold karna (row ko ek operator se collapse karna, nested ek side ko). Is bank ka har trap actually inhi do shapes mein se ek ke baare mein question hai.


True or false — justify karo
Ek parameter pack mein zero elements ho sakte hain.
f() legal hai, aur yahi reason hai ki recursive expansion ko ise catch karne ke liye ek base-case overload chahiye.sizeof...(Ts) run time par evaluate hota hai.
constexpr size_t hai jo compile time par known hota hai; tum ise if constexpr, array sizes, aur dusre compile-time contexts mein use kar sakte ho.(xs + ...) aur (... + xs) hamesha same numeric result dete hain.
+ ke liye True kyunki wo associative hai, lekin association order phir bhi alag hota hai (right-nested vs left-nested); non-associative operators jaise - ya / ke liye results alag hote hain.(xs + ...) mein parentheses optional stylistic choices hain.
( pack op ... ), toh inhe hatane se parse error aata hai, warning nahi.Empty pack par * ke saath unary fold 1 deta hai.
&&, ||, aur , ke defined empty-pack identities hain; empty pack par * compile error hai, implicit 1 nahi.typename... Ts aur Ts... args dono packs declare karte hain.
... ka matlab hamesha "ek pack declare karo" hota hai.f(args)... aur f(args...) same hain.
f(args)... expand hota hai f(a0), f(a1), f(a2) mein (f ko har ek par call karo), jabki f(args...) ek single call hai f(a0, a1, a2).Ek variadic function template pack se pehle normal (non-pack) parameters bhi le sakta hai.
void log(const char* tag, Ts... rest). Pack sirf fixed parameters ke baad ki sab cheez absorb karta hai.Fold expressions recursive pack processing ko completely replace karte hain.
if constexpr) phir bhi tool hai.(cout << xs << ' ', ...) left-to-right printing order guarantee karta hai.
Error dhundo
return xs + ...; — kya galat hai, aur compiler kya kehta hai?
return (xs + ...);. Unke bina GCC/Clang roughly error: expected primary-expression before '...' token report karte hain kyunki xs + ... ek recognised fold nahi hai.bool ok = (bs && ...); jab bs empty ho sakta hai — kya ye safe hai?
&& un teen operators mein se ek hai jinke paas empty-pack identity hai (true), toh ek empty pack error ki jagah true return karta hai.auto s = (xs * ...); jahan xs empty ho sakta hai — diagnostic kaisi dikhti hai?
error: fold of empty expansion over operator* (Clang) — * ka koi fold identity nahi hai. Binary fold aur init se fix karo: (1 * ... * xs).void f(Ts... args) { g(args); } — kyun compile nahi hoga?
args ek pack hai, single value nahi; diagnostic hai error: parameter packs not expanded with '...'. Tumhe ise expand karna hoga: g(args...). Bare args sizeof... ke andar ke alawa illegal hai.Pack elements count karne ke liye size_t n = sizeof(Ts); — error?
error: parameter packs not expanded with '...'. Pack par sizeof(Ts) ill-formed hai; count operator hai sizeof...(Ts). ... meaning ko entirely badal deta hai.template<typename... Ts>
void print(Ts... rest) { std::cout << ...; } // ill-formedYe kyun broken hai?
std::cout << ... ke fold ke operand side par koi pack expression nahi hai, toh compiler kuch aisa emit karta hai error: expected expression before '...'. Tumhe chahiye ((std::cout << rest << ' '), ...); (ek comma fold) ya ek recursive head/tail split.template<typename T, typename... Rest>
void print(T first, Rest... rest) { std::cout << first; print(rest...); }
// no void print() {} overloadJab pack empty ho jata hai toh kya hota hai?
print() call ko koi matching overload nahi milta; compiler fail karta hai error: no matching function for call to 'print()' ke saath — recursion ka koi terminator nahi hai.auto avg(Ts... xs) { return (xs + ...) / sizeof...(xs); } — subtle bug?
(xs + ...) compile fail ho jata hai (fold of empty expansion over operator+); agar compile bhi hota, sizeof... = 0 se divide karna undefined hai. sizeof...(xs) unsigned hona bhi signed average ko skew kar sakta hai.Why questions
Variadic templates kyun exist karte hain 1..N args ke liye manually overloading ki jagah?
... ko expansion ke liye pattern ke baad kyun place kiya jata hai lekin declaration ke liye naam se pehle?
... ek pack banata hai, trailing ... apne left wale pattern ko har pack element ke liye ek baar repeat karta hai (f(args)... → f(a0), f(a1), ...).- ke liye fold direction (left vs right) matter kyun karta hai lekin + ke liye nahi?
- non-associative hai, toh 1-(2-3)=2 alag hai (1-2)-3=-4 se; + associative hai toh sare groupings same value dete hain — sirf nesting shape badlti hai.print_each ke liye recursion ki jagah comma fold prefer kyun karein?
sizeof... compile-time constant kyun hai jabki recursive count run-time hoti?
Kaise ek fold Perfect Forwarding ke saath pair karta hai — forwarding actually kya preserve karta hai?
f(std::forward<Ts>(args)...) mein ... std::forward<Ts>(arg) ko har element ke liye ek baar repeat karta hai. Har std::forward<Ts> Ts&& mein wapas cast karta hai, toh ek argument jo rvalue ke roop mein aaya tha wo rvalue (movable) rehta hai aur lvalue, lvalue rehta hai — pack expansion wo value-category-preserving cast har element par uniformly apply karta hai.Kyun std::tuple construction pack expansion se itni naturally nikalta hai?
std::make_tuple(args...) pack ko exactly usi comma-separated argument list mein expand karta hai — pack ki "har slot mein ek type/value" structure tuple ke fields ki same shape hai, toh koi glue code nahi chahiye.if constexpr aksar type ke basis par packs process karte waqt recursion ko kyun replace karta hai?
sizeof... ya type traits par branch karne deta hai, aur untaken branch ko discard karta hai, toh terminate karne ke liye alag base/recursive overloads likhne ki zaroorat nahi.Edge cases
Single-element pack (x + ...) ka unary right fold kya reduce karta hai?
x — ek element ke saath combine karne ke liye kuch nahi, toh fold wo element unchanged return karta hai.Single-element pack (... + x) ka unary left fold kya reduce karta hai?
x. Left aur right folds sirf 2+ elements ke saath distinguishable hain; single element par dono lone value tak collapse hote hain, toh (... + x) aur (x + ...) yahan identical hain.Empty pack par (... , args) (comma fold) kya evaluate karta hai?
void() — comma un teen operators mein se ek hai jinke paas defined empty-pack identity hai, toh ye valid no-op hai.Kya ek template ke same parameter list mein do parameter packs ho sakte hain?
Agar tum ek variadic template ko zero arguments ke saath call karo toh kya hota hai?
sizeof... 0 hai, unary folds ko teen empty-safe operators mein se ek use karna hoga ya binary init par switch karna hoga, aur recursive versions immediately base case hit karte hain.Kya (0 + ... + xs) result change karta hai jab xs non-empty ho?
+ ke liye koi meaningful change nahi: ye sirf left-fold ko 0 se seed karta hai, deta hai ((0+a0)+a1)+...; safety sirf tab matter karti hai jab xs empty ho sakta ho.Binary right fold (xs + ... + init) ke liye, init nesting mein kahan baithta hai?
a0 + (a1 + (... + (an + init))) — init right se last mein combine hota hai, empty pack ke liye bhi ek value guarantee karta hai.Kya (xs op ...) legal hai jab elements ke mixed types hon?
op successive operand types ke beech defined ho (built-ins ya Operator Overloading ke zariye); result type usual promotion/overload-resolution rules follow karta hai.Recall Interactive self-test (hints included — khud check karo)
Har ek ko zyoor se jawab do, phir upar ke sections ki apni memory expand karke hint reveal karo:
- Teen operators ke naam batao jinke unary fold empty pack par legal hain, aur har ek ki identity do. Hint: ye short-circuit boolean pair plus sequencing operator hain →
&&→true,||→false,,→void(). - Ek sentence mein batao kyun fold mein parentheses mandatory hain. Hint: grammar production socho, style nahi →
( pack op ... )hi rule hai, toh inhe hatana = parse error. - Explain karo kyun
(xs - ...)≠(... - xs). Hint: nesting draw karo → right =1-(2-3)=2, left =(1-2)-3=-4;-non-associative hai.
Agar tumhare kisi bhi jawab mein koi reason attached nahi tha sirf bare fact ke, toh wo item pehle revisit karne wala hai.