variadic_template


Concept: variadic templates

Variadic templates are a powerful feature in C++ that allow you to write functions, classes, or other templates that can accept an arbitrary number of template arguments. Introduced in C++11, variadic templates are a key component of modern C++ metaprogramming, enabling more flexible and reusable code.

Key Concepts of Variadic Templates

Basic Syntax

The basic syntax for variadic templates involves using an ellipsis (...) to declare a template parameter pack and to unpack it.

template<typename... Args>
void functionName(Args... args) {
    // Function body
}

Example 1: Basic Variadic Function

Here's a simple example of a variadic template function that prints all arguments passed to it:

#include <iostream>

template<typename... Args>
void printAll(Args... args) {
    (std::cout << ... << args) << std::endl;  // Fold expression in C++17
}

int main() {
    printAll(1, 2.5, "Hello", 'A');  // Outputs: 1 2.5 Hello A
    return 0;
}

Explanation:

Example 2: Recursive Variadic Function

Before C++17, variadic templates often used recursion to process each argument individually. Here’s an example of a function that prints each argument on a new line:

#include <iostream>

// Base case: No arguments left
void print() {
    std::cout << "End of arguments" << std::endl;
}

// Recursive case: Process one argument and recurse
template<typename T, typename... Args>
void print(T first, Args... args) {
    std::cout << first << std::endl;  // Print the first argument
    print(args...);  // Recursively call print with the remaining arguments
}

int main() {
    print(1, 2.5, "Hello", 'A');
    return 0;
}

Explanation:

Example 3: Variadic Template Class

Variadic templates can also be used in class templates. Here's an example of a simple tuple-like class that can hold an arbitrary number of elements:

#include <iostream>
#include <tuple>

template<typename... Args>
class SimpleTuple {
public:
    SimpleTuple(Args... args) : data(args...) {}

    void print() const {
        printTuple(data);
    }

private:
    std::tuple<Args...> data;

    template<std::size_t I = 0>
    void printTuple(const std::tuple<Args...>& t) const {
        if constexpr (I < sizeof...(Args)) {
            std::cout << std::get<I>(t) << " ";
            printTuple<I + 1>(t);
        } else {
            std::cout << std::endl;
        }
    }
};

int main() {
    SimpleTuple<int, double, std::string> tuple(1, 2.5, "Hello");
    tuple.print();  // Outputs: 1 2.5 Hello
    return 0;
}

Explanation:

Example 4: Variadic Templates with Inheritance

#include <iostream>

class Base1 {
public:
    void show() const { std::cout << "Base1\n"; }
};

class Base2 {
public:
    void display() const { std::cout << "Base2\n"; }
};

template<typename... Bases>
class Derived : public Bases... {
public:
    void showAll() const {
        (Bases::show(), ...);
    }

    void displayAll() const {
        (Bases::display(), ...);
    }
};

int main() {
    Derived<Base1, Base2> obj;
    obj.showAll();    // Calls Base1::show()
    obj.displayAll(); // Calls Base2::display()
    return 0;
}

Explanation:

Summary

Variadic templates are a powerful tool in modern C++ programming, enabling more flexible and reusable code. They are particularly useful in metaprogramming and in scenarios where you need to handle an unknown number of arguments or types.

Previous Page | Course Schedule | Course Content