メモ
もう少しマシに出来ないだろうか
http://melpon.org/wandbox/permlink/ECTzA3hv0pkHUlFo
overloaded_function, fusedの関数ポインタ対応を済ませた
overloaded_function, fusedの関数ポインタ対応を済ませました。
これでoverloaded_function, fusedの当面の目標を一通り実装しました。
また別のネタを模索しようと思います。
overloaded_function, fusedがラムダ式に対応した
ちょっと頑張ってmake_overloadやmake_fusedでラムダ式も扱えるようにしました。
https://github.com/fimbul/shiro/blob/master/shiro/functional/overloaded_function.hpp
https://github.com/fimbul/shiro/blob/master/shiro/tuple/fused.hpp
これで以下のようなコードが書けるようになりました。
かくなる上は関数ポインタ対応か。
#include <shiro/functional.hpp> #include <shiro/tuple.hpp> #include <cassert> int main() { constexpr auto f = shiro::make_fused( shiro::make_overload(std::plus<int>{}, std::minus<double>{})); static_assert(f(1, 2) == 3, ""); static_assert(f(3.0, 1.0) == 2.0, ""); static_assert(f(shiro::make_tuple(1, 2)) == 3, ""); static_assert(f(shiro::make_tuple(3.0, 1.0)) == 2.0, ""); auto g = shiro::make_fused( shiro::make_overload([](auto a, auto b) { return a + b; }, [](auto a, auto b, auto c) { return a + b + c; })); assert(g(1, 2) == 3); assert(g(1, 2, 3) == 6); assert(g(shiro::make_tuple(1, 2)) == 3); assert(g(shiro::make_tuple(1, 2, 3)) == 6); }
overloaded_function, fusedを実装した。
実験的なライブラリなので、後々仕様変更などをするかもしれませんが、とりあえずshiro::tupleに対して使えるfusedまで実装しました。現状overloaded_functionが扱えるのは関数オブジェクトだけですが、のちのちboost::overloaded_functionのように関数オブジェクト以外にも対応出来るようにしたいなぁと考えていたりします。あとついでに適当にmake_overloadとmake_fusedも入ってます。
overloaded_function
https://github.com/fimbul/shiro/blob/master/shiro/functional/overloaded_function.hpp
fused
https://github.com/fimbul/shiro/blob/master/shiro/tuple/fused.hpp
これで以下のように書くことが出来るようになりました。
#include <shiro/tuple.hpp> #include <shiro/functional.hpp> int main() { constexpr shiro::fused< shiro::overloaded_function<std::plus<int>, std::minus<double>> > f{}; static_assert(f(1, 2) == 3, ""); static_assert(f(3.5, 1.5) == 2.0, ""); static_assert(f(shiro::make_tuple(1, 2)) == 3, ""); static_assert(f(shiro::make_tuple(3.5, 1.5)) == 2.0, ""); }
index_tuple_catを書いた
typename index_tuple_cat<index_tuple<Indices1...>, index_tuple<Indices2...>, ..., index_tuple<IndicesN...>>::typeがindex_tuple<Indices1..., Indices2..., ..., IndicesN...>となるようなメタ関数を書きました。
https://github.com/fimbul/shiro/blob/master/shiro/utility/index_tuple_cat.hpp
tupleの実装記事の紹介
以下のページで2012年の時点でインデックスを割り振って多重継承するというアプローチが紹介されていたようです。ここまでtupleの実装について丁寧に解説してくれている記事もなかなか無いと思います。もっと早く知りたかった。
http://mitchnull.blogspot.jp/2012/06/c11-tuple-implementation-details-part-1.html
The non-recursive approach
The basic idea behind the non-recursive tuple implementation is that tuple elements are stored in TupleLeaf base classes, but whereas the recursive implementation uses a deep class hierarchy, we'll use multiple-inheritance. In pseudo-code:
template<typename T0, typename T1, ..., typename Tn> class PseudoTuple : TupleLeaf<0, T0>, TupleLeaf<1, T1>, ..., TupleLeaf<n, Tn> { ... };
Each leaf has an index, so that each base-class becomes unique even if the types they contain are identical, so we can access the nth element with a simple static_cast:
static_cast<TupleLeaf<0, T0>*>(this); // ... static_cast<TupleLeaf<n, Tn>*>(this);
しかし戻り値型を得る為に線形再帰のtuple_elementを使っているので要素アクセスが早いというわけではないみたいです。この点は型をtemplate argument deductionで得る方法の方が優れていますね。
What's Wrong with the For Loop
ユーザコードでループを使う代わりに、ループの役割を分担した高階関数を状況に応じて使い分ける方が良いスタイルだろうという話。
What's Wrong with the For Loop
http://notes-on-haskell.blogspot.jp/2007/02/whats-wrong-with-for-loop.html
「for ループはなぜダメなのか」という記事を読んだが、「データ列に対する繰り返し処理というのは fold と map と filter という三種類に分類できるが、 for ループによる記述はそれらを区別しないからだ」という趣旨だった。
— ngr (@ngr_t) July 20, 2014