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 あたりに。
697 名前:693 mailto:sage [2005/06/14(火) 18:57:55 ] 言い方が不正確だったな。 規格には、「メンバ関数は、その定義が必要とされるとき実体化される(意訳)」とある。 で、virtual関数については、いつ「定義が必要とされる」か正確に規定している部分が(俺の見た限りでは)なかった。 従って、virtual関数の正確な実体化のタイミングは規定されていないことになる。 それでも、「必要」になり次第実体化されることは保障される。
698 名前:688 mailto:sage [2005/06/14(火) 19:22:06 ] あー、なるほど。 規定されていないのは実体化されるタイミングだということですね。 どうもありがとうございました。
699 名前:デフォルトの名無しさん mailto:sage [2005/06/26(日) 18:25:16 ] int k = 0; for (vector< set<int> >::iterator it = v.begin(); it != v.end(); ++it) it->insert(k++); を boost::lambda か何かを使って for_each でシンプルに書けませんか? メンバー関数に bind する仕方がよく分からないんですが・・・
700 名前:デフォルトの名無しさん mailto:sage [2005/06/26(日) 19:33:36 ] >>699 typedef std::set< int > set_type; typedef std::vector< set_type > vector_type; void f( vector_type& v ) { using namespace boost::lambda; int k = 0; std::for_each(v.begin(), v.end(), (protect(bind((std::pair<set_type::iterator,bool> (set_type::*)(int const&))(&set_type::insert), _1, var(k)++)))(*_1)); } ○ boost::lambda か何かを使って ○ for_each で × シンプルに
701 名前:700 mailto:sage [2005/06/26(日) 19:49:39 ] メンバ関数に限らず、オーバーロードが絡むと lambda は使いにくいな。
702 名前:デフォルトの名無しさん mailto:sage [2005/06/27(月) 06:52:07 ] protect要るか? >>701 C++は名前が重なった場合の簡潔な指名定方法がないしね。 lambdaに限らず面倒。 typeofがBoostに入るそうだから、そのうち頑張って改善されるといいな。
703 名前:700 mailto:sage [2005/06/27(月) 07:50:29 ] >>702 こんな感じで変形していったが、途中のやつの エラーメッセージがひどくて(数100行ぐらい出る)、 何がまずかったのかよくわかってない。 × ((*_1)->*insert)(var(k)++) × bind(insert, *_1, var(k)++) ○ (protect(bind(insert, _1, var(k)++)))(*_1)
704 名前:702 mailto:sage [2005/06/27(月) 22:11:02 ] >>703 その3つの最初から間違ってるよ。 for_eachなんだから_1にはイテレータではなく参照が入る。よって _1をdereferenceする必要はない。 まあ同じなんだけど、俺ならオーバーロードが絡む場合は メンバ関数の特定を追い出すかな。 void hoge(vector<set<int> >& v) { typedef set<int> set_type; pair<set_type::iterator,bool>(set_type::*insert)(const int&) = &set_type::insert; int k = 0; for_each(v.begin(), v.end(), bind(insert, _1, var(k)++)); }
705 名前:700 mailto:sage [2005/06/28(火) 00:20:42 ] >>704 うわ、とんでもない勘違いをしていたよ。 ありがとう。
706 名前:デフォルトの名無しさん mailto:sage [2005/07/05(火) 14:15:55 ] ttp://d.hatena.ne.jp/soleil/searchdiary?word=%2a%5b%c5%fd%b7%d7%5d ここに書いてあった struct Mean ってどう使うの? 例がないと分からない functorなのは分かったけど
707 名前:デフォルトの名無しさん mailto:sage [2005/07/05(火) 14:27:54 ] int array[] = {1, 3, 5}; std::vector<double> v = ...; int ma = Mean<int *>()(array, array + 3); double mv = Mean<std::vector<double>::iterator>()(v.begin(), v.end()); こんな感じじゃないか?
708 名前:デフォルトの名無しさん mailto:sage [2005/07/05(火) 16:19:10 ] for_eachにかけるものではないのね でも便利そう thx
709 名前:デフォルトの名無しさん mailto:sage [2005/07/05(火) 16:25:40 ] >>707 のとおりにやってみたけど コンパイル通らなかったよ
710 名前:デフォルトの名無しさん mailto:sage [2005/07/05(火) 17:04:14 ] >>706 > 算術平均を求める Mean を書き直すと以下のようになる > (もちろん Sum も反復子を使うように変更してあることが前提) ちゃんとSumもコード書いた? んで、漏れなら、合計値(累積値)を求めるアルゴリズムaccumulateを使い 平均値は: void f(vector<double>& m) { double avg = accumulate(m.begin(), m.end(), 0.0) / m.size(); } のようにして求めるな。分散・標準偏差、RMSあたりも似たような実装ができる。
711 名前:デフォルトの名無しさん mailto:sage [2005/07/06(水) 04:42:18 ] >>710 わざわざ関数にするのか? コードの大きさを抑えるのにはいいけど。
712 名前:デフォルトの名無しさん mailto:sage [2005/07/06(水) 07:22:20 ] >>711 しない。入力が何で出力が何か明確にしたかったので、関数形式で書いただけ。 実際に関数にするなら、template、inline、引数にはconst、戻値の型を明記、あたりが必要です。 蛇足で糞コード晒す。 template <typename T> struct square : public binary_function<T, T, T> { T operator()(const T& lhs, const T& rhs) { return lhs + rhs*rhs; }; }; double ms = accumulate(m.begin(), m.end(), 0.0, square<double>()) / m.size(); double rms = sqrt(ms); double stdev = sqrt(ms - avg*avg);
713 名前:デフォルトの名無しさん mailto:sage [2005/07/06(水) 08:07:25 ] STLは連続した、同じような事の繰り返し処理には滅法強いな。
714 名前:デフォルトの名無しさん mailto:sage [2005/07/06(水) 20:49:48 ] >>713 あなたの人生もSTLで簡単になりますよ。 void silly_life(life& your_life) { struct { static int daily(day& d) { d.nebou(); d.nichan(); d.onanu(); d.shigoto(); d.nichan(); d.onanu(); d.neru(); return 0; } }; std::for_each(your_life.begin(), your_life.end(), daily); } 久しぶりにtemplate見たよ。。。C#使いづれ〜。。。orz
715 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 00:00:05 ] それがSTLクオリティ。 語呂悪いな。
716 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 07:31:19 ] 速度が重要になるコードを書かなければなのですが、 やはりSTL経由の連続処理は、速度的に不利なんでしょうか? 一応自分なりに、次レスに書いたような実験をしてみたのですが、 プロファイル結果はSTL版hoge()が平均301msに対し、 シンプルなリストhage()の方が平均12msと、圧倒的な差に…。 今更自前リストなんて使うのは、考えただけで頭が痛くて。 なにかテストに落ちがないか、 或いはSTL版速度向上のための抜け道が無いか、教えて頂けないでしょうか。
717 名前:714 行制限のため、見づらくてすいません mailto:sage [2005/07/07(木) 07:35:09 ] #include <list> struct simple_list{ int val; simple_list* next; }; template <typename T> void hoge( T first, T last ){ int sum = 0; while( first != last ) sum += *(first++); }; void hage( simple_list* sl_first ){ int sum = 0; while( sl_first ){ sum += sl_first->val; sl_first = sl_first->next;} }; int main(){ std::list<int> listInt; for( unsigned long i=0; i < 100000; ++i ) listInt.push_back(i); simple_list* sl_first = new simple_list; simple_list* sl = sl_first; for( unsigned long c=0; c < 100000; ++c ){ sl->val = c; sl->next = new simple_list; sl = sl->next; } sl->next = NULL; hoge( listInt.begin(), listInt.end() ); hage( sl_first ); while( sl_first ){ sl = sl_first->next;delete sl_first; sl_first = sl; } return 0; }
718 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 07:51:04 ] >>716 プロファイルでは最適化は有効にしてる? 最適化しないと比較にならないし、最適化すると hoge(), hage() が sum を返してないので、最適化で処理自体が消えてダメかもしれない。 hoge の sum += *(first++); を { sum += *first; ++first } にすると、少し違うかもしれない。
719 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 07:51:41 ] >>716 最適化した? うちじゃ hoge(): 8.46567 ms hage(): 7.92051 ms くらいなんだけど 環境はg++ (3.3.5)
720 名前:716 mailto:sage [2005/07/07(木) 08:08:12 ] 我ながら非道い sl->next = NULL;を削って sl->next = new simple_list; を sl->next = (c != 100000-1) ? new simple_list : NULL; とでも >>718-719 最適化をすっかり忘れていました。 なぜだかsumを返すようにしてもhogeの方が消えてしまうのですが もう少し試行錯誤してみます。 いずれにせよ力づけられました。ホッとしています。 レスありがとうございました。
721 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 08:20:05 ] >>720 返すだけで戻り値を使ってないんじゃ、と消えるかもしれないな。 チェックもかねて、画面に値を出すようにすれば大丈夫じゃない? (そこまでやっても、ただの定数に置き換えてしまうコンパイラとかあるかもしれない。) 最終的にはアセンブリを吐かせて確認するといい。
722 名前:716 mailto:sage [2005/07/07(木) 08:25:49 ] 最適化無しで719さんの方法で15%ほど速く >>721 もしかしたらtemplateだったせいかも知れないです。インライン化されていたのかな。 templateを外したらhogeも出ました hoge: 5.579 ms hage: 5.313 ms (vc++6) 朝からお騒がせしました、お二人(三人?)に再度感謝です
723 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 08:31:10 ] その程度の処理だとlistは兎も角、vectorは普通の配列と全く同じ速度出るよ。 #つーか、gccでもVC++でもstlの有無で全く同じ(質の)コード吐くんだけどね。
724 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 18:13:33 ] >>723 VCだと vector>=配列 になるときもない?(誤差範囲内だけど) GCCは vector使うと少し遅くなる気がした。
725 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 18:23:22 ] その辺は具体的なコードを提示して比較でもしない限りなんとも言えないなぁ。 そもそも最適化で消えないコードでって条件になっちゃうし。
726 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 18:30:29 ] vectorのiteratorは大抵の処理系/STL実装で非デバッグ時には単なるポインタだろ。
727 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 18:34:16 ] >>722 ちなみに std::list が double-linked list だということは知ってるよな
728 名前:デフォルトの名無しさん mailto:sage [2005/07/07(木) 23:52:14 ] doubleじゃないSTLのlistを提示しない限りそのレスは無意味
729 名前:デフォルトの名無しさん mailto:sage [2005/07/08(金) 00:55:24 ] >>728 おれは>727じゃないけど、なんで?
730 名前:デフォルトの名無しさん mailto:sage [2005/07/08(金) 01:02:35 ] そういえばslistは標準じゃないんだな。 STLPortにはあるけど。
731 名前:デフォルトの名無しさん mailto:sage [2005/07/08(金) 20:43:04 ] 次のようなコードがあるとします: struct base1 { base1(int x) {}; }; struct base2 { base2(int x, int y) {}; }; // IF<P,T,F>クラステンプレートは、Pが非0のときT、0のときFをIF::typeにtypedefする template <int N> struct derived : public IF<N,base1,base2>::type {}; このとき引数の数が異なるコンストラクタを持つ基底クラスをテンプレートで切り替え、 派生クラスのコンストラクタから、基底クラスのコンストラクタを呼び出したいのです: derived<1> d(0); // base1から継承し、コンストラクタは引数1 derived<0> d(0, 1); // base2から継承し、コンストラクタは引数2 基底クラスのコンストラクタを呼び出すときには、派生クラスの初期化リストを使います。 ところが、派生クラスのコンストラクタ初期化リストでは、基底クラスのコンストラクタ 以外呼べませんから、次のように多重定義できません: // Nが非0だとすると derived(int x) : base1(x) {}; derived(int x, int y) : base2(x, y) {}; // error! 基底クラスはbase1 このように基底クラスをテンプレートで替える場合に、うまく派生クラスのコンストラクタの 引数の数を調整するようなテクニックがあれば、ご教示いただけると幸いです。 また、異なるアプローチもあればコメントください。
732 名前:デフォルトの名無しさん mailto:sage [2005/07/08(金) 20:50:10 ] 俺にはderivedをNの値によって特殊化する方法しか思いつかない。
733 名前:デフォルトの名無しさん mailto:sage [2005/07/08(金) 22:22:17 ] 試しにこう書いてみたら g++ 3.4.4 cygming special では通ったんだが。 derived(int x) : IF<N,base1,base2>::type(x) {} derived(int x, int y) : IF<N,base1,base2>::type(x,y) {}
734 名前:731 mailto:sage [2005/07/09(土) 02:41:09 ] >>732-733 レスありがとうございました。 >733の方法で、パパ、うまくできそうです。 続きがんばります!
735 名前:デフォルトの名無しさん mailto:sage [2005/07/09(土) 08:17:21 ] どうもネットの世界の「ご教示」とか「ご教授」って浮いた言葉だなぁ。
736 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 00:59:18 ] 実は初めてこの構文を知ったんだけどさ >ttp://www.comeaucomputing.com/techtalk/templates/#esprobs > >template <class T> >T foo(T blah) >{ > xyz object; > T someInt; > >// (略) > > someInt = object.mt<int>(99.99); // AA: ill-formed > someInt = object.template mt<int>(99.99); // BB: well-formed > > return someInt; >} ってなってて AA は ill-formed になってるんだけど、 object はテンプレートパラメータに依存してないんだから template をつけなくても問題ないと思うんだけど。実際 g++ 3.4.4 だと通るし、. の前をテンプレートパラメータに 依存するように書き換えるとエラーが出る。 規格参照箇所 14.2-4 > When the name of a member template specialization appears after . or -> in a postfix-expression, or after > nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a > template-parameter (14.6.2), the member template name must be prefixed by the keyword template. > Otherwise the name is assumed to name a non-template.
737 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 02:07:52 ] template <typename T> class Hoge { public: typedef std::vector<T> Container; typedef Container::iterator Iterator; private: Container v; }; と書いて、Hoge<int> hoge; とか呼ぶと、implicitなtypenameだと警告を言われます。 iteratorを表現するにはどのように記述すべきなのでしょうか。
738 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 02:09:19 ] >>737 gcc version 3.2 20020927 (prerelease) です。
739 名前:737 mailto:sage [2005/07/10(日) 02:11:47 ] www.tietew.jp/cppll/archive/10073 によると、 typename Container::iterator Iterator; と書くみたいですね。これって常識なのかしら。
740 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 02:27:11 ] >>739 その場合、typenameは必須。
741 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 02:36:16 ] 常識
742 名前:デフォルトの名無しさん mailto:sage [2005/07/10(日) 04:36:52 ] 当然
743 名前:デフォルトの名無しさん mailto:sage [2005/07/11(月) 10:24:40 ] >>739 特殊化があるC++では、Tが確定しないと型推論が困っちゃうんで、 typedef typename Container::iterator Iterator; って感じで。 typename Container::iterator Iterator; も可能。 Container<int> v; なら何とかなるはずだけど、explicitにtypenameしましょうという仕様。
744 名前:デフォルトの名無しさん mailto:sage [2005/07/16(土) 20:53:42 ] >型推論が困っちゃう そうなのか? Tが確定しないと、特殊化のあるC++ではstd::vector<T>::iteratorが typedefされた型名か、メンバ(メンバ変数・関数)かが分からないから コンパイラへのヒントとして型名であることを明示するのを義務付けてるんでは?
745 名前:デフォルトの名無しさん [2005/07/19(火) 22:11:08 ] 全然わかってないけど質問します。 テンプレートクラスの実装って全てヘッダーでやらないといけないんですか? .cppの方でやるとリンカーエラーが出てリンクできないのですが!? (全部ヘッダーにコピペしたら通った)
746 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 22:14:53 ] 追加 だが、しかしそれをやると2重定義になる… どうすればいいんじゃーーーー
747 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 22:20:05 ] >>745 テンプレートの定義をcppファイルに書きたければ、宣言と定義の両方にexportを付けるだけ。 しかしほとんどのコンパイラで使えない。(使えるコンパイラが全くないわけではない) というわけで普通はヘッダにインラインで全て書く。 ごく稀に明示的実体化が使われることはあるが。
748 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 22:48:35 ] >>747 明示的実体化ってまさか、 template class c<bool>; template class c<char>; template class c<unsigned char>; みたいに延々と cpp ファイルに書いていくわけ?
749 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 23:06:05 ] g++にはextern templateってのがあるね。
750 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 23:11:50 ] >748 そゆこと。
751 名前:745 mailto:sage [2005/07/19(火) 23:17:21 ] やってみた>>747 make -k all g++ -Wall main.cpp Class.cpp -c g++ -Wall main.o Class.o -o a.exe main.o(.text+0x25):main.cpp: undefined reference to `Class<int>::Class[in-charge]()' collect2: ld returned 1 exit status make: *** [all] Error 1 ムリポ >>749 を含めて出直してくる。これはイマの私の頭ではいくら考えても答えが出ない。 本を読むかg++のマニュアルを漁るか…
752 名前:デフォルトの名無しさん mailto:sage [2005/07/19(火) 23:44:58 ] >>751 g++のinclude/bits/istream.tccより // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. #if _GLIBCPP_EXTERN_TEMPLATE extern template class basic_istream<char>; extern template istream& ws(istream&); extern template istream& operator>>(istream&, char&); extern template istream& operator>>(istream&, char*)
753 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 19:33:12 ] template <class T> class foo; template <class T> class baa{ friend foo; int n; public: baa() : n(777){} }; template <class T> class foo : public baa<T>{ int hoge; public: void set_val( baa<T>& arg ){ hoge = arg.n; } }; int main(){ baa<int> b; foo<int> f; f.set_val( b ); return 0; } インデントが全角スペースですいません これだとarg.nにアクセス出来ないのですが、間違っている場所を教えて頂けないでしょうか friend foo; が、やっぱり template <class T> friend foo; なんでしょうか
754 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 19:45:24 ] >>753 g++ でコンパイルすると、 :4: error: ISO C++ forbids declaration of `foo' with no type :4: error: `foo' is neither function nor member function; cannot be declared friend まぁそれは置いとくとして、 friend class foo<T>; で通ったよ。
755 名前:753 mailto:sage [2005/07/23(土) 19:59:42 ] >>754 やっぱりclass指定しますよね 書き込む前にチェックしたサイトで、指定が無かったので、自分が間違っていたのかと そうか、再度template <class T>付けるのは馬鹿でした。 VC6なので、Tが同じじゃなかったらアウトだったかも・・・良かった。 本当に助かりました。コンパイルまでして頂いてすいません。ありがとうございました。
756 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 20:13:13 ] baaっての…なんかプログラムがアホっぽくなるな。
757 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 22:22:39 ] >>755 friend かどうかっていう問題なのか? baa<T>::n が private か protected/public かどうかっていう問題では?
758 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 22:47:57 ] >>757 vtableを避けるための小細工なんです 眉をしかめる人が多いと思いますが、自分しか使わないのでお見逃しを
759 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 23:36:56 ] >>758 よくわからないな。>>753 のを template <class T> class baa{ protected: int n; public: baa() : n(777){} }; とすると VC6 だと vtable に関して状況が変わるの?
760 名前:デフォルトの名無しさん mailto:sage [2005/07/23(土) 23:51:14 ] 753がprotectedを知らなかったというオチ?
761 名前:デフォルトの名無しさん mailto:sage [2005/07/24(日) 00:21:24 ] >>759 失礼、深読みしすぎてました。 しかしすいません、そうなると>>757 で頂いたレスの意図が分からないです。 protectedすると、引数で他のbaaを受け取ったとき、nにアクセス出来るのでしょうか。
762 名前:760 mailto:sage [2005/07/24(日) 00:40:00 ] 753のコードでは、bar<T>::nがprotectedならfoo<T>::set_valの中でarg.nにアクセスできると思っていたがそうではなかったようだ。 スマソ
763 名前:デフォルトの名無しさん mailto:sage [2005/07/24(日) 01:03:17 ] >>761 アクセスできると思ってた。けど間違ってたのなら失礼。 ・基本 class から 派生 class を public 継承したとき、 ・基本 class の protected member である n について、 ・派生 class から this の n にアクセスできる。 ・派生 class から this 以外の n にアクセスできない。 ということかな?も一回勉強しなおそ。 ・ある class の private member である n について、 ・その class から this の n にアクセスできる。 ・その class から this 以外の n にアクセスできる。 というのは間違いないと思うんだけど。 あと自分の VC7 は、これに関して template class かそうでないかによって コンパイル結果が違うのもよくわからない。
764 名前:デフォルトの名無しさん mailto:sage [2005/07/24(日) 02:17:54 ] 勉強しなおした。>>763 は間違い多数につきスルーよろしく。失礼しますた。
765 名前:デフォルトの名無しさん mailto:sage [2005/07/28(木) 18:38:46 ] Compile-time if で型でなく値を返すにはどうすればいいのでしょうか? int v= boost::mpl::if_c< (sizeof(T) <= sizeof(double)), 10, 20 >::Value はだめでした
766 名前:デフォルトの名無しさん mailto:sage [2005/07/28(木) 19:41:12 ] >>765 boost::mpl::int_ を使って、型にマップすればいい。
767 名前:デフォルトの名無しさん mailto:sage [2005/07/28(木) 19:56:38 ] >>765 struct R0 { enum {value = 10}; }; struct R1 { enum {value = 20}; }; template <typename T> int func () { typedef typename boost::mpl::if_c <(sizeof (T) <= sizeof (double)), R0, R1>::type Result; return Result::value; }
768 名前:デフォルトの名無しさん mailto:sage [2005/07/29(金) 10:42:43 ] template<CONTANER> class CmyContaner { typedef CONTANER::iterator iterator_type; }; としたらコンパイル通らなかったんですが、 CONTANER::iteratorはできないってことなのでしょうか?
769 名前:デフォルトの名無しさん mailto:sage [2005/07/29(金) 11:35:24 ] >>768 -typedef CONTANER::iterator iterator_type; +typedef typename CONTANER::iterator iterator_type;
770 名前:デフォルトの名無しさん mailto:sage [2005/07/29(金) 15:37:41 ] そのままじゃ型名かメンバ変数かわからんからね。 > CONTANER 北斗の拳の主題歌を思い出すスペルミスだな。
771 名前:デフォルトの名無しさん mailto:sage [2005/07/29(金) 16:46:27 ] >>768 ここもだね -template<CONTANER> +template<typename CONTANER>
772 名前:デフォルトの名無しさん [2005/07/30(土) 08:40:48 ] template<Functor> class MyMethod { public: Functor f_ MyMethod(Functor f):f(f_) {} value() { f_(10); } }; class MyClass { public: struct MyFunctor{ operator()(int a) { std::cout << a; }myFunc; //MyMethod<MyFunctor> myMethod(myFunc);//コンパイル通らない MyMethod<MyFunctor> myMethod(MyFunctor);//なぜかコンパイル通る value(){ myMethod.value();//左側がクラス 構造体 共用体でありません と怒られる } }; クラスの中でfunctorを定義したら動かなくなりました。 回避方法はないのでしょうか?
773 名前:デフォルトの名無しさん mailto:sage [2005/07/30(土) 09:48:49 ] >>772 >クラスの中でfunctorを定義したら動かなくなりました。 クラスの外でfunctorを定義したらそれ動く?
774 名前:デフォルトの名無しさん mailto:sage [2005/07/30(土) 13:47:17 ] >772 とりあえず } が 1 個足りない。 } myFunc; の前に 1 個ある、でいいのか? >MyMethod<MyFunctor> myMethod(MyFunctor); これだと MyFunctor 型の引数をとり、MyMethod<MyFunctor> 型を返すメンバ関数 myMethod を 宣言しているんじゃまいか? >//MyMethod<MyFunctor> myMethod(myFunc);//コンパイル通らない なんでメンバ変数を宣言してるのに初期化しようとしてるの? MyMethod<MyFunctor> myMethod; MyClass() : myMethod(myFunc) {} じゃねーのか?あと↑だと myFunc との初期化順序が問題になる場合があるかも。 今回の場合、MyClass() : myMethod(MyFunctor()) でいいような気もするが。
775 名前:772 [2005/07/30(土) 14:59:26 ] すみません } が1つぬけてました。 template<Functor> class MyMethod にclass の外で定義したfunctorを使うと 意図したとうりの動きをすることを確認しています。
776 名前:デフォルトの名無しさん mailto:sage [2005/07/30(土) 15:06:57 ] >>775 >class の外で定義したfunctorを使うと >意図したとうりの動きをすることを確認しています。 本当に? コピペにかなりミスがあると思うよ MyMethod::value() MyClass::MyFunctor::operator()(int a) の返値の型は? もし本当に動くなら処理系を教えてね
777 名前:776 mailto:sage [2005/07/30(土) 15:09:07 ] たぶんこんなことしたいのかな template <typename Functor> struct MyMethod { Functor f_; MyMethod (Functor f): f_(f) {} void value () {f_ (10);} }; struct MyClass { struct MyFunctor { void operator () (int a) { std::cout << a; } } myFunc; MyMethod <MyFunctor> myMethod; MyClass (): myFunc (), myMethod(myFunc) {} void value() {myMethod.value();} };
778 名前:デフォルトの名無しさん mailto:sage [2005/08/02(火) 22:23:20 ] template<X> class CHoge {public: CHoge( X= typeof(x) ) {} }; なんてできないの? 自動で型判別してほしい。 自動判別した型を使ってCompile-time Ifもできるとさらにいいんだけど
779 名前:デフォルトの名無しさん mailto:sage [2005/08/02(火) 23:18:35 ] >>778 >自動で型判別してほしい。 >自動判別した型を使ってCompile-time Ifもできるとさらにいいんだけど これらはできるけど 例で何がしたいのかさっぱり分かりません
780 名前:デフォルトの名無しさん mailto:sage [2005/08/05(金) 23:15:18 ] template< ArrayType > function( ArrayType array) { Compile-time If (ArrayType はポインタの配列?) { int a= array[0]->value; }else{ int a= array[0].value; } こんなことがしたい
781 名前:デフォルトの名無しさん mailto:sage [2005/08/05(金) 23:30:47 ] type_traitsでいいんじゃないの?
782 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 00:52:15 ] 個人的には値の配列とポインタの配列を静的多相に扱おうとする行為そのものに 異議を申し立てたい.
783 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 02:36:31 ] 次のようなコードが、Visual C++では通るけどGCCでは通りません。 オブジェクトの名前と番号の型を保持する構造体を用意 template<class S,class I> struct Types { typedef S String; typedef I Integer; }; この定義を受け取って型を定義するベースクラスを作成 template<class T> struct Base { typedef typename T::String StringType; typedef typename T::Integer IntegerType; }; そして、これを利用するサブクラスを作成。 template<class T> struct Derived : public Base<T> { StringType name; //!< ここでコンパイルエラー IntegerType number; //!< 同様 }; typedef Types<std::string,int> StdTypes; Derived<StdTypes> derived;
784 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 02:38:23 ] 続き 以下のように書けばGCCでもコンパイルは通ります。 typename Derived::StringType name; typename Derived::IntegerType number; こんな面倒な書き方しかできないなら、 わざわざベースクラスにtypedefした意味がないんですが 何かいい方法ありませんか?
785 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 02:58:54 ] >>783-784 Base の定義中に typename が必要な理由を知っていれば、無理だと予想が付くだろうに。
786 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 07:54:33 ] >>783-784 俺だったら Base::Stringと書けないか Derivedの中にusing Base::String;と書けばStringが使えないか の2つをまず試してみる。これでできるかどうかはもちろんしらんが。
787 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 09:04:33 ] Baseを使うなら、 typename Base<T>::StringType name; typename Base<T>::IntegerType number; こうなるから、これこそ、 > わざわざベースクラスにtypedefした意味がない ので、>>784 のやり方が良いだろう。 VC++もそのうち>>783 は駄目になることでしょう。
788 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 09:32:41 ] >>784 それVC7.1のバグらしい。 面倒見が良すぎて、typenameを本来ならば書かなければならない 所を、曖昧さがない場合は無くても通してしまう。 VC7.1でもちゃんと typename は書くべき。
789 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 12:59:29 ] このスレの難読コードをみて おれにとて C++はなかたことになた
790 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 13:03:53 ] そんなだから、未だに君にとってこの程度が「難読コード」なんだよ。
791 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 13:07:40 ] 俺もtemplateのコードは可読性が低いと思うよ 唯一の弱点だな
792 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 13:32:35 ] テンプレートとC++「本体」って明らかに別の言語だよな。 概念の異なる2つの言語が混在してるんだから、 可読性が低いのは当たり前。
793 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 15:19:32 ] >>792 じゃあどういう構文にすればいいよ?
794 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 19:15:56 ] 構文の話なのかな。
795 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 19:21:27 ] >>784 template<class T> struct Derived : public Base<T> { typedef Base <T> Base_; typedef typename Base_::StringType StringType; typedef typename Base_::IntegerType IntegerType; StringType name; IntegerType number; };
796 名前:デフォルトの名無しさん mailto:sage [2005/08/06(土) 20:27:48 ] >>795 意味無いじゃん。
797 名前:神゜ mailto:sage [2005/08/06(土) 20:49:53 ] そろそろ俺の出番か?