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

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

【C++】STL(Standard Template Library)相談室 11

1 :デフォルトの名無しさん:2009/01/11(日) 11:13:44
C++標準ライブラリの一つ、STLについて。

前スレ
【C++】STL(Standard Template Library)相談室 10
http://pc11.2ch.net/test/read.cgi/tech/1219719677/

過去ログ・リンク・書籍紹介は >>2 以降

130 :デフォルトの名無しさん:2009/02/23(月) 18:07:27
関数オブジェクトの使い方として、以下のような記述は許されますか?

// generate アルゴリズムを使ってコンテナに公差1の等差数列を代入する
template < class T > class Gens {
public:
  Gens() : s_( 0 ) {}
  Gens( T i ) : s_( i ) {}
  T operator () (){ return s_++; }
private:
  T s_;
};

int main() {
  vector< int > vector1( 20 );
  Gens< int > gens( 10 );                // 問題はココと
  generate( vector1.begin(), vector1.end(), gens ); // ココ
}

普通は
generate( vector1.begin(), vector1.end(), Gens< int >() );
のように書きますが、
あらかじめオブジェクトを構築しておいて、
そのオブジェクトを引数として渡すというものです。
上記の例ではあらかじめオブジェクトを構築することで
ジェネレータが作り出す数列の初項を10に設定しています。

131 :デフォルトの名無しさん:2009/02/23(月) 20:10:05
>>130
全く問題ないよ

132 :デフォルトの名無しさん:2009/02/23(月) 21:15:07
>>130
>上記の例ではあらかじめオブジェクトを構築することで
>ジェネレータが作り出す数列の初項を10に設定しています。
なら
generate( vector1.begin(), vector1.end(), Gens< int >( 10 ) );
でもインジャネーノ?


133 :デフォルトの名無しさん:2009/02/23(月) 21:28:02
>>130
そもそも内部状態を持つ関数オブジェクトをアルゴリズムで使うのはよろしくない
http://www.kijineko.co.jp/tech/superstitions/functor-is-not-copied-in-algorithm.html

134 :デフォルトの名無しさん:2009/02/23(月) 21:49:05
コピー禁止すりゃいいんじゃね?

135 :デフォルトの名無しさん:2009/02/23(月) 22:29:12
誰にも突っ込んでもらえなかったけど、コピー禁止してどうやって渡すんだ orz

136 :デフォルトの名無しさん:2009/02/23(月) 22:33:29
>>133
たしかに規格上は保証がないかもしれないが、なんだか屁理屈に聞こえる。

137 :デフォルトの名無しさん:2009/02/23(月) 23:43:39
>>136
同感だな
内部状態を持つ関数オブジェクトって普通にありえるからな
なんか現実を無視して重箱のすみを突いているって感じだな

138 :デフォルトの名無しさん:2009/02/23(月) 23:53:59
いや、これははまるぞ
移植してバグったとき、大変そうだ

139 :デフォルトの名無しさん:2009/02/24(火) 00:01:50
ん?
マッサーの STL 本では generate のサンプルで内部状態を保持しているし
メイヤーズの Effective STL でも、関数オブジェクトの利点は
「必要に応じていくつでも状態を格納できること」と書いてるぞ?(たとえば p.161 )

述語は純粋関数でないとだめだけど。
サッターの C++ Coding Standardsでは
「述語は関数オブジェクトの部分集合である」( p.172 )としていて
すなわち述語でない関数オブジェクトは純粋関数でなくても良いということになってるぞ?

どっちなんだ。

140 :デフォルトの名無しさん:2009/02/24(火) 00:05:52
ちなみに、generate の第三パラメータは述語ではないので、
(マッサー、メイヤーズ、サッターの本にあるとおり)
純粋関数でなくても良いということになる。

141 :デフォルトの名無しさん:2009/02/24(火) 00:12:15
今、シルトの本も調べてみたが、やっぱり関数オブジェクトの利点として
「値を格納したり、追加機能を実装できる」( p.230 )と書いてるな。

142 :デフォルトの名無しさん:2009/02/24(火) 00:12:48
すまん、全部 age ちまった・・・ orz

143 :デフォルトの名無しさん:2009/02/24(火) 00:44:58
vectorの連続性と一緒だな
普通はコピーなんてしないし、規格作った方もそんなつもりじゃなかったけど
ちゃんと書いてないせいで信用できないし、コピーしちゃう実装を誰かが作っても責められない
そんな誰も得しない状態

0xで直るんかね

144 :デフォルトの名無しさん:2009/02/24(火) 00:52:16
vectorの格納領域は「必ず」連続するようになったのは1998年以降だから
まぁ、いまどきのコンパイラならもう必ず連続すると考えていいんじゃないの。


