[2026] C++ Fold Expressions | Folding Parameter Packs in C++17
이 글의 핵심
C++17 fold expressions explained: unary/binary folds, left vs right, empty packs, supported operators, and patterns for sum, print, all_of, and containers.
What are fold expressions?
C++17 fold expressions “fold” a variadic template parameter pack with a single operator, without writing recursive templates. After you know template basics, folds make many variadic utilities shorter. 다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Before C++17: recursion
template<typename T>
T sum(T value) {
return value;
}
template<typename T, typename....Args>
T sum(T first, Args....args) {
return first + sum(args...);
}
// C++17: fold expression
template<typename....Args>
auto sum(Args....args) {
return (....+ args); // unary left fold
}
cout << sum(1, 2, 3, 4, 5) << endl; // 15
The four fold forms
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 1. Unary right fold: (args op ...)
template<typename....Args>
auto sum1(Args....args) {
return (args + ...); // ((1 + 2) + 3) + 4
}
// 2. Unary left fold: (....op args)
template<typename....Args>
auto sum2(Args....args) {
return (....+ args); // 1 + (2 + (3 + 4))
}
// 3. Binary right fold: (args op ....op init)
template<typename....Args>
auto sum3(Args....args) {
return (args + ....+ 0); // ((1 + 2) + 3) + 0
}
// 4. Binary left fold: (init op ....op args)
template<typename....Args>
auto sum4(Args....args) {
return (0 + ....+ args); // 0 + (1 + (2 + 3))
}
Unary vs binary folds
- Unary fold: The pack appears on one side of the operator only. For an empty pack, only certain operators are allowed (see below); others are ill-formed.
- Binary fold:
(pack op ....op init)or(init op ....op pack)supplies an initializer, so an empty pack can yieldinit—handy for sums, products, and logical folds. Same+operator:(0 + ....+ args)starts from0;(....+ args)folds only the arguments. Associativity and empty-pack behavior differ.
Left vs right fold
- Left fold
(....op args): grouping associates from the left (exact tree follows the standard’s expansion rules). - Right fold
(args op ...): grouping associates from the right. For associative operations (+,*), order often does not matter for the value; for subtraction, division, or stream insertion, you must pick the fold that matches the intended order (e.g.(cout << ....<< args)for natural print order).
Practical use in variadic functions
Typical patterns: (1) apply one operation to every argument; (2) split “first vs rest.” Folds excel at (1). 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 실행 예제
template<typename....Args>
void invoke_all(Args&&....f) {
(std::forward<Args>(f)(), ...);
}
If zero arguments are possible, prefer a binary fold with an initializer or if constexpr (sizeof...(Args) == 0).
Common patterns: sum, print, all_of
| Goal | Idiomatic fold | Notes |
|---|---|---|
| Sum | (0 + ....+ args) or (....+ args) | Use binary fold if empty is allowed |
| Product | (1 * ....* args) | Same idea |
| All true | (....&& args) | Empty pack ⇒ true (unary && rules) |
| Any true | (false || ....|| args) or (args || ...) | Empty unary || ⇒ false |
(std::cout << ....<< args) | Mind stream types and order | |
push_back | (vec.push_back(args), ...) | Comma fold |
Logical OR can use a binary fold with a false initializer or a unary right fold; for “all arguments are true,” (....&& args) is often the clearest. |
Role in the language
Fold expressions are a pure compile-time syntactic extension in C++17. There is no runtime cost for the fold itself; generated code is usually a flat sequence of operations. With C++20 concepts, you can constrain which types may appear in a fold.
Supported operators
Arithmetic, logical, bitwise, comparison, and comma operators are supported as specified in the standard—see cppreference for the full list.
Examples
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
void print(Args....args) {
(cout << ....<< args) << endl;
}
print("x = ", 42, ", y = ", 3.14);
All true
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
bool all(Args....args) {
return (....&& args);
}
Push into a vector
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename T, typename....Args>
void push_back_all(vector<T>& vec, Args....args) {
(vec.push_back(args), ...);
}
Call functions
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Funcs>
void call_all(Funcs....funcs) {
(funcs(), ...);
}
Range / membership checks
Illustrative patterns—adapt to your types.
Min/max
Using std::min with an initializer list is often clearer than misusing < as a fold:
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
auto minimum(Args....args) {
return std::min({args...});
}
Comma operator
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
void process2(Args....args) {
((cout << args << " "), ...);
}
Common pitfalls
Empty packs
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
auto sum(Args....args) {
return (0 + ....+ args); // OK: binary fold
}
// Empty-pack friendly unary folds: &&, ||, ,
Precedence
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename....Args>
auto func(Args....args) {
return (....+ (args * 2)); // parenthesize
}
Type consistency
다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
template<typename T, typename....Args>
T sum(Args....args) {
return (T(0) + ....+ T(args));
}
Fold vs recursion
Folds replace long recursive templates for many “reduce over pack” patterns; recursion is still useful when you need non-uniform structure.
FAQ
Q1: When should I use folds?
A: Variadic templates, pack processing, and anywhere you would otherwise write recursion.
Q2: Are all operators supported?
A: Binary operators yes; unary operators cannot be folded in the same way.
Q3: Performance?
A: Similar to an equivalent expanded loop; compile time may improve vs deep recursion.
Q4: Empty packs?
A: Only &&, ||, , unary folds allow an empty pack; otherwise use a binary fold or a branch.
Q5: Before C++17?
A: Use recursive templates or helper metafunctions.
Q6: Resources?
A: C++17 — The Complete Guide, cppreference, Effective Modern C++.
Related: Advanced variadic templates, template basics, template argument deduction.
Related posts
Keywords
C++, fold expression, variadic, parameter pack, C++17.