Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Folding expressions

Use case

Variadic logging or combining flags.

Explanation

Fold expressions expand parameter packs over an operator. Unary fold has one operator ((pack | ...)). Binary fold has two operators plus an init value ((init << ... << pack)).

Code

#include <cstdint>
#include <iostream>

template <typename... Args> void log(Args... args) {
  // Binary fold: init op ... op pack (2 operators).
  // Expands to: ((std::cout << arg1) << arg2) << arg3.
  (std::cout << ... << args) << "\n";
}

template <typename... Flags> constexpr auto combineFlags(Flags... flags) {
  // Unary fold: pack op ... (1 operator).
  // Expands to: flag1 | flag2 | flag3.
  return (flags | ...);
}

int main() {
  log("Entry: 0x", std::hex, 0x10001000);

  // https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/EXTERNAL_HEADERS/mach-o/loader.h#L145
  // https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/EXTERNAL_HEADERS/mach-o/loader.h#L190
  constexpr uint32_t MH_PIE = 0x20000;
  constexpr uint32_t MH_TWOLEVEL = 0x80;
  constexpr auto flags = combineFlags(MH_PIE, MH_TWOLEVEL);

  std::cout << "Flags: 0x" << std::hex << flags << "\n";

  return 0;
}

View on GitHub.

Output

$ ./src/c++17/build/folding-expressions
Entry: 0x10001000
Flags: 0x20080