> ## 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++ Variadic Parameter

A variadic parameter is a language mechanism that allows a function, template, or macro to accept an arbitrary number of arguments. C++ supports two distinct implementations: compile-time variadic templates (introduced in C++11) and runtime C-style variadic functions.

## Variadic Templates (Parameter Packs)

Variadic templates utilize an ellipsis (`...`) to declare a **parameter pack**. The compiler resolves these at compile time, ensuring strict type safety and generating specific function signatures for each unique invocation.

There are two distinct types of parameter packs:

1. **Template parameter pack:** Represents zero or more template parameters (types, non-types, or templates).
2. **Function parameter pack:** Represents zero or more function parameters.

```cpp theme={"dark"}
// 'Args' is a template parameter pack
// 'args' is a function parameter pack
template <typename... Args>
void evaluate(Args... args) {
    // Implementation
}
```

### Pack Expansion

Parameter packs cannot be indexed or accessed directly; they must be expanded. The compiler expands the pack by replacing it with a comma-separated list of its instantiated elements. Historically, this required recursive template instantiation, peeling off one argument at a time until a base case was reached.

```cpp theme={"dark"}
// Base case for recursive expansion
void expand() {}

// Recursive expansion
template <typename T, typename... Rest>
void expand(T first, Rest... rest) {
    // 'first' is isolated; 'rest...' is expanded in the recursive call
    expand(rest...); 
}
```

### Perfect Forwarding

When a function parameter pack is declared as a forwarding reference (`Args&&...`), it can be combined with `std::forward` to perfectly forward an arbitrary number of arguments. The expansion `std::forward<Args>(args)...` preserves the exact value category (lvalue or rvalue) and `const`/`volatile` qualifiers of every argument in the pack.

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

template <typename... Args>
void forward_wrapper(Args&&... args) {
    // Expands to: target(std::forward<T1>(arg1), std::forward<T2>(arg2), ...)
    target_function(std::forward<Args>(args)...);
}
```

### Fold Expressions (C++17)

C++17 introduced fold expressions, which allow a parameter pack to be reduced over a binary operator without recursive instantiation. The compiler expands the expression directly into a sequence of operations.

A critical language rule applies to empty parameter packs: unary folds over most operators (including `+`, `-`, `*`, `/`) are ill-formed and will trigger a compilation error if the pack is empty. Only `&&`, `||`, and `,` have default values for empty unary folds. To safely handle potentially empty packs with other operators, a **binary fold** must be used to provide an explicit initial value.

```cpp theme={"dark"}
template <typename... Args>
auto compute_sum(Args... args) {
    // Binary left fold: handles empty packs by providing an initial value (0)
    // Expands to: (((0 + arg1) + arg2) + ...)
    return (0 + ... + args); 
}
```

### The `sizeof...` Operator

The `sizeof...` operator queries the number of elements contained within a parameter pack. It evaluates at compile time and returns a `std::size_t` constant expression.

```cpp theme={"dark"}
template <typename... Args>
constexpr std::size_t get_pack_size() {
    return sizeof...(Args);
}
```

## C-Style Variadic Functions

Inherited from C, this legacy mechanism uses the ellipsis (`...`) at the end of a function parameter list. It bypasses C++ compile-time type checking and relies on runtime stack manipulation via macros defined in the `<cstdarg>` header.

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

// Requires at least one named parameter to anchor the stack frame
void legacy_variadic(int count, ...) {
    va_list args;
    va_start(args, count); // Initialize the argument pointer

    for (int i = 0; i < count; ++i) {
        // The type must be explicitly known and passed to va_arg
        int value = va_arg(args, int); 
    }

    va_end(args); // Clean up the argument pointer
}
```

### Mechanics and Limitations

* **Type Erasure:** The compiler does not enforce type safety for arguments passed to the ellipsis. The receiving function must deduce types implicitly (e.g., via a format string) or assume a specific type.
* **Default Argument Promotions:** Arguments passed through C-style variadics undergo implicit promotion. For example, `float` is promoted to `double`, and narrow integer types (`char`, `short`) are promoted to `int` or `unsigned int`.
* **Object Restrictions:** Passing non-trivial class types (e.g., `std::string`, `std::vector`) to an ellipsis is conditionally-supported with implementation-defined semantics (since C++11), or results in undefined behavior (pre-C++11). The C++ standard does not guarantee that constructors or destructors will be invoked correctly through this mechanism.

<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>
