C++1z 畳み込み式

C++1zでは、「畳み込み式 (Fold expressions)」という機能が入ります。これは可変引数テンプレートのパラメータパックに対して集計操作を行うためのものです。

たとえば、整数のシーケンスを与えてその合計値を求める計算は、以下のように書けます:

#include <iostream>

template <class... Args>
int sum(Args... args)
{
    // 「... @ args」が畳み込み式。@の部分は任意の二項演算子
    return (... + args);
}

int main()
{
    int x = sum(1, 2, 3, 4, 5);
    std::cout << x << std::endl; // 15
}

このような計算はこれまで再帰を使用して実装する必要がありましたが、より簡潔に書けるようになりました。

ここでは、argsパラメータパックに含まれる全要素を、+二項演算子を使って集計しています。...演算子の左辺に置いているので、左から畳み込みが行われます。計算過程としては、以下のようになります:

1 + 2
3 + 3
6 + 4
10 + 5

...演算子の右辺に置くと、右から畳み込まれます:

template <class... Args>
int sum(Args... args)
{
    return (args + ...);
}

計算過程:

4 + 5
3 + 9
2 + 12
1 + 14

accumulate()アルゴリズムと同様に、初期値をくっつけることもできます:

template <class... Args>
int sum(Args... args)
{
    return (0 + ... + args);
}

畳み込み式で使用できる演算子

畳み込み式で使用できるのは、以下の二項演算子です:

+  -  *  /  %  ^  &  |  ~  =  <  >  <<  >>
+=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=
==  !=  <=  >=  &&  ||  ,  .*  ->*

前述した例の+演算子以外ですと、たとえば条件式のシーケンスに対して「全てtrueか」「いずれかがtrueか」「全てfalseか」を調べる関数は、以下のように書けます:

#include <cassert>

// 全てのパラメータがtrueならtrueを返す
template <class... Args>
bool all(Args... args)
{
    return (true && ... && args);
}

// いずれかのパラメータがtrueならtrueを返す
template <class... Args>
bool any(Args... args)
{
    return (... || args);
}

// 全てのパラメータがfalseならtrueを返す
template <class... Args>
bool none(Args... args)
{
    return !any(args...);
}

int main()
{
    bool a = all(true, true, true);
    bool b = any(false, true, false);
    bool c = none(false, false, false);

    assert(a == true);
    assert(b == true);
    assert(c == true);
}

パラメータパックが空の場合のデフォルト値

パラメータパックがからの場合のデフォルト値は、演算子によって変わります:

演算子
* 1
+ int()
& -1
| int()
&& true
|| false
, void()

この表に記載されていない演算子を空のパラメータパックに対して適用すると、コンパイルエラーになります。

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。