Zero Argument Variadic Functions

What happens if I call a variadic function with no arguments?

When you call a variadic function with no arguments, the parameter pack will be empty, and the size of the pack (sizeof...(Args)) will be zero. Depending on how the variadic function is implemented, this may or may not be a valid use case.

Let's consider a few examples:

Example 1: Variadic function that expects at least one argument:

#include <iostream>

template <typename T, typename... Types>
void PrintValues(T First, Types... Rest) {  
  std::cout << First;
  if constexpr (sizeof...(Rest) > 0) {
    std::cout << ", ";
    PrintValues(Rest...);
  }
}

int main() {
  PrintValues();  // Error: no matching function
}
error: 'PrintValues': no matching overloaded function found

In this case, calling PrintValues() with no arguments will result in a compilation error because the function expects at least one argument (T First).

Example 2: Variadic function that handles zero arguments:

#include <iostream>

template <typename... Types>
void PrintValues(Types... Args) {
  if constexpr (sizeof...(Args) > 0) {
    (std::cout << ... << Args) << '\n';
  } else {
    std::cout << "No arguments passed\n";
  }
}

int main() {
  // Valid: prints "No arguments passed"
  PrintValues();

  // Valid: prints "123"
  PrintValues(1, 2, 3);
}
No arguments passed
123

In this example, the variadic function PrintValues() handles the case when no arguments are passed using an if constexpr statement. If the size of Args is greater than zero, it prints the arguments using a fold expression. Otherwise, it prints a special message indicating that no arguments were passed.

Example 3: Variadic function with a default empty base case:

#include <iostream>

void PrintValues() {
  std::cout << "\nNo arguments passed\n"; }

template <typename T, typename... Types>
void PrintValues(T First, Types... Rest) {
  std::cout << First;
  if constexpr (sizeof...(Rest) > 0) {
    std::cout << ", ";
  }
  PrintValues(Rest...);
}

int main() {
  // Valid: calls the non-template overload
  PrintValues();

  // Valid: calls the variadic template
  PrintValues(1, 2, 3);
}
No arguments passed
1, 2, 3
No arguments passed

In this approach, we provide a non-template overload of PrintValues() that takes no arguments and serves as the base case for the variadic template. When PrintValues() is called with no arguments, it invokes the non-template overload, which prints a special message. When called with arguments, it invokes the variadic template, which recursively prints the arguments.

In summary, calling a variadic function with no arguments is valid if the function is designed to handle that case, either through compile-time conditionals or by providing a non-template base case. If the variadic function expects at least one argument, calling it with no arguments will result in a compilation error.

Variadic Functions

An introduction to variadic functions, which allow us to pass a variable quantity of arguments

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Passing Parameter Packs by Value or Reference
When should I pass the parameters in a parameter pack by value, reference, const reference, or forwarding reference?
Recursion vs Fold Expressions
When should I use fold expressions over recursive variadic function calls?
Capturing Lvalues and Rvalues in Variadic Functions
How can I write a variadic function that can accept both lvalue and rvalue arguments?
Performance Considerations with Variadic Functions
Are there any performance implications to using variadic functions?
Why use parameter packs instead of just va_args?
I can already write variadic functions in C++ using va_args. Why would I use parameter packs instead?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant