[2026] C++ Fold Expressions | Folding Parameter Packs in C++17

[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 yield init—handy for sums, products, and logical folds. Same + operator: (0 + ....+ args) starts from 0; (....+ 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

GoalIdiomatic foldNotes
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
Print(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

Print

아래 코드는 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.

Keywords

C++, fold expression, variadic, parameter pack, C++17.

See also

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3