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 あたりに。
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; }