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 あたりに。
486 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 01:06:01 ] template <class T, bool HasKeyType, bool HasValueFirstType> struct A_specialized_impl { static const bool value = false; }; template <class T, bool HasValueFirstType> struct A_specialized_impl<T, true, HasValueFirstType> { static const bool value = is_same_type<int, typename T::key_type>::value; }; template <class T> struct A_specialized_impl<T, false, true> { static const bool value = is_same_type<int, typename T::value_type::first_type>::value; }; template <class T> struct A_specialized : A_specialized_impl< T, has_key_type<T>::value, has_value_first_type<T>::value > {}; template <class T, bool Specialized = A_specialized<T>::value> struct A { ... }; // 通常版 template <class T> struct A<T, true> { ... }; // 特殊化版
487 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 02:23:21 ] >485 細かいことですけどmapのkey_typeってconstですよ. SFINAEのこういう使い方はあくまで 「必要条件を満たさないものを振り落とす」ってだけなんですよね. それにできることが基本的な型特性と内部型の存在のテストくらいだし・・・. せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.
488 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 03:24:21 ] >>487 いや、value_type が pair<const Key, T> なのであって、 key_type は Key のままだよ。 そうでないと一時変数作れないし。
489 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 09:27:04 ] >>487 > せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど. typeof(メンバ関数)で何とかなります。
490 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 10:28:50 ] >488 マジボケしてました・・・. >489 何とかなります?typeofってそもそも非標準ですし.
491 名前:ヽ(´ー`)ノ ◆.ogCuANUcE mailto:sage [2005/05/10(火) 10:36:09 ] >>490 まだ sandbox だけど boost::typeof とか。 boost スレかどっかで見たけど、どこだったか忘れた。
492 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 14:30:49 ] >>489 これとか見ると、メンバ関数のシグネチャが分かれば なんとかできそうな気はする ttp://lists.boost.org/MailArchives/boost/msg70844.php
493 名前:デフォルトの名無しさん mailto:sage [2005/05/10(火) 22:34:40 ] >>491 typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか? >>492 汎用プログラミングの文脈だと「〜〜というシグネチャを持ったメンバ関数があるかどうか」というテストより 「〜〜という構文でメンバ関数が呼び出せるかどうか」というテストの方が重要だと思うので, そこで使われている技法は少なくとも汎用プログラミングでは非常に使いづらいような気がします. それにその技法,言語規格的に結構スレスレなことやってるので,GCCではうまく通らなかったり VC7.1でもうまく機能しないケースがあったり・・・.
494 名前:デフォルトの名無しさん mailto:sage [2005/05/11(水) 00:30:14 ] >>493 > typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか? traitsみたいなんじゃ不十分で、条件分岐とかしたいという事?
495 名前:ヽ(´ー`)ノ ◆.ogCuANUcE mailto:sage [2005/05/11(水) 10:34:33 ] >>493 失敗するだけだね。boost::mpl::has_xxx とかで何とかできないかとも思ったが、 寝不足なせいか、頭がこんがらがってきた。
496 名前:デフォルトの名無しさん mailto:sage [2005/05/11(水) 19:59:54 ] >>494 そうです.traitsというよりはintrospectionといったほうが適切ですかね. traitsはユーザが明示的に特殊化する分,確実ですけれど一方で面倒な側面もあると思うので, ある程度は要件を自動的にテストしてくれたほうが楽かなという発想です. >>495 boost::mpl::has_xxxは内部型の存在テストにしか使えないです.
497 名前:デフォルトの名無しさん mailto:sage [2005/05/12(木) 00:23:09 ] >>496 > そうです.traitsというよりはintrospectionといったほうが適切ですかね. traitsとも違い、 virtual classをinheritしたり、 interfaceをimplementsするのとは違う用途は、 具体的にどういうものを想定しているんですか?
498 名前:デフォルトの名無しさん mailto:sage [2005/05/12(木) 03:28:39 ] >>497 >具体的にどういうものを想定しているんですか? いや,あまりろくなことを考えていないんですが,一応,型がどのコンセプトの モデルなのかを識別するための手段として使えないか,と想定していました. 型がどのコンセプトのモデルであるかを識別できれば,クラステンプレートの特殊化や 汎用関数のオーバーロード選択をより柔軟にできるんじゃないかという考えです.例えば template<class Iterator, class T> void replace(Iterator first, Iterator last, T const &x); という汎用関数があって,TがIteratorの値型に変換可能な型ならstd::replaceの機能で, TがIteratorの値型を受ける単項述語ならstd::replace_ifの機能といった具合です. 逆に言うと,STLはこのようなコンセプトに基づいたオーバーロード選択の技術がないので replaceとreplace_ifとに名前を分けざるを得なかった,とも言えると思います. で,仮に例えばTのoperator()がIteratorの値型で呼び出せるかどうかを テストできるような実装技術があれば,traitsの明示的な特殊化に頼ることなく 上記のような高度な振り分けができるんじゃないか,という考えです. ただ,もちろんメンバ関数の存在テストはコンセプトの必要条件を調べられるだけで, 決してコンセプトのモデルであるための十分条件を調べることにはならないのですが・・・.
499 名前:デフォルトの名無しさん mailto:sage [2005/05/12(木) 03:29:37 ] ・・・ということを想定していたんですが, tinyurl.com/as9k5 上のような議論を見つけたので読んでみた結果,やはりtraitsの特殊化などで 明示的に表明する方が良いような気がしてきました.より根本的には 言語としてこういうことを直接サポートしてくれればもっとうれしいのですけれど. www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1758.pdf
500 名前:デフォルトの名無しさん mailto:sage [2005/05/12(木) 12:05:02 ] 上記PDFもそうだけど、D&Eの書き下ろし前文(-1章)を見ても、 コンセプト回りの拡張が c++0x でなされる可能性は高いんじゃないかな。 ただ、Stroustrup としても テンプレート回りのエラーメッセージの酷さを何とかすることや、 テンプレート宣言と定義の分離問題を何とかするために導入したいような 感じだし、基本的にはコンパイル時検査の強化を目的としたものであって、 オーバーロード選択などに使われるようなものではないと思う。 例えば、関数ポインタのシーケンスがあったとして、 operator== による find なのか、operator() による find_if なのか、 コンセプトだけでは判断できないケースもあるわけで。
501 名前:デフォルトの名無しさん mailto:sage [2005/05/12(木) 19:39:36 ] >>500 > 使われるようなものではないと思う。 けど,使われるようなものではないものに,使われて驚くのがtemplateだしなあ…
502 名前:デフォルトの名無しさん mailto:sage [2005/05/13(金) 01:07:52 ] >>500 >テンプレート回りのエラーメッセージの酷さを何とかすることや、 >テンプレート宣言と定義の分離問題を何とかするために導入したいような これは前々からずっと言ってますからねぇ.近い将来標準に導入されると信じていますけれど. >例えば、関数ポインタのシーケンスがあったとして、 >operator== による find なのか、operator() による find_if なのか、 >コンセプトだけでは判断できないケースもあるわけで。 う,やはりここ突っ込まれますよね・・・.こういう曖昧なケースではユーザが 明示的に曖昧性を解消するような方向を想定してました.微妙ですけれど. やはり現在の段階では,コンセプトに基づくオーバーロード選択や テンプレートの特殊化といった発想は飛躍しすぎている感がありますね.
503 名前:デフォルトの名無しさん mailto:sage [2005/05/14(土) 03:29:59 ] 参照templateのパラメータに制限あるのかな? グローバル変数しか使えないみたいなんだが... struct A{}; template <A& a>struct C{}; A a;//OK int main() { A a;//NG C<a> c; }
504 名前:デフォルトの名無しさん mailto:sage [2005/05/14(土) 05:10:48 ] >503 14.3.2 Template non-type arguments 4 [Note: Temporaries, unnamed lvalues, and named lvalues that do not have external linkage are not acceptable template-arguments when the corresponding template-parameter has reference type. 14.3.2-1 の補足。
505 名前:デフォルトの名無しさん mailto:sage [2005/05/14(土) 09:10:05 ] テンプレートはコンパイル時に生成されるわけで mainの方のaは実行してみないとどこに作られるかわからないわけで そのaをテンプレート引数にstruct Cは生成できないわな。
506 名前:デフォルトの名無しさん [2005/05/15(日) 21:00:03 ] VisualC++7.1なんですが、テンプレートコンストラクタの明示的なインスタンス化をしたいんですが コンパイルが通りません。なぜでしょうか? class A { public: template< typename B > A( B b){;} }; template< > A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。 他 template A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。
507 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 21:28:04 ] >>506 ttp://www.kuzbass.ru/docs/isocpp/template.html#temp.expl.spec ここに明示的な特殊化の対象となるものがリストされているんだが、 "member function template of a class template" はあるけど、 "member function template of a class" は無いな。 できないのかもしれない。
508 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 21:51:51 ] >>506 >>507 多分これ。 14.5.2.5 [Note: because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates. ] コンストラクタは関数名を持たないので、メンバテンプレートにされたコンストラクタおよび 変換メンバ関数テンプレートは明示的に実引数を与えられないって事っすね。 C++の不具合とも言えるので、次期C++規格ではfixして欲しいですな。
509 名前:デフォルトの名無しさん [2005/05/15(日) 21:56:00 ] >>506 理解しました。ありがとうございました。 しかし皆さん凄いですね。
510 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 21:56:33 ] >>506 というわけで 「コンストラクタテンプレートぐらいhppに全部書いちゃえば良いじゃない」 もしくは 「コンストラクタテンプレート内の処理を静的メンバ関数に委譲して (この部分だけはhppに書く必要アリ) 委譲先の静的メンバ関数を明示的にインスタンス化すれば良いじゃない」
511 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 22:32:53 ] ん?これでできてるっぽいぞ。 template<> A::A( int b);
512 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:29:21 ] >>511 あれ?本当だね。という事は、template <>の構文がちゃんとメンバテンプレート に適用されているみたいだね。俺の勘では、明示的特殊化になってなくて、単なる オーバーロードのような気もするが・・・・
513 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:36:57 ] もう少し規格票をよく読んでみる・・・・・ >>508 はそしたら違う事に関してなのかな。
514 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:41:09 ] >>511 しかし、そのコードは構文的に正しいとは言えないですよね。 謎だ。
515 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:41:17 ] 特殊化とインスタンス化とを混同してない?
516 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:55:33 ] >508が示したように、コンストラクタテンプレートに対して テンプレート引数を明示する方法は無い。 しかし、(メンバ)関数テンプレートの特殊化を宣言する再には、 テンプレート引数を明示しなくても、関数引数の型から テンプレート引数の推測が働く。 >>514 明示的特殊化の構文は template<> delcaration だから、>511は構文的に正しいと言える。
517 名前:デフォルトの名無しさん mailto:sage [2005/05/15(日) 23:58:48 ] 構文的には確かに正しいのだけれど、もともとの506の要求は 明示的インスタンス化(≠明示的特殊化)なわけで・・・
518 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:02:05 ] 勉強になった。
519 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:08:01 ] >>517 それがどうした? 明示的インスタンス化の構文は template declaration だ。あとは同じ。
520 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:12:53 ] >>519 すまんすまん。それでVC++7.1で通ったよ。
521 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:15:29 ] コンパイラに「これこれのテンプレートをT型でインスタンス化しますた」 とレポートするスイッチがあればいいのに
522 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:17:31 ] 実体化の位置を決定するルールは結構複雑だからな。
523 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 00:59:29 ] おまえらの必死さに笑った。 C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、 まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
524 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 01:03:16 ] C++知らないのに、知ってる振りして がんばって煽るアンタもそうとう必死だが
525 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 01:35:46 ] むしろC++で駄目なのは テンプレートじゃなくてコンストラクタ
526 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 01:47:19 ] >>525 コンストラクタの何が不満だって?
527 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 02:48:50 ] 純粋なOO言語と比べると C++のOOは不完全
528 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 03:05:21 ] >>526 class A { int a; public: A( int a_ ) : a(a_){;} }; class B : A { public: B(){ int a = 略; A::A(a);} B( int a ) : B(){;} };
529 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 03:16:11 ] 何がしたいのか理解に苦しむ。C++について理解しているとは思えないコードだ。
530 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 03:30:52 ] >>529 これが出来ないから嫌だなと。 >B(){ int a = 略; A::A(a);} これはAに突っ込む引数aを Bのコンストラクタ内で生成したい時。 C++ではAのコンストラクタは、Bの初期化リストにしか 置けないので複雑なロジックは難しい。 >B( int a ) : B(){;} これは多重定義したコンストラクタから デフォのコンストラクタを予呼びたい時。 デフォのコンストラクタに生成時にかならず呼ばれる 初期化コードを収める。 これが出来ないと全てのコンストラクタに 同じ初期化コードを書かなければならない。
531 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 04:43:03 ] >>530 最初の:AはBの基底クラス。最初にAが構築されなきゃBが構築できない。 2番目の:B() {Init();} B(int a) {Init();hogehoge(a);}
532 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 08:55:21 ] 最初のは static int hoge() {return 略} B() : A(hoge()) {} とかすれば。
533 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 09:05:50 ] >>530 そういうことか。 ではどうしたらいいと思う? Dは両方いけるんだっけか?
534 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 09:06:24 ] >>531 > Aが構築されなきゃBが構築できない 関係ない。 > Init() Init() の中に初期化リストが書けない。
535 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 09:07:23 ] >>532 hoge() の値を初期化リストで2度使いたくなったらやっぱり困るな。 「略」が軽くて副作用がなければ、2回呼び出すんだろうけど。
536 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 09:10:37 ] 要は設計が悪いんだろ。
537 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 09:18:31 ] まあそうだな。C++の設計の悪さは今更いかんともしがたい部分がある。
538 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 11:19:33 ] >>530 > C++ではAのコンストラクタは、Bの初期化リストにしか > 置けないので複雑なロジックは難しい。 コンストラクタの途中でexceptionが起きたことを考えると、 >>532 のような方法で初期化リストを旨く使う方法に頭を悩ませるのが良い。 >>528 のやり方ではコンストラクト失敗時のデストラクトの扱いがかなり難しくなる。 初期化リストで上手くできない場合は、 exception safeの事を考えるとコンストラクタ自体がかなり複雑になってしまう。
539 名前:>>538 mailto:sage [2005/05/16(月) 11:21:07 ] 定義順じゃなくて、初期化リスト記述順だといいのになあと思ったことはある。
540 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 12:06:24 ] >>539 それだと、コンストラクタごとに初期化順が変わってしまう。 Ex. class foo { public: foo() : a_(), b_() {} foo(int a) : b_(a), a_(a) {} ...; };
541 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 12:21:40 ] >>540 539はまさにそれを意図しているのだと思うが、何か不都合があるの?
542 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 12:53:52 ] >>541 初期化リストに載ってないメンバはどうすればいい? by コンパイラ
543 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 13:14:10 ] くるしゅうない。よきにはからえ。
544 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 13:17:59 ] 構築した順番の逆順で解体することを保証しなきゃならんので コンストラクタごとに初期化順が変わったら大変だ。
545 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 14:05:33 ] なるほど。それもそうだ。
546 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 15:32:47 ] つーか藻前らEffectiveC++くらい読んどけよ。
547 名前:デフォルトの名無しさん [2005/05/16(月) 20:25:46 ] template< uint n > class X { public: void f(...); } こういうクラスがあったとして、 nが1だった場合 → X::f( uint f0 ); nが2だった場合 → X::f( uint f0, uint f1 ); nが3だった場合 → X::f( uint f0, uint f1, uint f2 ); こういうふうにテンプレート引数によって 関数の引数の数が変わるようにしたいんですが可能ですか? 出来ないまでも、代替手段みたいなのはありますか?
548 名前:デフォルトの名無しさん [2005/05/16(月) 20:53:37 ] あの〜 templateって実はマクロ?
549 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 21:23:34 ] >>547 関数のデフォルト引数でなんとかしろ。同一のテンプレートパラメータの型を 持つクラスは2回以上は定義できん。
550 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 21:58:37 ] >>549 了解、こういうのも出来るといいですね。
551 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 22:15:27 ] いやだから、ディフォルト引き数で何が不満なんだ?
552 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 22:22:47 ] それぞれ特殊化で可能じゃない?もちろんそうするのが良いか悪いかは別。
553 名前:デフォルトの名無しさん [2005/05/16(月) 22:26:17 ] >>551 例えばベクトルクラスがあります。 template< uint n >class vector; これをインスタンス化したい場合、こういうふうに書きたいんです。 vector<2> v2 = vector<2>(5,1); vector<3> v3 = vector<3>(5,1,6); vector<4> v4 = vector<4>(5,1,6,3); vector<5> v5 = vector<5>(5,1,6,3,9); vector<100> v100 = vector<100>(5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9); 自然な欲求だと思います。
554 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 22:31:08 ] >>553 そういう時のためのstd::vectorではないかと思うのだが・・・・
555 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 22:34:16 ] static const uint initialValues[] = {5, 1, 6, 3, 9,}; std::vector<uint> v5 = std::vector<uint>(initailValues, initialValues + sizeof(initialValues) / sizeof(*initialValues));
556 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 22:34:58 ] その例なら 配列を初期化して、std::vectorにぶち込めばいいじゃん どうしてもやりたいならBOOST_PPで特殊化
557 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:09:19 ] 部分特殊化。以降略。なんか馬鹿みてえ。 #include <iostream> #include <cstddef> template <std::size_t N, typename T = int> class vec { T a[N]; public: vec(T i) { a[0] = i; std::cout << a[0] << std::endl; } }; template <typename T> class vec<2, T> { T a[2]; public: vec(T i, T j) { a[0] = i; a[1] = j; std::cout << a[0] << ' ' << a[1] << std::endl; } }; int main() { vec<1> v1 = vec<1>(5); vec<2> v2 = vec<2>(5,1); }
558 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:21:18 ] 特殊化はイヤというか面倒くさすぎるから、普通はこんなカンジだろうね template<uint Dim> class vector { double *const coord; public: vector(double x) : coord(new double[sizeof(char[Dim == 1]) * Dim]) { coord[0] = x; } vector(double x, double y) : coord(new double[sizeof(char[Dim == 2]) * Dim]) { coord[0] = x; coord[1] = y; } vector(double x, double y, double z) : coord(new double[sizeof(char[Dim == 3]) * Dim]) { coord[0] = x; coord[1] = y; coord[2] = z; } }; int main() { vector<1> v(1); vector<1> v1(1, 2); // error vector<2> v2(1, 2); vector<2> vv2(1); // error vector<3> v3(1, 2, 3); }
559 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:24:56 ] やはりコンストラクタのオーバーロードに落ち着くか。
560 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:25:18 ] >> そうするまでもなく 普通に多重定義でいいと思うよ。 template <std::size_t N, typename T = int> class vec { T a[N]; public: vec( T x, T y) { if( N > 0 )a[0] = x; if( N > 1 )a[1] = y; } vec( T x, T y, T z) { if( N > 0 )a[0] = x; if( N > 1 )a[1] = y; if( N > 2 )a[2] = z; } };
561 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:27:04 ] ちなみに、 sizeof(char[Dim == 1]) ってのは、 Dim == 1 のときは、1 で、そうでなければ、コンパイルエラーね
562 名前:デフォルトの名無しさん mailto:sage [2005/05/16(月) 23:59:25 ] どうも読みにくいので、直した template<unsigned Dim> class vector { double coord[Dim]; public: vector(double x) { sizeof(char[Dim == 1]); // Dim == 1 でなければエラー coord[0] = x; } vector(double x, double y) { sizeof(char[Dim == 2]); // Dim == 3 でなければエラー coord[0] = x; coord[1] = y; } vector(double x, double y, double z) { sizeof(char[Dim == 3]); // Dim == 3 でなければエラー coord[0] = x; coord[1] = y; coord[2] = z; } }; int main() { vector<1> v(1); vector<1> v1(1, 2); // コンパイルエラー vector<2> v2(1, 2); vector<2> vv2(1); // コンパイルエラー vector<3> v3(1, 2, 3); }
563 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 02:55:12 ] おまえらの必死さに笑った。 C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、 まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
564 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 02:57:49 ] ×メンテ不能 ○俺に理解不能
565 名前:デフォルトの名無しさん [2005/05/17(火) 07:37:28 ] あーあ、4,5,6って別々にするわけ?テンプレの意味ねー
566 名前:デフォルトの名無しさん [2005/05/17(火) 07:41:46 ] テンプレートはマクロ www.iba.k.u-tokyo.ac.jp/〜yanai/template_tips.html
567 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 10:05:48 ] >>563 まあ同意。boostとか見てても思うが、言語使用の範囲内でどうにかしようとするから無理が出てくる。 パズルとしては興味深いが、無理やりやってるからどうしてもキモくなる。 新しいプリプロセッサ作ったほうがマシな気がする。
568 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 12:24:00 ] >>566 典型的なアホっぽいが。 exportはComeauでサポートされていることすら知らんようだし。
569 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 12:40:07 ] >>566 > まず最も重要な事実は、templateはマクロであるということである。 そもそも、始めの仮定についてキチンと論証してない時点でアウトだな。
570 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 13:16:28 ] templateはマクロだよ。 マクロと聞いてCやC++のプリプロセッサ(やVBAなどアプリケーション内のスクリ プティング言語)しか思いつかない人に向けた文章ではなかろ。
571 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 14:01:12 ] >ここではオブジェクト指向に則ったよいtemplateの使い方を模索する。 この時点で道を誤っている気が。
572 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 14:29:53 ] templateの明示的インスタンス化なんて、少し考えれば 使い道などろくに無い機能だとわかるだろうに しかも使う必要も無い機能だし それにこだわってる時点で、ダメだなそのページ
573 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 18:56:42 ] ネタをまじめに叩くなよ
574 名前:デフォルトの名無しさん [2005/05/17(火) 20:39:55 ] ねたじゃねーし templateはコンパイルする前に展開されるからマクロなの
575 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 20:42:50 ] コンパイルする前に展開しちゃったら タイプセーフは無理じゃないの?
576 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 20:47:38 ] いいよわからん奴は無理に使うな
577 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 21:03:14 ] マクロで使える構文を限定的にして型を認識させたのがテンプレート
578 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 21:12:28 ] みんな好き勝手に「マクロ」の意味を定義して使ってるから、話が噛み合わない だけでしょ。
579 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 21:56:51 ] おっと、ここで578が正式にマクロの定義とやらを教えてくれるらしいぞ
580 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 22:03:42 ] なにこの意味不明な反応
581 名前:デフォルトの名無しさん mailto:sage [2005/05/17(火) 22:21:02 ] 付き合うだけ無駄でつ
582 名前:デフォルトの名無しさん [2005/05/18(水) 07:21:54 ] 普通のマクロでも引数の数を変えられるようなことはできないから >>553
583 名前:デフォルトの名無しさん mailto:sage [2005/05/20(金) 00:28:48 ] VC7.1で std::list<int>使うとポインタの保存のためか std::vector<int>の3倍近いメモリ使うんだが、 省メモリな実装のlistって無理なのかな?
584 名前:デフォルトの名無しさん mailto:sage [2005/05/20(金) 00:55:57 ] >>583 SGI STLのstd::slistなら、一方向リストだけど、少しでも少ないかも。
585 名前:デフォルトの名無しさん mailto:sage [2005/05/20(金) 01:45:41 ] リストすら作りを理解してないのかよ。
586 名前:デフォルトの名無しさん mailto:sage [2005/05/20(金) 12:25:58 ] std::vectorのresizeコストが気になるようならstd:;dequeとか