C++
C++14

C++でzip (未完成)

C++で,複数の列からそれら各要素の同一インデックス同士の組を要素に持つ列を構成するzipを作ってみる.

手元の環境の制約からC++14上の実装を考えます.

もちろん,C++11でも,もっと新しい規格でもよいのですが…

とりあえず,まず始めに作成したコードはこれ1,2です.まだ未完成です.

コピーするのが面倒なので,リンクを貼るだけにします.


目標

まず,引数を可変長にしたいですね.

それと,できるだけコピーや一時的なオブジェクトの生成を減らしたいです.

多くの場合,zipの結果を使用する場面は,演算のフローが明確な場合が多いと思います.

簡単な例を挙げると,

for (auto&& t : zip(xs, ys, zs)) {

const auto& x = std::get<0>(t);
const auto& y = std::get<1>(t);
auto& z = std::get<2>(t);
z = f(x, y);
}

こんな感じかと思います.

作成コードには,参照方法が異なる3つのパターンを作成しました.

名前空間lrefは,左辺値参照で列を受け取ります.

zip内では,std::tieを使用して左辺値参照型を要素に持つstd::tuple型が要素のstd::vectorを作ります.

このzipは右辺値参照を取ることができません.

そのため,

auto a = zip(xs, zip(ys, zs));

こういったネストするような呼び出しのコードは書けません.

次のような書き方はOKです.

auto b = zip(ys, zs);

auto a = zip(xs, b);

今のところネスト呼び出しの必要性はありません.

そのため,引数の個数を可変長にする事を優先しようと思いますが…

どうやってパックしたり展開すればよいのか,すぐに思い付きません…


TODO


  1. 引数を可変長にする.

  2. できるだけコピーや一時オブジェクトの数を減らす.

  3. 右辺値参照を受け取れるようにする.

引数を可変長にするには,std::tupleの各要素に対してoperator*operator++を呼び,かつ返り値のstd::tupleで補足して返す関数があれば良さそう.

でも,どうやって定義するんだ?

また,色々書いてみた2が,この実装はコンパイルは通るが実行時エラーになってしまう…


コンパイル時zip

zipの対象となる列が全てstd::arrayならば,constexpr関数として定義できるそうだ3

つまり,それ以外,例えばstd::vectorを使用する限り,やはり,何らかのコピーや一時オブジェクトの生成は避けられないという事なのかもしれない.


参考情報