> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Template Parameter Pack

A template parameter pack is a template parameter that accepts zero or more template arguments. It serves as the foundational mechanism for variadic templates in C++, enabling the definition of classes, functions, and variables that can be instantiated with an arbitrary number of arguments.

The syntax relies on the ellipsis operator (`...`) placed immediately before the identifier in the template parameter list.

## Types of Template Parameter Packs

There are three distinct categories of template parameter packs, corresponding to the three types of template parameters:

**1. Type Template Parameter Pack**
Accepts zero or more arbitrary types.

```cpp theme={"dark"}
template <typename... Types>
struct TypePack;
```

**2. Non-Type Template Parameter Pack**
Accepts zero or more constant expressions of a specific type.

```cpp theme={"dark"}
template <int... Values>
struct NonTypePack;
```

**3. Template Template Parameter Pack**
Accepts zero or more class templates.

```cpp theme={"dark"}
template <template <typename> class... Templates>
struct TemplateTemplatePack;
```

## Function Parameter Packs

A template parameter pack is frequently used in a function declaration to create a **function parameter pack**, which accepts zero or more function arguments. The ellipsis is placed between the template parameter pack name and the function parameter pack identifier.

```cpp theme={"dark"}
template <typename... Args>
void functionName(Args... args); // 'Args' is the template pack, 'args' is the function pack
```

## Pack Expansion

A parameter pack cannot be evaluated directly as a single entity; it must be expanded. Pack expansion consists of a **pattern** followed by an ellipsis (`...`). During instantiation, the compiler expands the pattern by replacing the pack with a comma-separated list of its constituent elements.

Pack expansion can occur in several contexts, including function arguments, braced-init-lists, base class specifiers, and member initializer lists.

```cpp theme={"dark"}
template <typename... T>
void targetFunction(T... args) {}

// 1. Base class specifier expansion
template <typename... Bases>
struct Derived : public Bases... { 
    
    // 2. Member initializer list expansion
    Derived(const Bases&... args) : Bases(args)... {} 
    
    void expand(Bases... args) {
        // 3. Function argument expansion
        targetFunction(args...); 
        targetFunction(&args...); 
        
        // 4. Braced-init-list expansion
        // A leading 0 is used to prevent an ill-formed empty array 
        // initialization if the parameter pack 'Bases' is empty.
        int sizes[] = { 0, sizeof(Bases)... }; 
    }
};
```

## Fold Expressions (C++17)

Fold expressions provide a direct mechanism to reduce (fold) a parameter pack over a binary operator without requiring recursive template instantiations. They evaluate the pack using logical, arithmetic, or other binary operators.

There are four types of fold expressions:

* **Unary Right Fold:** `(pack op ...)` expands to `E1 op (... op (En-1 op En))`
* **Unary Left Fold:** `(... op pack)` expands to `((E1 op E2) op ...) op En`
* **Binary Right Fold:** `(pack op ... op init)` expands to `E1 op (... op (En-1 op (En op init)))`
* **Binary Left Fold:** `(init op ... op pack)` expands to `(((init op E1) op E2) op ...) op En`

**Note on Empty Packs:** Unary folds over most operators are ill-formed if the parameter pack is empty. Only `&&` (defaults to `true`), `||` (defaults to `false`), and `,` (defaults to `void()`) permit empty packs in unary folds. For all other operators, a binary fold with an explicit initial value must be used to support zero arguments.

```cpp theme={"dark"}
template <typename... Args>
auto sum(Args... args) {
    // Binary left fold: (((0 + arg0) + arg1) + ...)
    // Safe for zero arguments (returns 0).
    return (0 + ... + args); 
}

template <typename... Args>
bool allTrue(Args... args) {
    // Unary left fold: (((arg0 && arg1) && arg2) && ...)
    // Safe for zero arguments (returns true).
    return (... && args); 
}
```

## The `sizeof...` Operator

To determine the number of elements contained within a parameter pack at compile time, C++ provides the `sizeof...` operator. It yields a `std::size_t` constant expression and can be applied to both template parameter packs and function parameter packs.

```cpp theme={"dark"}
#include <cstddef>

template <typename... Args>
constexpr std::size_t getPackSize(Args... args) {
    constexpr std::size_t typeCount = sizeof...(Args); // Count of types
    constexpr std::size_t argCount = sizeof...(args);  // Count of function arguments
    return typeCount;
}
```

## Placement Rules and Constraints

* **Primary Class Templates:** The template parameter pack must be the final parameter in the template parameter list.

```cpp theme={"dark"}
template <typename T, typename... Rest> // Valid
class MyClass;

template <typename... Rest, typename T> // Error
class MyClass;
```

* **Function Templates:** A template parameter pack does not need to be the final parameter in the template parameter list, provided that all subsequent template parameters can be deduced from the function arguments or have default arguments. However, if a *function* parameter pack is not at the end of the function parameter list, it creates a **non-deduced context** for the parameter pack itself. While the trailing parameters can still be deduced, the compiler cannot implicitly deduce the pack, requiring explicit template arguments.

```cpp theme={"dark"}
// Valid: T is deduced from the first argument, Args from the remaining arguments.
template <typename... Args, typename T>
void deduceFromArgs(T firstArg, Args... args); 

// Non-deduced context: The compiler cannot implicitly deduce the parameter pack 'Args'.
// Calling this requires explicitly specifying 'Args': invalidDeduction<int>(1, 2.0f);
// This explicitly sets Args to <int>, allowing T to be implicitly deduced as float.
template <typename... Args, typename T>
void invalidDeduction(Args... args, T finalArg); 
```

* **Class Template Partial Specializations:** A parameter pack can appear anywhere in the specialization's argument list, provided the compiler can unambiguously deduce it from the primary template's arguments.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
