- 1 名前:デフォルトの名無しさん [2009/01/04(日) 23:54:01 ]
-
■関連サイト■ p-stade.sourceforge.net/
- 2 名前:デフォルトの名無しさん mailto:sage [2009/01/05(月) 00:17:10 ]
- わたしアイちゃん
よろしくね
- 3 名前:デフォルトの名無しさん [2009/01/06(火) 01:08:05 ]
- こんな変態でマイナーナの、努力しないとあっという間にDAT落ちするぞ。
----Ovenの概要 ようするに、| 演算子でパイプ(Unix的なあれ)を作ったC++テンプレートライブラリ。 #include <iostream> #include <boost/foreach.hpp> #include <pstade/oven/sorted.hpp> int main() { using namespace pstade::oven; int a[] = {1, 9, -5, 10, -2, 6, 4}; BOOST_FOREACH(int x, a | sorted) { std::cout << x << ' '; } std::cout << std::endl; } 出力: -5 -2 1 4 6 9 10 a | sortedってのがOvenを使った部分。sortedは名前通り入力をソートした結果を返すというものだ。 このように入力も出力もRange。 Rangeを知らなければここ読め。ようするに配列やSTLコンテナなど。BOOST_FOREACHできるやつと思っても可。 www.kmonos.net/alang/boost/classes/range.html
- 4 名前:デフォルトの名無しさん [2009/01/06(火) 01:24:05 ]
- #include <iostream>
#include <iterator> #include <string> #include <vector> #include <cctype> #include <pstade/oven/transformed.hpp> #include <pstade/oven/copied.hpp> #include <pstade/oven/copied_to.hpp> int main() { using namespace pstade::oven; std::string s = "HogeFooBar"; std::vector<char> v = s | transformed(std::toupper) | copied; //当然パイプにパイプを重ねることが可能 v | copied_to(std::ostreambuf_iterator<char>(std::cout)); std::cout << std::endl; } 出力: HOGEFOOBAR transformedやcopied_toのように、関数呼出の形で引数を与えるものもある。 transformedは各要素に与えられた関数を適用したレンジを返す。Lispでいうmapだな。 もちろん関数オブジェクトも可。Boost.Lambdaもいけるはず。 copiedはここで打ち止めの意、vectorなどのコンテナへ初期化・代入できるようになる。ただし、std::stringへは上手くいかないようだ。 Ovenで | を通した結果の型はテンプレートの塊なので、どんな型か考えない方がいい。この点、C++0xのautoがやや待ち遠しい。 copied_toは指定された出力イテレータにコピーを送る。それは副作用としてなので、さらにパイプを続けられたはず。
- 5 名前:デフォルトの名無しさん [2009/01/06(火) 01:45:57 ]
- >>1のリンク先から辿れるけど、ダウンロードページへのリンクがあるこっちも挙げておいたほうが親切だと思う。
sourceforge.net/projects/p-stade/ 解凍したら、コンパイラのインクルードパスに通すだけで使える。事前ビルド不要。 これくらい書けば1晩は越せるかな。
- 6 名前:デフォルトの名無しさん [2009/01/06(火) 21:53:27 ]
- どう書く?orgからネタをもらう。
ja.doukaku.org/comment/7652/ #include <cmath> #include <iostream> #include <iterator> #include <pstade/oven/counting.hpp> #include <pstade/oven/filtered.hpp> #include <pstade/oven/copied_to.hpp> #include <pstade/oven/taken.hpp> bool t(unsigned n) { return (static_cast<unsigned long long>(std::pow(30., static_cast<double>(n))) % n) == 0; } int main() { using namespace pstade::oven; unsigned n; std::cin >> n; counting(1u, max_count) | filtered(t) | taken(n) | copied_to(std::ostream_iterator<unsigned>(std::cout, "\n")); } こういうのでは、出力に無理してcopied_to使わずにBOOST_FOREACHやBoost.RangeExのfor_eachを素直に使う方がいいと思う。
- 7 名前:デフォルトの名無しさん [2009/01/06(火) 23:53:54 ]
- そういえば、countingはまだ紹介していない種類だった。
counting(m, n)はmからnまで1ずつ増加するレンジを作るというもの。max_countは最大値までの意。 そういうわけで、これまでのと違って|の左側に置いている。 そうそう、遅延評価風味。foreach類やcopied(_to)などを使わないと動かない。 次のコードでは何も出力されない。 #include <iostream> #include <pstade/oven/transformed.hpp> int f(int x) { std::cout << x << std::endl; return x; } int main() { using namespace pstade::oven; const int a[] = {1, 2, 3}; a | transformed(f); }
- 8 名前:デフォルトの名無しさん [2009/01/07(水) 00:01:30 ]
- 逆に、次のコードでは2回ずつfが呼ばれる。
要素を参照するときに評価が起こると思えばいい。 #include <iostream> #include <algorithm> #include <boost/range.hpp> #include <pstade/oven/transformed.hpp> void dummy(int) {} int f(int x) { std::cout << x << std::endl; return x; } template<typename Range> void g(Range const& r) { std::for_each(boost::begin(r), boost::end(r), dummy); std::for_each(boost::begin(r), boost::end(r), dummy); } int main() { using namespace pstade::oven; const int a[] = {1, 2, 3}; g(a | transformed(f)); }
- 9 名前:デフォルトの名無しさん [2009/01/07(水) 21:29:06 ]
- そういえば、>>4でtransformed(std::toupper)を使ったけど、
そのものずばりupper_charsがあった。 いい加減疲れてきたのでサンプル本家リファレンスのコピペ p-stade.sourceforge.net/oven/doc/html/oven/string_adaptors.html#oven.string_adaptors.upper_chars BOOST_CHECK( equals( std::string("AbCdEFG")|upper_chars, std::string("ABCDEFG") ) ); もちろんlower_charsもある。
- 10 名前:デフォルトの名無しさん [2009/01/08(木) 00:05:59 ]
- zipped はどうつかうの?
- 11 名前:デフォルトの名無しさん [2009/01/08(木) 00:58:10 ]
- ちょうどいい。そのうち書こうと思っていた。
もっとも単純な(?)使い方は、複数レンジを同時にfor eachすることだと思う。 #include <iostream> #include <boost/foreach.hpp> #include <pstade/oven/zipped.hpp> int main() { using namespace pstade::oven; int const a[] = {1, 2, 3}; long const b[] = {2, 4, 6}; typedef boost::tuple<int, long> my_tupple_t; BOOST_FOREACH(my_tupple_t const& e, boost::make_tuple(a, b) | zipped) { std::cout << boost::get<0>(e) + boost::get<1>(e) << std::endl; } for (std::size_t i = 0; i < sizeof a / sizeof a[0]; ++i) { std::cout << a[i] + b[i] << std::endl; } } 上のBOOST_FOREACHと下のforで同じことをやっている。 普通、同時に複数のレンジのfor eachはできないが、要素をtupleでまとめることでそれを実現している(eのこと)。 レンジを渡す側も、tupleで1つにまとめることで、複数のレンジを1つの | へ渡すことを可能にしている。 for eachだとあまり有難みは無いが、アルゴリズム関数で複数個のレンジまたはイテレータを渡せるようになるのが嬉しい。 例えば、STL <algorithm>のtransformは入力イテレータ1つのと2つのしかないが、 そんな用意がなくともzippedで束ねればいくつでも渡せるという具合。
- 12 名前:デフォルトの名無しさん [2009/01/08(木) 01:40:05 ]
- zippedされたレンジの要素はtupleになるが、tupleを作るところをカスタマイズできるというのがzipped_with。
この例では、cat関数にてtupleではなくstringを作ってもらうようにして、fizzbuzzを作ってみた。 #include <iostream> #include <string> #include <boost/foreach.hpp> #include <boost/lexical_cast.hpp> #include <pstade/oven/zipped_with.hpp> #include <pstade/oven/counting.hpp> #include <pstade/oven/cycled.hpp> #include <pstade/oven/taken.hpp> std::string cat(unsigned i, std::string const& f, std::string const& b) { if (f.empty() && b.empty()) return boost::lexical_cast<std::string>(i); else return f + b; } int main() { using namespace pstade::oven; std::string const fizz[] = {"", "", "fizz"}; std::string const buzz[] = {"", "", "", "", "buzz"}; BOOST_FOREACH(std::string const& s, boost::make_tuple( counting(1u, max_count), fizz | cycled, //"", "", "fizz", "", "", "fizz", ...のように無限に繰り返すレンジが作られる。 buzz | cycled) | zipped_with(cat) | taken(20)) { std::cout << s << std::endl; } } このfizzbuzzは作者mb2さんのブログ記事を参考にして作った(なぜか全体のコードが見れなかったけど)。 d.hatena.ne.jp/mb2sync/20070514#p1
- 13 名前:デフォルトの名無しさん [2009/01/08(木) 11:07:32 ]
- >>11
配列をvectorにすると、コンパイルは通るけど、実行時にエラーになる。
- 14 名前:11 mailto:sage [2009/01/08(木) 20:12:01 ]
- >>13
試してみた。VC++ 2008 SP1で確かに落ちるね。ちなみに、g++ 4.3.1では平気だった。 vectorだとmake_tupleでaとbのコピーを作ることになるのだけど、 この一時オブジェクトの寿命がBOOST_FOREACHが終わるまで持たなかったのだと思う。 とりあえず、make_tupleの代わりに参照型で受け取るtieを使えば動いた。
- 15 名前:デフォルトの名無しさん [2009/01/09(金) 20:09:33 ]
- なぜかすっかり忘れていたけど、Ovenの元ネタはこれ。
Range Library Proposal www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1871.html Ovenのマニュアルにも冒頭に「Oven is an advanced implementation of Range Library Proposal」と書いている。 p-stade.sourceforge.net/oven/doc/html/
- 16 名前:デフォルトの名無しさん [2009/01/09(金) 23:38:57 ]
- 作者不在で、ovenやeggの更新が止まってるのが残念
- 17 名前:デフォルトの名無しさん mailto:sage [2009/01/10(土) 03:09:10 ]
- ちょwなんというマイナーライブラリスレ
- 18 名前:1 [2009/01/10(土) 10:28:38 ]
- 誰か語って
- 19 名前:デフォルトの名無しさん mailto:sage [2009/01/10(土) 12:33:52 ]
- Ovenは慣れれば便利だよな
変態だけど Egg?シラネ
- 20 名前:デフォルトの名無しさん [2009/01/10(土) 15:16:38 ]
- >>17
>>3-9の間、誰にも邪魔されなかったほどに過疎っている。 >>18 自分からもネタふりしてくれ。
- 21 名前:デフォルトの名無しさん [2009/01/11(日) 21:04:17 ]
- <pstade/oven/algorithm.hpp>と<pstade/oven/numeric.hpp>には、
それぞれ<algorithm>と<numeric>のRange版が収録されている。 (もちろん名前空間pstade::oven) 例えば、>>4のv | copied_to(std::ostreambuf_iterator<char>(std::cout));は、 copy(v, td::ostreambuf_iterator<char>(std::cout));と書き換えることが可能。 もちろん、Boost.RangeExでもいいわけだけど。むしろRangeExのほうがコンパイル速いし。
- 22 名前:デフォルトの名無しさん [2009/01/11(日) 22:03:35 ]
- 日本語版のドキュメントが欲しくね?
あと、もう少し詳しく書いて欲しくね?(俺だけか・・・) 慣れればどれも同じ様な使い方だからなんとか使えるけど。 あと、pstade::oven::regular ってどういう動作するの?
- 23 名前:デフォルトの名無しさん mailto:sage [2009/01/12(月) 01:08:55 ]
- >>22
確かにHamigakiは日本語文書があるのがやや有難いとは思う。 ドキュメントを読んでわからないときは、libs\oven\example\を参考にすることが多い。 どういう動作かって?実装のことならソース嫁で頼む。
- 24 名前:デフォルトの名無しさん [2009/01/13(火) 01:31:33 ]
- #include <cmath>
#include <iostream> #include <iterator> #include <pstade/oven/counting.hpp> #include <pstade/oven/filtered.hpp> #include <pstade/oven/copied_to.hpp> #include <pstade/oven/taken.hpp> #include <pstade/oven/regular.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> unsigned long powul(unsigned long x, unsigned long y) { return static_cast<unsigned long long>(std::pow(static_cast<double>(x), static_cast<double>(y))); } int main() { namespace bll = boost::lambda; using namespace pstade::oven; unsigned n; std::cin >> n; counting(1u, max_count) | filtered(regular((bll::bind(powul, 30, bll::_1) % bll::_1) == 0)) | taken(n) | copied_to(std::ostream_iterator<unsigned>(std::cout, "\n")); }
- 25 名前:デフォルトの名無しさん [2009/01/13(火) 01:39:48 ]
- 書きかけで送ってしまった。
>>24は>>6をBoost.Lambda+regularに置き換えたもの。 このコードで、regularを外すとコンパイルエラーになる。 なぜかというと、公式のリファンレスに書いてある通り、 Boost.LambdaのファンクタがAssignableでないため。 それをどうにかするのがregularということだそうだ。 なお、>>24のコードはunsigned longを使っているため、 unsigned longが32ビット以下の環境では正しい結果を返さないことに注意。
- 26 名前:デフォルトの名無しさん [2009/01/14(水) 16:27:05 ]
- たまには実用的(?)そうなものを。
stream_linesはstreamから1行読んで1要素とするレンジを作るもの。 #include <iostream> #include <string> #include <deque> #include <iterator> #include <algorithm> #include <pstade/oven/stream_lines.hpp> #include <pstade/oven/copied.hpp> int main() { using namespace pstade::oven; std::deque<std::string> l = stream_lines(std::cin) | copied; std::copy(l.begin(), l.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } 姉妹版として、std::istream_iteratorとstd::istreambuf_iteratorに対応する stream_readとstreambuf_readがある。 また、ファイル相手ならfile_rangeも存在する。こっちはしかもランダムアクセス可とのこと。
- 27 名前:デフォルトの名無しさん [2009/01/17(土) 02:45:13 ]
- narrow_charsとwide_charsはnarrowとwidenで変換しているので、
マルチバイト文字の変換には無力。 わざとうまくいかない例を載せる。これでうまくいく環境があったらびっくりだ。 #include <iostream> #include <locale> #include <iterator> #include <pstade/oven/narrow_chars.hpp> #include <pstade/oven/algorithm.hpp> #include <pstade/oven/as_literal.hpp> int main() { using namespace pstade::oven; copy( L"こんにちわ、世界" | as_literal | narrow_chars, std::ostreambuf_iterator<char>(std::cout)); std::cout << std::endl; }
- 28 名前:デフォルトの名無しさん [2009/01/19(月) 21:15:44 ]
- >>8のコードで、NUL出力のような出力イテレータがないかなと思っていたが、eaterがそれだった。
ついでにcopyもレンジ版にした。 #include <iostream> #include <algorithm> #include <boost/range.hpp> #include <pstade/oven/transformed.hpp> #include <pstade/oven/algorithm.hpp> #include <pstade/oven/eater.hpp> int f(int x) { std::cout << x << std::endl; return x; } template<typename Range> void g(Range const& r) { using namespace pstade::oven; copy(r, eater()); copy(r, eater()); } int main() { const int a[] = {1, 2, 3}; g(a | pstade::oven::transformed(f)); }
- 29 名前:デフォルトの名無しさん [2009/01/22(木) 04:30:31 ]
- #include <iostream>
#include <string> #include <boost/lexical_cast.hpp> #include <pstade/oven/zipped_with.hpp> #include <pstade/oven/counting.hpp> #include <pstade/oven/cycled.hpp> #include <pstade/oven/taken.hpp> #include <pstade/oven/any_range.hpp> #include <pstade/oven/algorithm.hpp> std::string cat(unsigned i, std::string const& f, std::string const& b) { if (f.empty() && b.empty()) return boost::lexical_cast<std::string>(i); else return f + b; } int main() { using namespace pstade::oven; std::string const fizz[] = {"", "", "fizz"}; std::string const buzz[] = {"", "", "", "", "buzz"}; any_range<std::string, boost::single_pass_traversal_tag> r = boost::make_tuple( counting(1u, max_count), fizz | cycled, //"", "", "fizz", "", "", "fizz", ...のように無限に繰り返すレンジが作られる。 buzz | cycled) | zipped_with(cat); unsigned n; std::cout << "How many?" << std::endl; std::cin >> n; copy(r | taken(n), std::ostream_iterator<std::string>(std::cout, "\n")); }
- 30 名前:デフォルトの名無しさん [2009/01/22(木) 04:31:29 ]
- 改行制限に引っ掛かったので、1レスで済ますのを諦めた。
any_rangeは型消去(type erasure)でどんなレンジでも受け付けるという代物。 ようするにboost::functionのレンジ版とでも言える。 プログラムは、またもや以前のネタの使い回し。>>12より。
- 31 名前:デフォルトの名無しさん mailto:sage [2009/01/26(月) 02:49:20 ]
- そろそろ即死から逃れられる頃合いか?
- 32 名前:デフォルトの名無しさん [2009/01/29(木) 17:06:39 ]
- 保守age
- 33 名前:デフォルトの名無しさん mailto:sage [2009/02/02(月) 19:30:41 ]
- 保守
- 34 名前:デフォルトの名無しさん [2009/02/05(木) 17:21:50 ]
- 保守ついでにany_rangeから目次順に取り上げることを目標にする。
というわけでまずはany_indexed。 any_rangeのランダムアクセス特化版、らしい。
- 35 名前:デフォルトの名無しさん [2009/02/10(火) 16:19:16 ]
- void print( pstade::oven::any_indexed<int> r)
{ std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, "\n")); } std::vector<int> v(boost::counting_iterator<int>(0),boost::counting_iterator<int>(10)); pstade::oven::any_indexed<int > ai(v); print(ai);
- 36 名前:デフォルトの名無しさん [2009/02/11(水) 14:31:46 ]
- pstade::oven::identitiesってなにするもん?
- 37 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 20:33:18 ]
- single pass range conceptを満たすものからiterator_rangeを作って返すものっぽいな
io.hppのinspect機構はiterator_rangeに対して働くものだから single(ryを満たすコンテナのままでは動作しないわけだ さらに引数を指定することによって元のコンテナがsingle pass rangeでもrandom access rangeのように見せかけたりできると マニュアルやソース、テストを見る限りそう読みとれた
- 38 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 22:09:21 ]
- STLスレからやってきたのか。
あのコードだと、(v|ov::identities)をov::make_range(v)にしても動くな。 どっちを使うかは好みの問題かな。
- 39 名前:デフォルトの名無しさん [2009/02/12(木) 11:54:40 ]
- pstade::oven::parallel_for_each の第一引数はなに?
.net 4 のparallel for と同じ様な動作?
- 40 名前:停止しました。。。 mailto:sage [2009/02/14(土) 18:05:21 ]
- 真・スレッドリスターター。。。( ̄ー ̄)ニヤリッ
- 41 名前:デフォルトの名無しさん mailto:sage [2009/02/26(木) 07:35:15 ]
- >>39
分割数じゃないかなあ?使ったことないけど。
- 42 名前:デフォルトの名無しさん [2009/02/27(金) 14:33:36 ]
- adapted_toとto_baseについて解説よろしく
- 43 名前:42 [2009/02/27(金) 15:01:39 ]
- わかったから、もういいや
- 44 名前:デフォルトの名無しさん [2009/02/27(金) 16:42:29 ]
- pstade::oven::expression はBoost.Typeofを使ってoverheadを無くすでいいのかな?
- 45 名前:デフォルトの名無しさん mailto:sage [2009/02/28(土) 10:58:37 ]
- >>25
>>24 のソースregularなくてもコンパイル通るけど・・・ taken(n) があると「左辺値がconstです」という旨のエラーになる。 「Boost.LambdaのファンクタがAssignableでない」ってどんなの? いろいろ試したけど、regular付けなくてもコンパイル通ってしまう。 WinXP, VC++2008EE, boost 1.37(boostpro)
- 46 名前:デフォルトの名無しさん [2009/03/02(月) 20:43:29 ]
- groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/67a593c8e747b97c#
RangeExがレビュー入りだってさ。 レンジアダプタ( | 演算子のやつ)も入っているよ!
- 47 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 02:33:08 ]
- >>45
Assignableは(publicな)代入演算子を持っているということ。 takenが無ければコンパイルが通るということは、たまたま代入演算子を使わなかったということ。
- 48 名前:デフォルトの名無しさん mailto:sage [2009/07/29(水) 13:03:13 ]
- 保守
- 49 名前:デフォルトの名無しさん mailto:sage [2009/11/01(日) 08:59:48 ]
- sage
- 50 名前:デフォルトの名無しさん mailto:sage [2010/03/05(金) 03:02:12 ]
- 保守
今規制されていないから、ネタの1つでも投下したい……。
- 51 名前:デフォルトの名無しさん [2010/04/27(火) 23:14:58 ]
- age
- 52 名前:デフォルトの名無しさん mailto:sage [2010/04/29(木) 12:26:57 ]
- そろそろboostにrangeExが入るそうで、Ovenとの相互運用性が気になるところ。
|

|