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 あたりに。
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(); }
283 名前:デフォルトの名無しさん [05/01/21 20:49:28 ] >>281 手元にVC7.1もboostもないし、よくわからんけど、 コンパイラがバグってることはよくあるからw
284 名前:デフォルトの名無しさん mailto:sage [05/01/21 20:57:34 ] >>282 g++(3.3.3)ではなんの警告もエラーもなく通るのぅ……
285 名前:デフォルトの名無しさん mailto:sage [05/01/21 21:31:52 ] >>282 戻り値を素直に typename boost::array<T, nSize>::iterator とすると通りますね。
286 名前:デフォルトの名無しさん mailto:sage [05/01/22 00:57:24 ] typedefがprivateなのにinlineなのがいけないんじゃないのか? と試してもないのに言ってみる
287 名前:281 mailto:sage [05/01/22 11:00:38 ] やはり、コンパイラが悪い方向なんですか… orz なお、>>286 を参考に、 すべてのメンバをpublic にしてみてもコンパイルが通りませんでした。 しょうがないので、現状では ・class内に直書き ・>>285 の方法 の2点で回避したいと思います。 どうもありがとうございました。
288 名前:デフォルトの名無しさん mailto:sage [05/01/22 11:27:55 ] いまだにちゃんと動かないコンパイラ多いのかよ おまえらC++信用できますか?
289 名前:デフォルトの名無しさん mailto:sage [05/01/22 11:28:34 ] C++なら信用できるよ。
290 名前:デフォルトの名無しさん mailto:sage [05/01/22 15:39:27 ] >>282 vc8 でもダメっぽい
291 名前:デフォルトの名無しさん [05/01/23 15:44:13 ] boost::bindはstd::bind2ndとかより実行速度が落ちるって本当ですか?
292 名前:デフォルトの名無しさん mailto:sage [05/01/23 16:18:47 ] >>291 ためして、みなさいって。
293 名前:デフォルトの名無しさん mailto:sage [05/01/23 16:20:48 ] using句が,による複数引数を受け付けないのは何故ですか? using A::AA, A::AB, A::AC; のように出来たら便利だと思うのですが?
294 名前:デフォルトの名無しさん mailto:sage [05/01/23 17:06:31 ] 本スレの次スレ 【標準C++】C++相談室 part39【STL含む】 pc5.2ch.net/test/read.cgi/tech/1106466303/
295 名前:デフォルトの名無しさん mailto:sage [05/01/23 17:51:32 ] >>293 そんなんオレらに聞かれても困るよ
296 名前:デフォルトの名無しさん mailto:sage [05/01/23 17:57:05 ] >>293 プリプロセッサマクロを書くとか? あんまり便利とも思えないけど
297 名前:デフォルトの名無しさん [05/01/23 22:42:53 ] boost(かSTL)に、次のような関数テンプレートって含まれていませんか? template<typename T> inline void assign(T& lhs, const T& rhs) { lhs = rhs; } 次のような感じで、setterを用意していないメンバ変数(m_is_foo)を変更する関数オブジェクトを作るのに使いたいのです。標準であるならそっちを使いたいなと思いまして。 hoge(boost::bind(assign<bool>, boost::ref(m_is_foo), true));
298 名前:デフォルトの名無しさん mailto:sage [05/01/23 23:01:05 ] >>297 試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ?
299 名前:297 mailto:sage [05/01/23 23:16:36 ] >>298 > 試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ? いけました。サンクスです。 うーん、lambdaか…。主観ですが実戦投入はちょっと怖いんですよね。
300 名前:デフォルトの名無しさん mailto:sage [05/02/07 09:18:51 ] ふぇ〜い Boostを最新リリースにしたら@VC6 _bvector.hでコンパイラが内部エラー起こしてビルドできない Releaseビルドなら通った コンパイラもしょっちゅう固まるし やっぱ テンプレートをプリコンパイルヘッダにしたのが悪いのかな ・・
301 名前:デフォルトの名無しさん mailto:sage [05/02/07 09:23:19 ] 日記はMeadowにでm(ry
302 名前:デフォルトの名無しさん mailto:sage [05/02/07 09:28:51 ] >>300 ヘッダのインクルード順序を変えてみれ。 自分は面倒なので#ifとか使ってインクルード順序をすぐに変えられるようにしてる。 例: #if 0 //ここを1にしたり0にしたりする。 #include <boost/regex.hpp> #include <algorithm> #else #include <algorithm> #include <boost/regex.hpp> #endif
303 名前:デフォルトの名無しさん mailto:sage [05/02/07 14:42:53 ] Meta-Programming 専用のスレってない?
304 名前:デフォルトの名無しさん mailto:sage [05/02/07 17:41:03 ] あったけど、ここに統合。
305 名前:デフォルトの名無しさん [05/02/11 13:36:27 ] テンプレートを使ったクラスでundefined referenceがでます。 ソースは次のようなものです。プリプロセッサは省略してあります。 //temptest.h template<class T> class temptest{ public: temptest(); }; //temptest.cpp template<class T> temptest<T>::temptest(){} //main.cpp int main(){ temptest<int> t; return 0; } gccでは "undefined reference to `temptest<int>::temptest(void)" VisualC++6では "public: __thiscall temptest<int>::temptest<int>(void)は未解決です" というエラーです。 ちなみに定義をインラインにしたらうまくできました。 どなたか解決方法を教えてください。
306 名前:デフォルトの名無しさん mailto:sage [05/02/11 13:40:12 ] >>305 templateの定義はヘッダに書かないとダメ、ということになってます。
307 名前:304 mailto:sage [05/02/11 13:50:47 ] そんな決まりがあったんですか。 でもSTLのインクルードファイルを見たところ宣言だけのようですが、 STLは特別なんでしょうか。
308 名前:デフォルトの名無しさん mailto:sage [05/02/11 13:52:15 ] STLもヘッダの下のほうに書いてあるんじゃねーの
309 名前:デフォルトの名無しさん mailto:sage [05/02/11 13:52:42 ] STLも例外ではないよ クラステンプレートに実体がなくてもその後ろにクラスメンバのテンプレートの実体が定義されてるはず
310 名前:デフォルトの名無しさん mailto:sage [05/02/11 14:13:29 ] stlportだとcppをヘッダからincludeしてたとおもう
311 名前:デフォルトの名無しさん mailto:sage [05/02/11 14:44:21 ] ヘッダからcppをインクルード・・・萌えるな。
312 名前:デフォルトの名無しさん mailto:sage [05/02/11 15:04:53 ] >>307 temptest.cpp コンパイル時には class T が何だか解らないので コンストラクタは生成されない ↓ main.cpp コンパイル時には temptest<int> のコンストラクタが どこかにあるものとしてコンパイル ↓ リンクしてみたら、どこにもいない 明示的にインスタンス化するよろし。 //temptest.cpp template class temptest<int>;
313 名前:デフォルトの名無しさん mailto:sage [05/02/11 16:01:01 ] exportキーワードをまともに実装した処理系はComeau C++だけでしょ。
314 名前:デフォルトの名無しさん mailto:sage [05/02/11 19:41:42 ] もう諦めてexportを標準から外した方が良いんじゃないかとさえ思ったり. 現状,exportによる利得というのがほとんど無いみたいですし.
315 名前:デフォルトの名無しさん mailto:sage [05/02/11 21:11:04 ] つーか既に実装しなくていいよもう、ってことになったんじゃなかったか?
316 名前:デフォルトの名無しさん mailto:sage [05/02/11 21:50:10 ] >315 ソースきぼんぬ. export周りは泣きそうなほどグダグダみたいですし,さもありなんですけど.
317 名前:デフォルトの名無しさん mailto:sage [05/02/11 22:10:19 ] それがC++クオリティ
318 名前:デフォルトの名無しさん mailto:sage [05/02/12 06:49:19 ] >>316 D&E日本語版読んでみ。 exportは未だに実装してないといけない規格になっている。
319 名前:デフォルトの名無しさん mailto:sage [05/02/12 19:42:14 ] exportって何?
320 名前:デフォルトの名無しさん mailto:sage [05/02/12 19:42:57 ] るby
321 名前:デフォルトの名無しさん mailto:sage [05/02/16 10:47:32 ] shared_ptrとかintrusive_ptrのリファレンスカウント操作って 引数で値渡しすると呼び出しのたびに操作しますよね。 最適化によるコード削減を阻害しないでしょうか? 特にテンプレートを展開したもののコードがどうなるかが気になります。
322 名前:デフォルトの名無しさん mailto:sage [05/02/16 11:26:01 ] >>321 適材適所で。 それからテンプレートの勉強もね。
323 名前:デフォルトの名無しさん mailto:sage [05/02/16 11:38:00 ] >>322 要するにオーバーヘッドはかかるというお答えという理解でよろしい? intrusive_ptrの参照を渡せばいいんですけど、ポインタの置き換えに使うつもり でいるといまひとつ面倒というか泥くさいというか。 あと、これらのコンテナをfor_eachなどで処理するときのbind(+lambda)で、 _1 と書くだけじゃdeductionしてくれず、bind(&HogePtr::get, _1) のようにしないといけないのが面倒で、 これを何とか自動でやってくれるようにする方法はありませんか。 HogePtrという派生クラスを作ってポインタから暗黙的にキャストさせると 一番簡単にコンパイラを黙らせられるんですが、今度はコンテナを処理するときに 毎回HogePtrを作って比較するというコードを出してくるようになるので、 なるべく派生はさせずに済ませたい。
324 名前:デフォルトの名無しさん mailto:sage [05/02/16 20:11:57 ] 参照カウンタによるオーバーヘッドが許せないのなら、 shared_ptr系は精神衛生上使わないほうがいいと思う。
325 名前:デフォルトの名無しさん mailto:sage [05/02/17 00:41:46 ] >>323 bind の件は既に修正済みのはず。
326 名前:デフォルトの名無しさん mailto:sage [05/02/17 14:17:53 ] >>323 恐ろしいことだが君のようなハッカーには それらはもうレガシーだ。boostなのにね。 sandboxにModern C++ Designのを移植した policy_ptrというのがあるので見るべき これはなかなか強烈だよ
327 名前:デフォルトの名無しさん mailto:sage [05/02/18 02:14:48 ] >>326 お前は独逸の詩人かよ!?
328 名前:デフォルトの名無しさん [05/02/18 12:12:10 ] >>326 ポリシーベースの派、前に検討して却下してshared_ptr達が採用されたのに なんで今更?
329 名前:デフォルトの名無しさん mailto:sage [05/02/18 20:40:47 ] >328 その議論読んでみたいんですがどこにありますか? policy_ptrは「shared_ptrは重い」といった主張を持つユーザに対する 選択肢の一つとして提供されるのだと思いますよ. そもそもpolicy_ptrはshared_ptrなどの既存のスマートポインタに取って代わるものではなく, むしろそれらと相補関係にあって共存するべきものですし. なのでshared_ptrを"legacy"と表現するのは恐らく適切ではないです. ここら辺のもう少し詳しい議論は以下のスレッドや policy_ptrのドキュメントのFAQあたりが参考になると思います. thread.gmane.org/gmane.comp.lib.boost.devel/116983
330 名前:デフォルトの名無しさん mailto:sage [05/02/18 21:19:44 ] 似たような*_ptrばっか増やして、 馬鹿じゃないの? ふざけてるの?
331 名前:328 mailto:sage [05/02/18 21:23:27 ] >>329 boost.cppll.jp/HEAD/libs/smart_ptr/shared_ptr.htm#FAQ の2番目を。
332 名前:デフォルトの名無しさん mailto:sage [05/02/18 23:38:55 ] >>330 C++ ってそういうもんだよ。人によって用途も違えば、実行環境のリッチさも 天と地ほど違うので。
333 名前:デフォルトの名無しさん mailto:sage [05/02/22 15:00:52 ] 新規にクラスを作るならば、COM のように侵入型の参照ポインタにして、 intrusive_ptr で管理するとか
334 名前:デフォルトの名無しさん mailto:sage [05/02/22 17:27:12 ] STLかboostあたりに、ある条件を満たすものをoutput_iteratorにコピー するような関数はないでしょうか? boost::mplにcopy_ifというそれらしい名前のがあるんですが、 使い方がさっぱりわからない……
335 名前:デフォルトの名無しさん mailto:sage [05/02/22 17:40:29 ] なぜか std に copy_if ないんだよね・・・ boost::filter_iterator と std::copy でなんとか汁
336 名前:デフォルトの名無しさん mailto:sage [05/02/22 17:43:19 ] std::remove_copy_if(first, last, std::not1(pred));
337 名前:336 mailto:sage [05/02/22 17:43:58 ] ごめん。 std::remove_copy_if(first, last, out, std::not1(pred); だ。
338 名前:デフォルトの名無しさん mailto:sage [05/02/22 18:06:02 ] 今回は元のコンテナを変更したくないのでremove_copy_ifは使えなさそうです。 結局自分で書きました。 自分でforループを書くと頭悪くなったように感じるので、 これくらいstdに入れておいてほしいものです……。 template <class InputIterator, class UnaryFunction, class OutputIterator> void copy_if(InputIterator begin, InputIterator end, OutputIterator result, UnaryFunction pred) { for ( ; begin != end; ++begin) if (pred(*begin)) { *result = *begin; ++result; } } g++のヘッダを見るとconcept checkとやらを入れたほうがいいらしいのですが、 何を使えばいいのかよくわからんです。boostに道具があるんでしょうか。 remove_copy_ifも説明がよくわからんのですよね。 削除するのに大きさが変わらないってどういうこと?
339 名前:デフォルトの名無しさん mailto:sage [05/02/22 18:06:58 ] >>338 remove_copy_ifは入力シーケンスを変更しないよ。
340 名前:デフォルトの名無しさん mailto:sage [05/02/22 18:17:58 ] >>338 return result;
341 名前:一つ賢くなった! mailto:sage [05/02/22 18:32:43 ] >>339 おお、本当だ。コードを見るとほぼそっくりではないですか。 今までremove_copy_ifは元のを破壊的に変更しつつ、削除したものを コピーするのだと思っておりました。 名前がミスリーディングだと思うのです……。 >>340 忘れてました。というか気にしてなかったのですが、返すべきですね。
342 名前:デフォルトの名無しさん mailto:sage [05/02/22 19:24:56 ] struct NURUPO { template<typename T> operator T*() { return 0; } }; int ILoveNurupo() { NURUPO mynurupo; return (int)mynurupo[0]; } vc7.1とgcc3.3にガッ
343 名前:デフォルトの名無しさん mailto:sage [05/02/22 21:10:19 ] なんか違わないか?
344 名前:デフォルトの名無しさん mailto:sage [05/02/23 01:38:28 ] >>338 STLPortには入ってるよ。
345 名前:デフォルトの名無しさん mailto:sage [05/02/24 14:00:35 ] テンプレートの特殊化ってどこに書きますか? 以下のように特殊化する型の定義と一緒に書くと、 * primary.h #include <iostream> template <class T> inline void foo(const T&) { std::cout << "primary\n"; } --- * specialized.h #include "primary.h" struct bar {}; template <> inline void foo(const bar&) { std::cout << "specialized\n"; } --- * troublesome.h struct bar; bar& get_bar();
346 名前:345 mailto:sage [05/02/24 14:01:58 ] * troublesome.cpp #include "specialized.h" bar& get_bar() { static bar b; return b; } void trouble1() { foo(get_bar()); // #1 } --- * main.cpp #include "primary.h" #include "specialized.h" // #2 #include "troublesome.h" int main() { foo(get_bar()); return 0; } --- #1 と #2 をコメントアウトしたりしなかったりで実行結果が変化します。 具体的には #1 と #2 の両方をコメントアウトした場合 primary が出力されます。 かといって、極端な話 STL のヘッダファイルに書き足すわけにもいけませんし・・・。
347 名前:デフォルトの名無しさん mailto:sage [05/02/25 00:39:40 ] >>345 ttp://www.kuzbass.ru/docs/isocpp/template.html#temp.expl.spec 14.7.3 -6- および -7- で、 使う場所より前に特殊化は宣言されていないといけない、 というルールは書いてあるが、コンパイラによるチェックは不要ということになっている。 あげくに規格中に「宣言の位置には気をつけろ」と書かれている。 primary.h の foo<T> の中でダミーでいいから sizoef(T) を使って、 不完全型ではインスタンス化できないようにしておけば、 いちおうエラーにすることができると思う。
348 名前:デフォルトの名無しさん mailto:sage [05/02/28 11:44:49 ] template<class T> class A { public: void hoge() { } void foo() { } // 他にいろいろなメンバがある }; というクラステンプレートがあって、プログラム中でA<T>::hogeだけどこからも使われなかったとき A<T>::hogeのコードは生成されるのでしょうか?
349 名前:デフォルトの名無しさん mailto:sage [05/02/28 12:01:34 ] >>348 されない。だから定義しなくても大丈夫。
350 名前:デフォルトの名無しさん mailto:sage [05/02/28 19:22:11 ] >>348 処理系依存
351 名前:デフォルトの名無しさん mailto:sage [05/02/28 21:47:50 ] >>350 ほんと?
352 名前:デフォルトの名無しさん mailto:sage [05/02/28 22:10:33 ] 一応標準としてはAの暗黙のインスタンス化ではhogeはインスタンス化されません.(14.7.1/1) ちなみにAの明示的インスタンス化の際にはhogeのインスタンス化が伴います.(14.7.2/7)
353 名前:デフォルトの名無しさん mailto:sage [05/02/28 22:10:41 ] >350は狼少年
354 名前:デフォルトの名無しさん mailto:sage [05/03/01 22:32:51 ] >>348 Modarn C++ Designの1.8に、生成されないことを前提にした技法があったな確か。 シンタックス・チェックだけは、実装によっては行われるんだったっけか。
355 名前:デフォルトの名無しさん mailto:sage [05/03/02 01:29:19 ] Modern ね
356 名前:デフォルトの名無しさん mailto:sage [05/03/02 12:31:04 ] スマソ
357 名前:デフォルトの名無しさん mailto:sage [05/03/08 02:55:11 ] AdobeのASLもここでいいんかな?
358 名前:デフォルトの名無しさん mailto:sage [05/03/08 10:23:35 ] 使われているプログラミング技法を語るならここかな あるいはBoostスレか
359 名前:デフォルトの名無しさん mailto:age [05/03/09 18:17:53 ] 以下のコードで complex を set に入れようとしたところ、 「stl_function.h:197: error: no match for 'operator<' in '__x < __y'」 とか言われてしまうのですが (g++ 3.3.3)、原因が分かりません。 何がおかしいのでしょうか。 #include <complex> #include <set> using namespace std; bool operator<(const complex<int> &a, const complex<int> &b) { return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b)); } int main() { set<complex<int> > s; s.insert(complex<int>(1, 2)); return 0; }
360 名前:デフォルトの名無しさん mailto:sage [05/03/09 18:39:00 ] >>359 <set>の中からそのoperator<()が見えていない。しかしoperator<()を #includeよりも前に持ってくると今度はcomplexが定義されていない。 しかしstd名前空間内部のものを先行宣言することは許されていない。 自分で関数オブジェクトを定義するしかない。
361 名前:デフォルトの名無しさん mailto:sage [05/03/09 18:40:16 ] namespace std { bool operator<(const complex<int> &a, const complex<int> &b) { return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b)); } } で通ったけど、これってやっていいことだっけ……?
362 名前:デフォルトの名無しさん mailto:sage [05/03/09 18:56:02 ] >>360 > <set>の中からそのoperator<()が見えていない。 これは関係ない。どうせグローバルのoperator<は使われない。
363 名前:デフォルトの名無しさん mailto:sage [05/03/09 19:00:21 ] >>361 結論:ダメ 宣言や定義をstd名前空間に加えてはならない。今回の場合、struct std::less<>の特殊化も考えられるが、後述の規定によりuser-definedな名前で 特殊化しない限りundefined behaviorとなる。 17.4.3.1 Reserved names -1 It is undefined for a C++ program to add declarations or definitions to namespace std or namespaces within namespace std unless otherwise specified. A program may add template specializations for any standard library template to namespace std. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user-defined name of external linkage and unless unless the specialization meets the standard library requirements for the original template.
364 名前:デフォルトの名無しさん mailto:sage [05/03/09 19:17:37 ] >>362 #include <set> using namespace std; struct hoge{int x;}; bool operator<(const hoge& a, const hoge& b){return a.x < b.x;} int main(){ set<hoge> s; s.insert(hoge()); return 0; } これ通らない?
365 名前:デフォルトの名無しさん mailto:sage [05/03/09 21:08:49 ] >364 それはhogeとoperator<が同じ名前空間(グローバル)で定義されているので通りますよ. std::complexを引数とする呼び出しからoperator<が見えるためには operator<がstd名前空間で定義されていないといけないです. でもそのような定義をstd名前空間に追加することは許されないので(>363), 自分で関数オブジェクトを書いて(>360)それをsetのテンプレート引数に与えるしかないです.
366 名前:デフォルトの名無しさん mailto:sage [05/03/09 21:12:46 ] で、結局こう、と。 #include <complex> #include <set> using namespace std; template <typename T> struct complex_less: binary_function<complex<T>, complex<T>, bool> { bool operator() (const complex<T>& a, const complex<T>& b) { return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b)); } }; int main () { set< complex<int>, complex_less<int> > s; s.insert(complex<int>(1, 2)); return 0; }
367 名前:359 mailto:sage [05/03/09 21:25:39 ] >>360-366 皆さんありがとうございます。よく分かりました。 ちゃんと勉強しないとダメだなぁ〜 orz
368 名前:デフォルトの名無しさん mailto:sage [05/03/09 21:55:23 ] string とか pair が std 名前空間に operator < を定義しているから ADL のせいで operator < を std 名前空間の外に探しに行かないという認識であってますか?