145 :デフォルトの名無しさん:2009/02/24(火) 11:38:30
std::vector<int> v;
v.reserve(10);
... // v に値を格納
std::copy(v.begin(),v.end(),std::ostream_itreator<int>(std::cout,","));

このコードの copy 内の ostream_iterator... の部分て何を行っているのですか?
コンテナの要素をループで書き出してるのは分かるのですが、内部でどのような処理をしているのでしょう?


146 :デフォルトの名無しさん:2009/02/24(火) 12:43:55
>>138
俺もはまった
boost::refして誤魔化した

147 :デフォルトの名無しさん:2009/02/24(火) 12:53:46
ええ、どこのベンダだよ

148 :デフォルトの名無しさん:2009/02/24(火) 16:00:32
vectorの格納領域と同じで、標準化委員会がどっかで修正コメントだしてないのかな?

149 :デフォルトの名無しさん:2009/02/24(火) 16:14:34
>>130
俺なら output_iterator を受け取る関数を作って back_inserter を渡す。
std::vector なら reserve してからね。

>>133
良くないのはそうだけど、総和とかには使うし、命名とかコーディングスタイルの話になるんじゃないか?

150 :デフォルトの名無しさん:2009/02/24(火) 18:48:24
>>146
それどこのSTLライブラリ?
で、どんなコードではまった?

151 :デフォルトの名無しさん:2009/02/24(火) 20:48:17
>>149
ライブラリの内部実装の話を命名やコーディングスタイルでどうするの?

152 :デフォルトの名無しさん:2009/02/24(火) 23:49:33
>>145
ttp://msdn.microsoft.com/ja-jp/library/0c6y7x31(VS.80).aspx


153 :デフォルトの名無しさん:2009/02/25(水) 00:08:40
>149
総和系なら accumulate があるべ。

154 :デフォルトの名無しさん:2009/02/25(水) 08:55:19
状態を持つと並行処理できないじゃないか。

なーんてね

155 :デフォルトの名無しさん:2009/02/25(水) 09:03:23
>>151
内部状態を持つ関数オブジェクトを使う話で、内部実装の話はしてないよ。
使わないほうがいいけど、使うなら注意を喚起するとか、専用の関数を作って封じ込めるとか、という話。

>>153
全くその通りでした。

156 :デフォルトの名無しさん:2009/02/25(水) 19:52:40
mapは構造体をキーに持つことができないのでしょうか?
具体的には、mapを使って2枚の画像の対応点を記録しようとしています。

typedef struct point
{
int x;
int y;
}point;

map<point, point> correspond;
point p1, p2;
/*p1とp2の座標を入力*/

correspond.insert( pair<point, point>(p1, p2) );

としてコンパイルするとerror C2784が出ます。
環境はVS2008、XP SP3を使っています。

どうしたら解決できるでしょうか?

157 :デフォルトの名無しさん:2009/02/25(水) 20:04:06
エラーの内容から二つのpointを比較できないコードであるということがわかるので、mapの為に比較関数を用意する。
方針としては、グローバルにpointの大小を判別するbool operator<(const point&, const point&)を定義するか、
correspondの宣言の歳にmap<point, point, compare_t> correspond(compare);とする
(ただしcompare_tは戻り値boolで引数に(const point&, const point&)を取ることができる関数オブジェクトまたは関数の型で
compareはそのインスタンス)

158 :デフォルトの名無しさん:2009/02/25(水) 20:25:45
>>157
素早い回答ありがとうございます。
pointのxとyどちらでソートすべきか比較関数を用意してやればよいということでしょうか?

159 :デフォルトの名無しさん:2009/02/25(水) 20:32:21
うん、例としては
bool f(const point& lhs, const point& rhs){
return lhs.x < rhs.x && lhs.y < rhs.y;
}
のようなものを定義して
map<point, point, bool(*)(const point&, const point&)> correspond(f);
かな?

operator<を使う方法についてはeffective C++とか参考にすれば、
綺麗に実装する方法が載ってると思う

160 :デフォルトの名無しさん:2009/02/25(水) 20:39:54
>>159
具体例までありがとうございます。
map 比較関数 でググったらいくつか例も出てきたので出来そうです。

よく考えるとmapは2分木を利用してるんだから自前の比較関数を用意してやる必要があるのは当たり前ですね。
勉強になりました。

161 :デフォルトの名無しさん:2009/02/27(金) 20:33:14
C++やSTLではコンテナの全要素を出力するときどのようにするのでしょうか?
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/8944.txt
今は上のようにやってます。
list vector mapやDataのようなクラスが増えていくにつれコードが増え、似たような処理が何回も出てきそうです

