Skip to content

Instantly share code, notes, and snippets.

@y-yu
Last active December 29, 2015 07:39
Show Gist options
  • Save y-yu/7637403 to your computer and use it in GitHub Desktop.
Save y-yu/7637403 to your computer and use it in GitHub Desktop.
zip

zip関数

次のような機能を満す関数zipを作ってほしい。ただし次のような制約がある。

  • C++11
  • STLはOK
  • BoostはNG

大嘘

template<int N, typename... T>
auto zip(const std::array<T, N>&... containers) -> decltype(std::make_tuple(std::begin(containers)...))

C++はよく分からないので間違ってるかも……。 →間違っているようですので、ニュアンスだけ提供します。

正しい型

実装してくださった方々のコードによると、次のようなものが正しいようです。

template<int N, typename... T>
auto zip(const std::array<T, N>&... containers) -> std::array < std::tuple < T ... > , N >

まあ、正直この辺は適当でいいです。

こんな感じで動く

std::array<int, 5>  a = {1, 2, 3, 4, 5};
std::array<char, 5> b = {'a', 'b', 'c', 'd', 'e'};

zip<5>(a, b);
// -> std::array<std::tuple<int, char>, 5> : (1, 'a'); (2, 'b'); ...; (5, 'e')

std::array<int, 4> c = {1, 2, 3, 4};

zip<4>(a, c)
// -> compile time error

std::vector<int> d = {1, 2, 3, 4, 5}
zip<5>(a, d)
// -> complie time error

何がしたいのか

僕の考えでは、std::arrayというのは型パラメータを2つ取り、それは

  • 配列の要素の型(T
  • 長さ(N

という内訳になっていると思います。

ということは、この配列は単なるT型の配列ではなくて、長さがNで要素がT型の配列という情報になっていると思います。 なので、このzip関数は、このNという長さの情報を使って、コンパイル時に長さが異なる配列が挿入されるとコンパイルエラーになるようにして欲しいです。

これは僕がzip関数が使いたいというよりは、Boostを使わずに長さNに依存したT型の配列を使うと、こういう便利なこと(= 長さの違う配列がぶち込まれるとコンパイル時に死ぬ)が出来るという例として考えてみました。 BoostがNGなのは、中で何をやっているのか不明だからです。

長さなどの情報に依存した配列が使えるとこういう便利が〜という目的なので、オーダーとかは正直適当でいいと思います。

制約に関する説明

C++11

まずC++11ということですが、僕の手元の処理系が対応しているのが、たぶんC++11までだろうということで採用しました。 特に深い理由はなくコードのテストが出来そうだからというだけです。 どうやらWeb上で実行させる物体があるようなので、これはぶっちゃけどうでもよかったかもしれないです。

STL

これはまあ書いておかないとダメなのかなーと思ったので書いただけです。

Boost NG

このような話が最近ありました。

やばい。いま作ってる科学技術計算の処理だと、ruby 36秒、perl 12秒、C++ 5秒、python 3.8秒だった。python以外でも書き方を変えれば劇的に高速化はするけれど、テクニックを用いず素直に書いてこれは大きい。科学計算でpythonがよく使われる訳が分かった。

これについて僕のタイムラインの中で、これはFORTRANで実装された物体を呼び出してるから早いのでは? みたいなツイートを多く目にしました。

これと今回の物体がどれほど関係あるのか微妙ですが、例えば「Rubyにはこの機能使えます(Pure Ruby)」と「Rubyにはこの機能が使えます(C拡張)」 では全然違うと思うので、とりあえず何をやってるのか謎なライブラリの使用は制限させてもらいました。

皆様の実装

えりっく君の助け(煽り)により、様々な人が実装してくれました。ありがとうございます。

実装の解説

江添さんがテンプレートメタプログラミングを用いた技法を解説しています。

感想

多くの方に実装していただき、特に@fimbul11さんにはテンプレートメタプログラミングについて様々な解説をしていただきました。ありがとうございます。 このzip関数を実装するにあたり、このような超絶技巧を駆使する言語はC++だけなのではないでしょうか。つくづく舌を巻くばかりです。

@PG_nonenさんによって実装されたコードは唯一ランタイム関数です。 僕はこの10行で実装されたバージョンもとてもよいと思っています。確かに副作用とかランタイムとか色々見劣りするところはあると思いますが、 それでも10行で実装出来ているという事実は評価されるべきことだと思います。 他の言語の事はよく分かりませんが、恐らくコンパイル時に配列の長さをチェックするという芸当が出来るのは、それほど多くはないと思います。 そのようなリッチな要求をたった10行で実装出来る表現力は、評価されるべきなのではないかと思います。

このテンプレートメタプログラミングを駆使した超絶技巧をよしとするか、 あるいは簡潔な実装をよしとするか、人々に問う機会となればいいのではないでしょうか。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment