Implementing Print Functions with C++ Variadic Templates

C++11 introduced variadic templates, a powerful feature that enables functions to accept an arbitrary number of arguments. This article explores two practical implementations: a recursive template function for printing multiple values and a custom printf-like formatter.

Recursive Template-based Printing

The following implementatoin demonstrates how to process multiple arguments using template recursion:

template <typename T>
void Display(T value)
{
    std::cout << value << std::endl;
}

template <typename First, typename... Remaining>
void Display(First first, Remaining... args)
{
    std::cout << first << ", ";
    Display(args...);
}

int main(int argc, char* argv[])
{
    Display(1);
    Display("hello", 1);
    Display(1, "hello");
    Display(1, "hello", 'H');
    
    return 0;
}

This approach works through template specialization. The single-parameter version handles the base case, while the variadic version processes the first argumant and recursively calls itself with the remaining parameters. The Remaining... syntax represents a parameter pack that gets expanded into individual arguments during compilation.

Building a Custom Printf-style Function

After understanding the mechanics of parameter pack expansion, we can create a more sophisticated formatter similar to printf:

template <typename T>
void PrintFormatted(const char* format, T value)
{
    if (format == nullptr) return;
    
    while (*format)
    {
        if (*format == '%' && *++format != '%')
        {
            std::cout << value;
            return;
        }
        std::cout << *format++;
    }
}

template <typename T, typename... Args>
void PrintFormatted(const char* format, T value, Args... args)
{
    if (format == nullptr) return;
    
    while (*format)
    {
        if (*format == '%' && *++format != '%')
        {
            std::cout << value;
            PrintFormatted(format, args...);
            return;
        }
        std::cout << *format++;
    }
}

int main(int argc, char* argv[])
{
    PrintFormatted("hello\n");
    PrintFormatted("Values: % and %\n", 42, "test");
    
    return 0;
}

This implementation scans the format string character by character. When encountering a percent sign followed by a non-percent character, it substitutes the next value from the argument pack. The function recursively processes the remaining arguments while advancing through the format string.

Key points to note include handling double percent signs to output literal percent characters and ensuring proper recursion termination when all format specifiers have been procesed.

Posted on Sun, 26 Jul 2026 17:19:59 +0000 by Fritz