162 :デフォルトの名無しさん:2009/02/27(金) 20:37:20
std::list<T>をTにすればコンテナ全種に使えるようになるはず。

163 :デフォルトの名無しさん:2009/02/27(金) 20:41:47
よくわからないけどこういうこと?
template<typename T>
std::ostream &print(std::ostream &ost, const T &cont)
{
ost << "[";
std::copy(cont.begin(), cont.end(), std::ostreambuf_iterator<T::value_type>(ost, ","));
ost << "]";
return ost;
}

164 :デフォルトの名無しさん:2009/02/27(金) 20:50:54
コンテナを取るんじゃなくて、algorithmみたいに範囲を取るようにすれ。

template<typename Iterator>
std::string to_str2(Iterator first, Iterator last) {
 std::ostringstream oss;
 Iterator it = first;
 oss << "[";
 if (it != last) {
  while (true) {
   oss << (*it);
   ++it;
   if (it == last)
    break;
   oss << ", ";
  }
 }
 oss << "]";
 return oss.str();
}


165 :デフォルトの名無しさん:2009/02/27(金) 20:51:31
まぁそれだけだとlist<list<...>>みたいなのに適応できないけどな

166 :161:2009/02/27(金) 23:02:22
>>162
ほんとですね、全部なおしました
std::ostream& operator<<(std::ostream & rhs, const <T>& lhs)はダメなんですね
当たり前なんでしょうけど

>>163
こういう書き方もできるのですね、、、
p to_str(dlist)かp 'to_str(std::list<Data, std::allocator<Data> > const&)' (dlist)でgdbから呼べるのですが、
ostreamかtemplate使うと消える?みたいなのでObject.to_string()とテンプレートではないto_str(x)は用意するので
ostreamやostringstreamを極力使わずにできればなと

>>164,165
Iteratorの中身がコンテナじゃなさそうな場所に使ってみます

167 :デフォルトの名無しさん:2009/02/28(土) 00:04:03
とりあえず、rhsは right hand side(右側)の略なんだから
lhs << rhs って形にしようぜw

168 :デフォルトの名無しさん:2009/03/02(月) 12:55:03
関数オブジェクトにしといてfor_each()じゃだめなのか

169 :デフォルトの名無しさん:2009/03/03(火) 21:45:22
>>168
それ、コードではどうやるの

170 :デフォルトの名無しさん:2009/03/04(水) 01:25:00
こんな感じ?

template <class T>
struct Out {
void operator()(T& i) const {
std::cout << i << ' ';
}
};

int main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::list<int> aa(a, a + sizeof(a) / sizeof(a[0]));

std::for_each(aa.begin(), aa.end(), Out<int>());
}

171 :デフォルトの名無しさん:2009/03/04(水) 12:40:27
ostream_iteratorにassignという手も

172 :デフォルトの名無しさん:2009/03/04(水) 16:04:02
例としてよく引き合いに出されるのは ostream_iterator に copy だと思うが・・・

173 :デフォルトの名無しさん:2009/03/04(水) 16:19:22
for_eachを使うと copy よりも凝った出力形式を作れるってくらいかな

174 :デフォルトの名無しさん:2009/03/05(木) 09:49:02
#include <pstade/oven/io.hpp>
#include <pstade/oven/make_range.hpp>

int main()
{
namespace oven = pstade::oven;
std::list<int> l = a|oven::copied;
std::cout << (oven::make_range(l)) << "\n";
}

175 :デフォルトの名無しさん:2009/03/10(火) 23:08:36
>>136,143
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#92
今のドラフトでは以下の記述が追加されている。
> algorithms that take function objects as arguments are permitted to copy those function objects freely

アルゴリズム内でどうコピーされるかは基本的に実装任せってことになるらしい。

for_each() の戻り値はまったく使えないことになりそうだ。

176 :デフォルトの名無しさん:2009/03/14(土) 16:56:46
>>175
for_eachの戻りはコピーされた関数オブジェクトに内部状態が反映されてるんじゃなかった?

177 :デフォルトの名無しさん:2009/03/14(土) 18:17:17
>176
関数オブジェクトに全要素を通して処理した結果の状態が保持されていることを期待するだろうが、
極端に言えば各要素の呼び出し毎に新しくコピーした関数オブジェクトを渡されたりすると、期待する
結果と異なる。
参照使うなりコピーされても大丈夫なようにはできるからまったく使えないは言い過ぎ。
とはいえ、そういう用途なら accumulate 使えばいいじゃん、とは思う。

178 :デフォルトの名無しさん:2009/03/14(土) 18:22:46
boost::ref使って渡せばいいんじゃないか。boost::mpl::for_eachではうまくいった

179 :デフォルトの名無しさん:2009/03/18(水) 22:23:42
 

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

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

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