1 名前:デフォルトの名無しさん mailto:sage [04/11/25 21:11:32] C++ のジェネリックプログラミングの話をしましょう。 以下のスレッドを統合するスレです。 STLスレッド Part1 pc.2ch.net/tech/kako/1004/10042/1004287394.html Part2 pc3.2ch.net/tech/kako/1026/10267/1026793823.html 【C++】Boost使い集まれ! pc3.2ch.net/test/read.cgi/tech/1033830935/ (html化待ち?) Generic Programming with C++ Template pc.2ch.net/tech/kako/1008/10085/1008593126.html 【C++】template 統合スレ -- STL/Boost/Loki, etc. pc2.2ch.net/tech/kako/1037/10377/1037795348.html 【C++】template 統合スレ -- Part2 pc2.2ch.net/test/read.cgi/tech/1047978546/ (html化待ち) 【C++】template 統合スレ -- Part3 pc5.2ch.net/test/read.cgi/tech/1066493064/ (html化待ち) 【C++】template 統合スレ -- Part4 pc5.2ch.net/test/read.cgi/tech/1083550483/ (html化待ち) 【C++】template 統合スレ -- Part5 pc5.2ch.net/test/read.cgi/tech/1091522597/ 関連スレ、その他リンクは >>2-5 あたりに。
159 名前:デフォルトの名無しさん [04/12/29 05:06:16] それはすくなくともLinuxなら可能です。 とくに、今後の64bit Linuxなら、アドレス「空間」はいくらでも余ってるので、 何の問題もないでしょう。
160 名前:デフォルトの名無しさん mailto:sage [04/12/29 17:23:10] >>159 ^^
161 名前:デフォルトの名無しさん mailto:sage [04/12/29 17:48:45] >>153 やりたいようにやればあ。 絶対アドレス依存じゃないヒープ保存で有名なのはEmacsとTeX。 絶対アドレスに依存するのはちょっと面倒だね。 C++のオブジェクトを直接張り付けるんじゃなくても、 wrapper classで仮想的に扱えるよね。
162 名前:デフォルトの名無しさん mailto:sage [04/12/29 21:34:37] おまえら、「boost の new」の意味はわかってるのか? 漏れにはわからん。
163 名前:デフォルトの名無しさん mailto:sage [04/12/29 21:39:05] 「boostで使うnewとかもひっくるめて自分でglobalなoperator new()をオーバーライドしちゃいます」 という意味だと思ってた
164 名前:デフォルトの名無しさん mailto:sage [04/12/29 21:53:12] >>163 そうなると、「mmap+boost で」っていうのがわからん。 boost も template も関係ないじゃないか。
165 名前:デフォルトの名無しさん mailto:sage [04/12/29 21:58:22] ううむ。確かに。 boostの機能のキの字も使ってないもんなぁ。
166 名前:161 mailto:sage [04/12/29 22:00:47] そもそもシリアライズじゃないし(w
167 名前:デフォルトの名無しさん mailto:sage [05/01/04 00:56:10] 知り合いs
168 名前:デフォルトの名無しさん mailto:sage [05/01/06 00:15:21] GC(参照カウント方式)に使えるポインタオブジェクトで オブジェクトのconst修飾が参照先のconst修飾に対応した クラスってないでしょうか Boost流だとこんな↓感じ? template<typename T> class my_shared_ptr : protected boost::shared_ptr<T> { public: const T * operator->() const { return __super::operator->(); } T * operator->() { return __super::operator->(); } // other functions implementation... }; おねがいします
169 名前:デフォルトの名無しさん mailto:sage [05/01/06 00:22:41] >>168 そんな感じでいいんじゃないの?
170 名前:168 mailto:sage [05/01/06 00:26:23] はい、ありがとうございます ただ、既存のライブラリでいいのはないかと思いまして・・・
171 名前:デフォルトの名無しさん mailto:sage [05/01/06 01:16:46] >>170 Boost は「既存のライブラリ」以外の何だというのかね?
172 名前:デフォルトの名無しさん mailto:sage [05/01/06 02:12:11] >>168 ちなみにshared_ptr<T const>を嫌う理由は何ですか?
173 名前:デフォルトの名無しさん mailto:sage [05/01/06 06:31:17] 重い
174 名前:デフォルトの名無しさん mailto:sage [05/01/06 10:28:20] プログラム全体の動作に致命的なほど遅くはなんねぇよ
175 名前:デフォルトの名無しさん mailto:sage [05/01/06 10:56:57] 何の要件もなしに「重い」と言って切り捨てる >173 も、 何の前提もなしに「致命的なほど遅くはなんねぇ」という >174 も、 同じ程度に浅はかである。
176 名前:デフォルトの名無しさん mailto:sage [05/01/06 11:01:20] >>175 それを否定してしまったら何もかけなくなっちゃうよ。
177 名前:デフォルトの名無しさん mailto:sage [05/01/06 11:09:22] >>176 175が何を否定してるんだ?
178 名前:デフォルトの名無しさん mailto:sage [05/01/06 11:10:18] 日本の将来
179 名前:電波系赤の他人 mailto:sage [05/01/06 11:13:22] 俺も人格も否定しているような気がする。
180 名前:デフォルトの名無しさん mailto:sage [05/01/06 18:37:00] >>172 嫌というほどでもないんですが、 コンパイルが遅そうとか、その程度です const my_shared_ptr<T> get_obj_ptr() const; my_shared_ptr<T> get_obj_ptr(); より、 shared_ptr<T const> get_obj_ptr() const; shared_ptr<T> get_obj_ptr(); の方が意味的に適切だとは思うんですが 自分で書くのめんどうなので、とりあえずboost::shared_ptrでいいや・・・
181 名前:デフォルトの名無しさん mailto:sage [05/01/06 20:30:30] こういうのどうですか? #defineBEGIN_JUNK( __Super, __Misc ) \ template< int _N >struct __Junkyard{ enum { _junk_no = __Junkyard< _N - 1 >::_junk_no }; }; \ template<> \ struct __Junkyard< __LINE__ > : public __Super::_junk \ { \ enum { _junk_no = __LINE__ }; \ typedef __Super::_junk _prev; \ __Misc; \ }; \ typedef__Junkyard< __LINE__ >_start_junk; \ #defineREDEF_JUNK( __Misc ) \ template<> \ struct __Junkyard< __LINE__ > : public _prev_junk \ { \ enum { _junk_no = __LINE__ }; \ typedef _prev_junk_prev; \ __Misc; \ }; \ #defineEND_JUNK() \ typedef_cur_junk_junk; \ 長いので詳細は↓に書いてあります。 www2.odn.ne.jp/freelife/Junkyard.htm 割と使えると思うんだがどうだろう?
182 名前:デフォルトの名無しさん mailto:sage [05/01/06 22:08:44] >181 マクロで実装してるreflection系ライブラリの提案見るたびに思うんですけれど マクロとテンプレートの相性の悪さはどう対処するつもりなんでしょうか? 毎回typedef?(面倒)BOOST_PP_SEQ?(カッコ悪い)variadic macro待ち?(いつ出る?) struct Sample2 { typedef Sample2 _self; BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; ); DATA_MEMBER( 1, my_class<char, int>, x ); END_JUNK(); };
183 名前:181 mailto:sage [05/01/06 22:39:57] >>182 言いたいことには同意 対処って程ではないが、苦肉の策でこんなことやってる #define $ , struct Sample2 { typedef Sample2 _self; BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; ); DATA_MEMBER( 1, my_class<char $ int>, x ); END_JUNK(); }; はげしくかっこ悪いが w
184 名前:デフォルトの名無しさん mailto:sage [05/01/06 22:59:24] >183 それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか? 色々漁ってみたら限界はあるもののいくつか対処法はあるみたいですね. lists.boost.org/MailArchives/boost/msg46364.php からだと template<class T> struct wrap { typedef T type; }; template<class T> struct wrap<void (T)> { typedef T type; }; #define TYPE(x) wrap<void x>::type #define DEP_TYPE(x) typename wrap<void x>::type struct Sample2 { typedef Sample2 _self; BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; ); DATA_MEMBER( 1, TYPE((my_class<char, int>)), x ); END_JUNK(); }; とか.記事本文では指摘されていないですけれど,型がdependent typeか どうかでマクロを使い分ける必要もありますね,これ. ・・・っていうか話題をそらしてしまってすいませんです.
185 名前:181 mailto:sage [05/01/07 00:10:36] >>184 コンパイル通らないですか? 当方、VC++ 2003 しかないので、他のコンパイラだと通らないのだったら正直すまん ただ、VC++ 2003 でも多重にマクロを定義している時は、評価順序によって通らない時もある その時はマクロを調整するでは駄目ですか・・? リンク先のようなやり方もあるとは知りませんでした 参考にさせて頂きます
186 名前:181 mailto:sage [05/01/07 00:38:04] あと、typename に対してですが __if_exists が使えればこういうやり方もあります template< bool >struct ExistsBool {}; template<>struct ExistsBool< true > { enum { _true }; }; #defineTYPEDEF( __Type, __Alias ) \ __if_exists( __template__::_true ){ \ typedef typename __Type __Alias; \ } \ __if_not_exists( __template__::_true ){ \ typedef __Type __Alias; \ } \ template< class _Type > struct Sample7 { typedef ExistsBool< true >__template__; TYPEDEF( _Type::_type, _type ); // 2値判定にも使える __if_exists( ::ExistsBool< _Type::_n == 0 >::_true ){ } }; __template__ をクラスごとに宣言する必要があるのが難点ですが
187 名前:デフォルトの名無しさん mailto:sage [05/01/07 19:48:15] >>184 >それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか? 引数展開の前に引数は確定するから、この例では問題ない。 でもこの結果を別のマクロに渡すと結局だめだから、 あまりお勧めはできないが。 # define ID(x) x # define COMMA() , # define DECL_A(type, var) type var # define DECL_B(type, var) ID(type) var DECL_A(std::pair<int COMMA() int>, pa); // ok DECL_B(std::pair<int COMMA() int>, pb); // error: IDの引数過多
188 名前:184 mailto:sage [05/01/07 21:39:12] >186 考えてみた結果enclosing scopeがtemplateかどうかに対する切り分けが 本質的に必要ではないかと思うのでこの方法はあまり使えなさそうです. >187 マクロのargument substitutionについて理解が足りていませんでした. function-like macroがidentityされてから後,replacement-listに対する 置換が実行される前にargumentに含まれるmacro tokenが置換されるんですね. 見た感じやはり184の解法が幾分かbetterでしょうか.
189 名前:181 mailto:sage [05/01/08 00:55:07] これでどうだろう。>>184 と組み合わせてみた。 template<class T> struct wrap{ typedef T type; }; template<class T> struct wrap<void (T)>{ typedef T type; }; #define TYPE(x) wrap<void x>::type template< bool >struct ExistsBool{}; template<>struct ExistsBool< true >{ enum { _true }; }; #defineTYPEDEF( type, alias ) \ __if_exists( __template__::_true ){ typedef typename TYPE((typename type)) alias; } \ __if_not_exists( __template__::_true ){ typedef TYPE((type)) alias; } \ #defineCLASS( __Class ) \ typedef __Classself; \ typedef ExistsBool< false >__template__; \ #defineTEMPLATE( __Class ) \ typedef __Classself; \ typedef ExistsBool< true >__template__; \ #define$,
190 名前:181 mailto:sage [05/01/08 00:55:32] つづき template< class T > struct hara { TEMPLATE( hara ); template< class T > struct horo { TEMPLATE( horo ); TYPEDEF( T::type,type ); }; struct hire : public horo< T > { CLASS( hire ); TYPEDEF( my_class<char $ int>, type2 ); }; TYPEDEF( hire::type, type ); TYPEDEF( hire::type2, type2 ); }; $ を主張するわけではないが、タイプ量が少ないと嬉しいので ところで、誰も Jankyard に触れてくれない orz
191 名前:デフォルトの名無しさん mailto:sage [05/01/08 01:04:10] 誤: typedef __Classself; 正: typedef __Class self; 誤: #define$, 正: #define $ , です。連投すんまそん
192 名前:デフォルトの名無しさん mailto:sage [05/01/09 07:22:01] >ところで、誰も Jankyard に触れてくれない orz ぶっちゃけていうとreflection系ライブラリの提案はすでに色々ありますからね. 自分の知っている範囲だと www.garret.ru/~knizhnik/cppreflection/docs/reflect.html www.arneadams.com/reflection_doku/index.html あたりでしょうか?後プロパティの実装なら www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1615.pdf とか. ついでに__if_existsに関して,名前がするかどうかというコンパイル時の情報で プリプロセッサレベルの処理を行えるというのは確かに強力で魅力的なんですが やはりVC++限定なのがネックでしょうね. 一応クラスのメンバ(型・関数・変数)や非メンバ関数の存在をテストしてその情報を コンパイル時に取得する技法を標準C++の範囲内で実装することは可能なので, それでほとんどの部分は代用できると思います. (というか自分は本質的に__if_existsが必要な状況を思い付けません)
193 名前:181 mailto:sage [05/01/09 09:15:49] >>192 今回提案したのはリフレクション自体ではなく、その辺りをサポートする仕組みだったのだが。 リフレクションも含む、その他タイプリスト生成や、マクロ間での型の受け渡し、 継承関係の中で連番発行など。プロパティはネタです。 __if_exists は本質的に必要ないのには同意します。 ただ、テンプレートの特化の変わりに使えるので __if_exists を使うとシンプルに記述出来ることも少なくありません。 この辺りは好みによるのでしょうね。 VC++限定なのはどうしようもないですが。 いづれにせよ、騒がしているだけのようなので、これで引っ込むことにします。 >一応クラスのメンバ(型・関数・変数)や非メンバ関数の存在をテストしてその情報を >コンパイル時に取得する技法を標準C++の範囲内で実装することは可能なので, >それでほとんどの部分は代用できると思います. 詳細きぼん
194 名前:デフォルトの名無しさん [05/01/09 12:47:08] ここでいいのかしら。ちょっと彷徨い気味ですがどうぞよろしゅう 2つのソート済みvectorの中で共通する項目の数を数えたいのですが set_intersection( (省略) , common_ins) common.size(); で実行しています。これだとvectorの中身が100kとかになった時に速度がちょっとまずいのです。 上記より高速な方法でなにか良案ご存知の方いらっしゃいませんか? ちなみのその後、共通部分から作ったcommonに対する処理は何も行いません(数えたいだけです)
195 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:52:27] vecAとvecBを mergeしてvecCを作りuniqueしてvecA.size()+vecB.size()-vecC.size()
196 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:54:20] set_intersectionもソート済み範囲なのか。なら>>194 の方が遅そうだ。
197 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:59:38] >>195 のがだろ
198 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:00:07] www.google.com/search?num=100&as_qdr=all&as_occt=any&as_dt=i&ie=sjis&oe=sjis&lr=lang_ja&as_q=%83%5c%81%5b%83g%8d%cf%82%dd%83x%83N%83%5e%82%cd%92x%82%a2
199 名前:194 mailto:sage [05/01/09 13:14:44] mergeして差分を考える方法は実行済みなのですが 残念ながら、set_intersectionの方法に比べて倍近く時間がかかってしまったのです う〜ん、これはもう構造的にどうしようもないですかね 割と頻繁に更新されるvectorなので、馬鹿にならないコストなんですが・・・
200 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:29:34] スマートポインタを使ってるならただのポインタに変えてみる。 ただのポインタなら実体に変えてみる。 実体ならポインタに変えてみる。
201 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:33:31] set_intersection の result は OutputIterator なので、 *result = common (or *result++ = common) がカウントアップの動作をするような擬似イテレータを作れば、 コピーのコストを無くすことができそうだ。
202 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:39:05] うっ、そこを触ることになりますか… Iteratorの中身について理解が出来ていないので全くの手探りになりますが、資料ひっくり返して勉強します ありがとうございました
203 名前:デフォルトの名無しさん mailto:sage [05/01/09 14:48:42] 暇つぶしにやってみた。 boost::counting_iterator がそのまま使えるかと思ったけど OutputIterator じゃなかった。 しょうがないから結局ファンクタ書く羽目になった。 #include <cstddef> #include <algorithm> #include "boost/function_output_iterator.hpp" template<typename Incrementable> class increment { Incrementable* m_target; // not reference to make this class Assignable public: increment(Incrementable& target) : m_target(&target) {} template<typename T> void operator () (T const&) { ++*m_target; } }; template<typename InputIterator1, typename InputIterator2> std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { std::size_t result = 0; std::set_intersection(first1, last1, first2, last2 , boost::make_function_output_iterator(increment<std::size_t>(result))); return result; } lambda 使えば、 increment くらい消せるかも。
204 名前:デフォルトの名無しさん mailto:sage [05/01/09 17:29:22] いちおうできた。 #include <cstddef> #include <algorithm> #include "boost/function_output_iterator.hpp" #include "boost/lambda/lambda.hpp" template<typename InputIterator1, typename InputIterator2> std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2) { std::size_t result = 0; std::set_intersection(first1, last1, first2, last2 , boost::make_function_output_iterator(++boost::lambda::var(result))); return result; } ただ、 lambda のファンクタが Assignable にならないので、 _GLIBCXX_CONCEPT_CHECKS で怒られた。 VCでは /W3 まで大丈夫。
205 名前:デフォルトの名無しさん [05/01/09 19:25:21] template<class T> struct X { void func() {} }; TがクラスAかクラスAのpublic派生クラスの特殊版を定義する場合 X<T>::func()をどのように定義すればよいのでしょうか?
206 名前:デフォルトの名無しさん mailto:sage [05/01/09 23:59:37] >193 具体的な実装の例だとboost/mpl/has_xxx.hppとかが参考になるかと思います. >205 Boost使うなら以下のような感じでですかね? #include <iostream> #include <boost/mpl/if.hpp> #include <boost/type_traits/is_base_and_derived.hpp> struct A{ }; template<class T> struct X{ struct yes_tag{ }; struct no_tag{ }; typedef typename boost::mpl::if_< boost::is_base_and_derived<A, T>, yes_tag, no_tag>::type dispatch_tag; void func_dispatch(yes_tag){std::cout << "derived version" << std::endl;} void func_dispatch(no_tag){std::cout << "non-derived version" << std::endl;} void func(){ func_dispatch(dispatch_tag()); } }; struct Hoge : public A{ }; struct Huga{ }; int main(){ X<Hoge>().func(); X<Huga>().func(); }
207 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:24:10] こういう書き方って動作は保証されるのでしょうか? std::vector<int> test; for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) { test.erase(element); }
208 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:30:51] ↑おもいっきりぬけてたので修正しました std::vector<int> test; test.push_back(0); test.push_back(1); test.push_back(2); test.push_back(3); test.push_back(4); for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) { if ( *element == 2 ) { test.erase(element); } }
209 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:35:21] >>208 eraseした時点でイテレータそのものが無効になるよ。
210 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:08] ではループしつつ条件に当てはまるイテレータの内容だけ削除するには どのような手段を用いればよいのでしょうか? プールで一端どこかにマークをつけて、ループ終了後該当の物だけeraseとかでしょうか?
211 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:33] だから、std::remove()で、値が2の要素をコンテナの後に集めておき、最後に一回だけ eraseするといい。 test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());
212 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:57] あ、ループがプールに・・orz
213 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:39:57] なるほど、ありがとうございます
214 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:40:36] こういう書き方は最初は戸惑うかもしれないが、慣れるとすごく便利になる。 そのうちこれでも不便になって、必ずboost::bindとかに手を出したくなるから。
215 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:43:26] わかりました。 参考にしてみます。
216 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:43:57] というか、EffectiveSTLを読め。 >>211 のも含めて色々書いてあるから
217 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:50:47] test.erase(std::remove(test.begin(), test.end(), 2), test.end()); でもいいねこの場合。叙述関数あるいは関数オブジェクトの替わりにconstな値を とるだけだから。
218 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:58:23] if ( *element == 2 ) { test.erase(element++); } でOK。
219 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:01:18] >>218 は忘れて。 for ( std::vector<int>:iterator element = test.begin(); element != test.end(); ) { if ( *element == 2 ) { element = test.erase(element); } else ++element; }
220 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:01:28] >test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end()); わけがわかりません。 こんなの仕事で使われたら恐怖です。 やめてください。
221 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:02:08] >>217-219 やめてください。 怖いです。
222 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:02:50] >>218 vectorコンテナのeraseはCで言うところのrealloc()に相当する動作を実行する 事もあるんだぞ。でたらめ書くな。
223 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:03:47] >>220 そのくらいのSTL構文も分からないならC++使うのをやめた方がいいよ。
224 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:06:37] >>222 おいおい。 「イテレータは、より小さなインデックスの要素が挿入または削除されたり、再割り当てが 行われて容量が変わるまで有効」だぞ。 規格票をよく読め。おまえこそでたらめ。
225 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:10:44] 規格票でました。 m9(^Д^)プギャー
226 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:12:25] §23.1.2.8当たりだろ。
227 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:13:13] www-6.ibm.com/jp/developerworks/linux/041203/j_l-cpregex.html >言語の機能 であるはずのものが、その言語のユーザーを恐れさせるようになったら、何かを変えるべき時なのです。
228 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:13:59] >>226 それAssociative Container
229 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:15:05] ここは 問題を無闇に複雑にして悦に浸る馬鹿のス靴(なぜか変換できない) ですね。
230 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:19:30] §23.2.4.3当たりだと見た。
231 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:20:25] >>227 >>229 またperlとかrubyの○キ信者ですか?
232 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:23:27] boostが異常なのは認めなければなるまい。 昨今のC++は異常が常態。
233 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:24:29] 確かに異常だが、使っているうちに快感になる。
234 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:24:50] (23.1.1/7)と(23.2.4.3/3)読む限り>219でもOKっぽいですね
235 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:27:46] CommonLispのようなわかりにくさを競い合って悦に浸るのがここの流儀
236 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:28:39] >>234 OKだろ。個人的には俺はあまり書きたくないけど。
237 名前:デフォルトの名無しさん [05/01/11 00:57:13] >>219 引くってのはどうよ。 for(element = test.begin(); element != test.end(); ++it) { if(*element == 2){ test.erase(element--); } } あ、でも element = test.begin(); element--; は大丈夫なのかな。 まぁ、EffectiveSTLを読んでいれば test.erase(remove(),test.end())と書くというのに一票。
238 名前:237 [05/01/11 00:58:59] 訂正。 >>237 ++it => ++element
239 名前:デフォルトの名無しさん mailto:sage [05/01/11 01:06:22] >>237 ダメ
240 名前:デフォルトの名無しさん mailto:sage [05/01/11 14:28:58] for(element = test.begin(); element != test.end(); ++element) if(*element == 2) { element = --test.erase(element); } こんな感じが一番シンプルなところなのかな?
241 名前:デフォルトの名無しさん mailto:sage [05/01/11 15:04:23] removeとeraseの組み合わせが一番シンプル
242 名前:デフォルトの名無しさん mailto:sage [05/01/11 15:59:47] とりあえずremoveとeraseの組み合わせが何でも一番です(^^
243 名前:デフォルトの名無しさん mailto:sage [05/01/11 16:01:18] clearって手もあるよ
244 名前:デフォルトの名無しさん mailto:sage [05/01/11 19:46:02] >>223 プロジェクトって大抵いろんな技術レベルの人がいるから その台詞でばっさりはちょっと抵抗あるなぁ。 一人でやるなら何使ったってOKだけどね。
245 名前:デフォルトの名無しさん mailto:sage [05/01/11 20:32:55] >>244 211はかなり基本だと思うんだけど...
246 名前:デフォルトの名無しさん mailto:sage [05/01/11 20:46:56] あれが解からないって? …ときどき思うんだ。俺、なんで2chなんか見てるんだろう、って。
247 名前:237 [05/01/11 22:30:46] なんか不安になってきたので確認したいのですが vectorのeraseで無効になるのは消した要素以降のイテレータですよね。 だから>>237 と>>240 は結果的に同じことになりますよね? 私が>>237 で心配だったのは 最初の要素でヒットしたとき、 element = test.begin(); --element; ++element; でbegin()に戻るのが規格で保証されてなさそう(多くの実装では戻りそうだけど) というのと 元々のサイズが1のとき、test.erase(test.begin());で全てのイテレータが無効になる ときにバッファを解放してbegin()とend()がNULLを返してくるようになるとend()と 永遠に一致しなそう(VC7のclearがバッファを解放(capacityを0)にしてくれるのに 気づいて以来疑り深くなっています) の二点なんですけど、 そのあたりをふまえて>>239 はダメと言っているんですよね? うーん、remove(や類似のアルゴリズム)を使わないでやるならやはり>>219 なのか。
248 名前:237 [05/01/11 22:34:15] ああ、そうか、後者の不安は>>240 と書くことで払拭されるのか。 スマソ
249 名前:244 mailto:sage [05/01/12 01:12:53] >>245 俺も基本だと思ってるし、これぐらいわかれよって思ってるよ。 でも、それが通用しないのが多人数でしょ?って投げかけ。 …技術と関係なくなるか。消えるよ。スレ汚しすまん。
250 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:17:30] なぜforで回す……わざわざC++使うんだったら、効率にも気を 配らないともったいないよ。 >247 >237 >240の例だと ・ループごとにtest.end()の呼び出しが発生する ・elementを削除するたびにvectorの再パッケージが発生する で遅くなりますな。 あと、>237だと後置インクリメントの一時オブジェクトの生成が 発生してさらに効率が悪くなります。
251 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:18:18] なぜにremoveを使いたくないのかが知りたい
252 名前:250 mailto:sage [05/01/12 02:24:13] 自己フォロー >237>240ともに、はelement==test.begin()のときに *element==2だとアウトですな。 #test.begin()よりも前に移動するから未定義の世界に突入
253 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:48:28] >250 ループごとのtest.end()も後置インクリメントもここでは本質じゃない。
254 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:56:25] >253 ふうん、じゃ、こう言っておこうかな ・郷に入れば郷に従え STLはC++の一部なんだから、それぐらい覚えろ ・こんぐらいできないなら、そもそもC++使うな or こんなこともできないやつをプロジェクトに入れるな 他にもPerlとか色々あるんだから、わざわざC++を使う必要ないよね。
255 名前:デフォルトの名無しさん mailto:sage [05/01/12 07:36:48] list に追加されている remove(),remove_if() 見習って、 template<class Container> void remove(Container&, typename Container::value_type const&) template<class Container, class Predicate> void remove_if(Container&, Predicate p); のような関数を作れば、双方文句はなかろう。
256 名前:255 mailto:sage [05/01/12 07:50:40] s/Container/Sequence/ remove() の意味が混乱を招きやすいという認識はSGIのドキュメントにも記載されている。 「慣用句だ」と言って押し切るよりは、むしろまともな認識だと思う。 www.sgi.com/tech/stl/remove_if.html#1 これをそのままソースに書いてしまうと言うのは、 例えば定数除算をシフトで書いてしまうのと同等の誤りであると思う。
257 名前:デフォルトの名無しさん [05/01/12 07:51:49] forで回すからうっかり>>218 とか>>237 とか>>240 とかいう問題のあるコードを書いて しまうんだよ。 だったらおとなしくremoveを使えと。 まぁ、色々書き方があってその中から適切な物を状況に応じて選ぶのがプログラムの 醍醐味ではあるけど。
258 名前:デフォルトの名無しさん mailto:sage [05/01/12 08:53:47] >なぜにremoveを使いたくないのかが知りたい 叙述関数やoperator==とかにコードが分散するのがイヤ ループが内包されるのがイヤ ループを制御下に置いておきたい ブレイクポイントが設定しやすいよ 削除以外の用途にループが流用できるよ てゆうかぶっちゃけremove_copy中でやってること、あれはありえないでしょ それを言ったらvectorでeraseすること自体ありえないかw
259 名前:デフォルトの名無しさん mailto:sage [05/01/12 09:59:55] >ループが内包されるのがイヤ ループを制御下に置いておきたい ループを明示的に書くより効率が良くなる可能性があるし、 コードの見通しも良くなる