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 あたりに。
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] >ループが内包されるのがイヤ ループを制御下に置いておきたい ループを明示的に書くより効率が良くなる可能性があるし、 コードの見通しも良くなる
260 名前:デフォルトの名無しさん [05/01/12 10:06:05] >>254 「理想郷」との差でしかモノを語れない 頭でっかちの引き籠もりはレスしなくていいです ;-)
261 名前:デフォルトの名無しさん mailto:sage [05/01/12 10:32:21] >260 それ、オレじゃない。人違いだ
262 名前:デフォルトの名無しさん [05/01/12 10:48:33] >260 IDくらい見ろ、ボケ!
263 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:10:58] >>262 この板ID無いんだって気付よ!
264 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:21:54] お前さんたちなんか楽しそうだね。
265 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:42:25] IDの見方知らない香具師ってまだいたんだね
266 名前:デフォルトの名無しさん mailto:sage [05/01/12 12:13:29] はっきりいってvectorに限らず配列っぽいデータ構造を使っている時に removeみたいなアルゴリズムを適用したくなることってあるか? 無理して適用しておもしろいことがあるようなものでもないと思うのだけど… 何か見落としている革新的な理由でもあったりするのだろうか?
267 名前:デフォルトの名無しさん mailto:sage [05/01/12 23:55:01] > removeみたいなアルゴリズムを適用したくなることってあるか? 配列から複数の要素を一度に取り除きたいときだな。
268 名前:デフォルトの名無しさん mailto:sage [05/01/13 00:11:28] 簡単 let remove x num = snd (List.partition (fun a -> a=x) num);;
269 名前:デフォルトの名無しさん [05/01/14 14:04:12] >>268 配列っぽくないデータ構造。
270 名前:デフォルトの名無しさん [05/01/15 01:33:25] >>267 そそ、端からeraseしてると効率悪いし、 効率的な処理にしようとすると意外に面倒。
271 名前:デフォルトの名無しさん mailto:sage [05/01/17 09:41:54 ] 俺も小さくて、しかもあまり使わないような関数を分散させるのが嫌いなんだけど、 「リファクタリング」を読むと、一行処理すら場合によっては関数にすることを推奨してるんだよな。 しっかりした関数名をつけることによって可読性が高まるって話なんだけど、 必ずしもそうとは思えないのは、英語圏ネイティブじゃないせいかね。 と、templateスレに書き込もうとしたのだけど、主旨に合わないのでこっちに投棄
272 名前:デフォルトの名無しさん mailto:sage [05/01/17 09:43:01 ] C++スレに書くつもりが… もうどうでもいいや
273 名前:デフォルトの名無しさん mailto:sage [05/01/17 13:41:34 ] リファ〜に書いてあるのは関数じゃなくてメソッドのことでは 何の分類もしない単独の関数増やしてくのはあんま良いとは思えないが メソッドの場合インターフェース抽出とか階層整理とかで意味がある
274 名前:272 mailto:sage [05/01/17 17:58:06 ] >>273 失礼、つい関数と呼んじまう。 インターフェース抽出や階層整理は、それ自体をメインにして行うべきな気がするんだよねぇ。 それどころかそれ以前で、非道い話だが「たくさんの、たった数行のメソッド」ってだけで、嫌悪感を感じてしまう。 いずれにせよスレ違い申し訳ない。
275 名前:デフォルトの名無しさん mailto:sage [05/01/18 00:41:35 ] >>273 そんな区別ないだろ。 少なくともC++ではthisポインタの有無しか違いはないわけで、 それが関数分けの基準に影響するとは思えない。
276 名前:デフォルトの名無しさん mailto:sage [05/01/18 01:35:22 ] 時々272のような人いるよね。 読むときあっちこっちの関数みないといけないから、とか言って。 このヘタレが
277 名前:デフォルトの名無しさん mailto:sage [05/01/18 01:45:39 ] そもそも行数とか関係ないだろ
278 名前:デフォルトの名無しさん mailto:sage [05/01/18 02:41:33 ] >275 その他にも可視性とアクセス範囲に違いがあるわけで……
279 名前:デフォルトの名無しさん mailto:sage [05/01/18 08:17:20 ] >>278 そうだな。 それらが要るならクラス作ってメンバ関数を作ればいいし、 要らないならフリー関数にしてもいい。 どう整理するかどうかが違うだけで、 処理に名前をつけてまとめたほうがよいかどうかの基準には関係ない。 複数のフリー関数を作った後に、さらに それらをまとめてクラスを作ればよいことに気付くことも考えられる。 思い立ったらさっさと名前付けてまとめれ。 渋る意味がわからん。
280 名前:272 mailto:sage [05/01/18 08:20:53 ] ちとスレ違い悪いんでこっちでレス pc5.2ch.net/test/read.cgi/tech/1099112338/41
281 名前:デフォルトの名無しさん mailto:sage [05/01/21 18:18:02 ] お聞きしたいのですが、 下記(次レス)のコードがVC7.1でコンパイルできませぬ。 どこがいけないのでしょうか… 色々実験してみた結果 ・UINT を int にすると通る。 ・UINT を std::size_t にしてもダメ。 ・typename T を削除して、 boost::array の T を int とかにすると通る。 ・boost:array の nSize を適当な数値で直打ちすると通る。 ・bcc5.5.1 では普通に通る。
282 名前:281 [05/01/21 18:18:34 ] #include <boost/array.hpp> typedef unsigned int UINT; template<typename T, UINT nSize> class A { typedef typename boost::array<T, nSize> tObjects; typedef typename tObjects::iterator tObjectsIt; tObjects m_cObjects; public: tObjectsIt Func(); }; // ↓C2244:関数の定義を既存の宣言と合致させることができませんでした。 template<typename T, UINT nSize> inline typename A<T, nSize>::tObjectsIt A<T, nSize>::Func() { return m_cObjects.begin(); }