Search code examples
c++c++11c++17sfinaefold-expression

Fold expression vs compile recursion


In c++17 we have fold expression which can greatly simplify code that could otherwise be implemented using compiler-recursion and SFINAE or overloading. For example, in the following code

#include <iostream>
#include <utility>

template<typename ...Args>
void printer(Args&&... args) {
  (std::cout << ... << args) << '\n';
}

void printer_cpp11() { }

template <typename First, typename ...Args>
void printer_cpp11(First&& first, Args&&... args)
{
  std::cout << first;
  printer_cpp11(std::forward<Args>(args)...);
}

int main()
{
  printer(3, 4, "hello");

  std::cout << std::endl;

  printer_cpp11(3, 4, "hello");

  return 0;
}

the c++17 function printer (taken from cpp reference) does exactly the same job as its c++11 version printer_cpp11.

At compile-time, several overloads of the function printer_cpp11 are generated, whereas a single function printer is needed using fold expression.

Is there an advantage in terms of performance in using fold expressions over the c++11-style? Or can one assume that the compiler inlines all the overloads of printer_cpp11, creating code with equivalent performance?


Solution

  • Both versions would lead to the same codegen due to inlining, so run-time performance is exactly the same: https://gcc.godbolt.org/z/VIHTvZ (code cleaned of streams clutter).

    However, compilation times and memory usage are expected to be way better with fold expressions than with recursive instantiations, and because of that, fold expression are generally preferred. Not to mention they are also provide for cleaner and easier to reason about code.