- 1 名前:デフォルトの名無しさん [2009/01/04(日) 23:54:01 ]
-
■関連サイト■ p-stade.sourceforge.net/
- 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もある。
|

|