C++17から導入されたフォールディング式(fold expressions)は、可変数のパラメーターパックを操作する際に非常に便利な機能です。この章では、フォールディング式の基本的な概念と、なぜこの機能が必要なのかについて説明します。

基本的な構文

編集

フォールディング式の基本的な構文は以下のようになります。

(expression op ...)    // 左折り畳み(Left fold)
(... op expression)    // 右折り畳み(Right fold)

ここで、opは演算子です。フォールディング式は、(...)の内部で演算子を適用し、パラメーターパックの要素を畳み込むことができます。

フォールディング式の種類

編集

左折り畳みと右折り畳みの2つの種類があります。左折り畳みは、パラメーターパックの最初の要素から始めて順に演算子を適用し、右折り畳みは逆の順序で演算子を適用します。折りたたみ演算子も利用可能です。

具体例

編集

以下に、フォールディング式を使った具体的な例を示します。

関数テンプレートに適用した例

編集
左折り畳みを使ったパラメーターパックの要素の合計
#include <iostream>

template <typename... Args>
auto sum(Args... args) -> auto {
    return (args + ...);
}

auto main() -> int {
    int const total = sum(1, 2, 3, 4, 5);
    std::cout << "Total: " << total << std::endl; // 出力: Total: 15
    return 0;
}

ラムダ式に適用した例

編集

フォールディング式はラムダ式とも組み合わせて使用することができます。

左折り畳みを使ったパラメーターパックの要素の合計
#include <iostream>

auto main() -> int {
    auto sum = [](const auto &...nums) { return (0 + ... + nums); };
    int const total = sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    std::cout << "Total: " << total << std::endl; // 出力: Total: 15

    return 0;
}
この例では、ラムダ式を使って引数の合計を計算しています。フォールディング式を使って、可変数の引数を合計している点に注目してください。
左折り畳みを使ったパラメーターパックの要素の最大公約数を求める
#include <iostream>

// 最大公約数を計算する関数
int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

// 可変引数の最大公約数を計算するジェネリックラムダ
auto gcd_multi = [](int result, auto&&... args) {
    ((result = gcd(result, args)), ...); // 可変引数を順番に処理
    return result;
};

auto main() -> int {
    std::cout << gcd_multi(32, 72, 12, 18) << std::endl;  // 6

    return 0;
}
左折り畳みを見つけにくいと思いますが、「可変引数を順番に処理」の , が演算子(カンマ演算子)です。