0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++でzip (未完成)

Last updated at Posted at 2019-03-16

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を使用する限り,やはり,何らかのコピーや一時オブジェクトの生成は避けられないという事なのかもしれない.

参考情報

  1. 作成したコードv1(未完成)

  2. 作成したコードv2(未完成) 2

  3. 本の虫: コンパイル時zip関数の書き方、並びに京都C++勉強会の案内

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?