09/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:デフォルトの名無しさん
09/02/25 20:39:54
>>159
具体例までありがとうございます。
map 比較関数 でググったらいくつか例も出てきたので出来そうです。
よく考えるとmapは2分木を利用してるんだから自前の比較関数を用意してやる必要があるのは当たり前ですね。
勉強になりました。
161:デフォルトの名無しさん
09/02/27 20:33:14
C++やSTLではコンテナの全要素を出力するときどのようにするのでしょうか?
URLリンク(kansai2channeler.hp.infoseek.co.jp)
今は上のようにやってます。
list vector mapやDataのようなクラスが増えていくにつれコードが増え、似たような処理が何回も出てきそうです
162:デフォルトの名無しさん
09/02/27 20:37:20
std::list<T>をTにすればコンテナ全種に使えるようになるはず。
163:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/02/27 20:51:31
まぁそれだけだとlist<list<...>>みたいなのに適応できないけどな
166:161
09/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:デフォルトの名無しさん
09/02/28 00:04:03
とりあえず、rhsは right hand side(右側)の略なんだから
lhs << rhs って形にしようぜw
168:デフォルトの名無しさん
09/03/02 12:55:03
関数オブジェクトにしといてfor_each()じゃだめなのか
169:デフォルトの名無しさん
09/03/03 21:45:22
>>168
それ、コードではどうやるの
170:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/03/04 12:40:27
ostream_iteratorにassignという手も
172:デフォルトの名無しさん
09/03/04 16:04:02
例としてよく引き合いに出されるのは ostream_iterator に copy だと思うが・・・
173:デフォルトの名無しさん
09/03/04 16:19:22
for_eachを使うと copy よりも凝った出力形式を作れるってくらいかな
174:デフォルトの名無しさん
09/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:デフォルトの名無しさん
09/03/10 23:08:36
>>136,143
URLリンク(www.open-std.org)
今のドラフトでは以下の記述が追加されている。
> algorithms that take function objects as arguments are permitted to copy those function objects freely
アルゴリズム内でどうコピーされるかは基本的に実装任せってことになるらしい。
for_each() の戻り値はまったく使えないことになりそうだ。
176:デフォルトの名無しさん
09/03/14 16:56:46
>>175
for_eachの戻りはコピーされた関数オブジェクトに内部状態が反映されてるんじゃなかった?
177:デフォルトの名無しさん
09/03/14 18:17:17
>176
関数オブジェクトに全要素を通して処理した結果の状態が保持されていることを期待するだろうが、
極端に言えば各要素の呼び出し毎に新しくコピーした関数オブジェクトを渡されたりすると、期待する
結果と異なる。
参照使うなりコピーされても大丈夫なようにはできるからまったく使えないは言い過ぎ。
とはいえ、そういう用途なら accumulate 使えばいいじゃん、とは思う。
178:デフォルトの名無しさん
09/03/14 18:22:46
boost::ref使って渡せばいいんじゃないか。boost::mpl::for_eachではうまくいった
179:デフォルトの名無しさん
09/03/18 22:23:42