5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

Oven/Egg総合スレ part1

1 :デフォルトの名無しさん:2009/01/04(日) 23:54:01

■関連サイト■
http://p-stade.sourceforge.net/

2 :デフォルトの名無しさん: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できるやつと思っても可。
http://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のリンク先から辿れるけど、ダウンロードページへのリンクがあるこっちも挙げておいたほうが親切だと思う。
http://sourceforge.net/projects/p-stade/
解凍したら、コンパイラのインクルードパスに通すだけで使える。事前ビルド不要。

これくらい書けば1晩は越せるかな。

6 :デフォルトの名無しさん:2009/01/06(火) 21:53:27
どう書く?orgからネタをもらう。
http://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があった。

いい加減疲れてきたのでサンプル本家リファレンスのコピペ
http://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さんのブログ記事を参考にして作った(なぜか全体のコードが見れなかったけど)。
http://d.hatena.ne.jp/mb2sync/20070514#p1

13 :デフォルトの名無しさん:2009/01/08(木) 11:07:32
>>11
配列をvectorにすると、コンパイルは通るけど、実行時にエラーになる。

14 :11: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
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1871.html
Ovenのマニュアルにも冒頭に「Oven is an advanced implementation of Range Library Proposal」と書いている。
http://p-stade.sourceforge.net/oven/doc/html/

16 :デフォルトの名無しさん:2009/01/09(金) 23:38:57
作者不在で、ovenやeggの更新が止まってるのが残念

17 :デフォルトの名無しさん:2009/01/10(土) 03:09:10
ちょwなんというマイナーライブラリスレ

18 :1:2009/01/10(土) 10:28:38
誰か語って

19 :デフォルトの名無しさん: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 :デフォルトの名無しさん: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 :デフォルトの名無しさん:2009/01/26(月) 02:49:20
そろそろ即死から逃れられる頃合いか?

32 :デフォルトの名無しさん:2009/01/29(木) 17:06:39
保守age

33 :デフォルトの名無しさん: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 :デフォルトの名無しさん: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 :デフォルトの名無しさん: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 :停止しました。。。:2009/02/14(土) 18:05:21
真・スレッドリスターター。。。( ̄ー ̄)ニヤリッ

41 :デフォルトの名無しさん: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 :デフォルトの名無しさん: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
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/67a593c8e747b97c#
RangeExがレビュー入りだってさ。
レンジアダプタ( | 演算子のやつ)も入っているよ!

21 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.00 2017/10/04 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)