1 名前:デフォルトの名無しさん mailto:sage [2008/01/11(金) 18:43:34 ] C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。
175 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:01:40 ] >>173 詳しく有難うございます。納得できました。 >>174 「構文」は間違いでした。>>173 のような事を表したかったのですが、 そういう場合は何と呼ぶべきですかね…
176 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:20:13 ] >>175 つか、何がしたいの?
177 名前:デフォルトの名無しさん [2008/01/26(土) 04:53:51 ] 今タイピングのアルゴリズムでゲーム中に「し」を「si」と「shi」のどちらでも受け付けるとような操作を考えています。 現段階では文字列クラスを用意して双方向リンクリストを使って分岐を操作して居るんですが、どうしてもコードが複雑になってしまいます。 もう少し簡単なアルゴリズムや便利なSTLなどがあったら教えてください。 文字列クラス class characterData { private: wchar_t ch; // 単語を構成する文字 Databace* follow; // この文字に続く文字へのポインタ Databace* other; // 分岐文字へのポインタ Databace* rear; // この文字の前の文字へのポインタ public: Databace(); Databace(wchar_t, Databace*, Databace*, Databace*, unsigned char); ~Databace(); // 変数の値を設定する関数群 void setFollow(Databace*); void setOther(Databace*); void setRear(Databace*); void setCh(wchar_t); void setLevel(unsigned char); // 変数の値を返す関数群 wchar_t getCh() const; Databace* getFollow() const; Databace* getRear() const; Databace* getOther() const; }; 文字列を作るクラス class createString { private: Databace* end; // 文字列の最後の文字へのポインタ Databace* div; // 分岐文字がある場合のみendと違う場所を指す void add(const int n, ...); // n個の文字を追加する public: CStrManage(); ~CStrManage(); // elementをローマ字に変換しbaseの後ろに追加する bool convert(const wchar_t* element, Databace* base); };
178 名前:デフォルトの名無しさん [2008/01/26(土) 05:00:27 ] 追加用の関数はこうなっています void createString::add(const int n, ...) { va_list args_pointer; wchar_t* arg_wchar; size_t length; va_start(args_pointer, n); // 文字を分岐させる for(unsigned char i=0; i<n; i++) { arg_wchar = va_arg(args_pointer, wchar_t*); length = wcslen(arg_wchar); // 分岐用文字列を作成する Databace cdb; // ダミーの作成 Databace* tmp = &cdb; // 追加先の指定 Databace* rear = NULL; // 現在地の記憶 // 文字の追加 for(unsigned char s=0; s<length; s++) { Databace* data = new Databace(); if(s==0) { rear = data; } // 追加前の場所を記憶 // 文字データの設定 data->setFollow(NULL); data->setOther(NULL); data->setCh(arg_wchar[s]); data->setLevel(s + 1); if(s==0) { data->setRear(end); } // 前の文字を参照させる else { data->setRear(rear); } // 新しく作った文字列の先頭を参照させる // 文字を追加 tmp->setFollow(data); tmp = tmp->getFollow(); } // 作成した文字をデータベースに追加する if(i!=0) { div->setOther(tmp2->getFollow()); div = tmp; // 作成した文字を追加 div->setFollow(cdb.getFollow()); div = end; // 分岐後の参照先を設定 } else { div->setFollow(cdb.getFollow()); end = div = tmp; } } va_end(args_pointer); }
179 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 05:34:13 ] >>170 sizeof(this) ってポインタのサイズだと思われ sizeof(*this) にしないとだめなんじゃね?
180 名前:179 mailto:sage [2008/01/26(土) 05:36:04 ] って、すでに173で指摘されてた・・・
181 名前:110 mailto:sage [2008/01/26(土) 06:16:08 ] >>177 std::listを使って一本のリストを作って、リストの各要素のオブジェクトを工夫したほうがいいよ。 リストクラス自作するにしても、これはあまりにも酷い。 せめてコンパイルが通りそうなコードを読ませてくれ。
182 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:09:34 ] >>175 そもそも、クラスの初期化を外部から行なってはいけません。
183 名前:156 mailto:sage [2008/01/26(土) 11:23:55 ] 結局、他の人はどうしてるの?
184 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:48:39 ] 折角階層的にネームスペースを宣言しているのに、ユージング宣言し捲くるってどうなのよ。 そんなばかげたことする香具師いないからレスがつかないんじゃね?
185 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:54:16 ] using なんて普通は使わないよな。
186 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:04:47 ] >>166 all.hにはすべてのヘッダファイルではなく、外部から提供されたライブラリのヘッダだけ入れておけば 基本的に更新することはないんじゃない? (その場合、all.hというネーミングは不適切だね。)
187 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:05:50 ] 目的を既に忘れてるな
188 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:18:43 ] using 宣言は使うだろ。 using しないとコードが汚くなる。 そこらじゅう ns1::ns2::hoge() とか nsN::nsM::hoge() とかばかりになるぞ。
189 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:21:44 ] ある程度のプロジェクトではファイルの先頭が #include や using で埋め尽くされるのは避けられないこと。 耐えろ。
190 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:22:45 ] >>188 おまいはヘッダファイルでも using 使って 迷惑かけるタイプか
191 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:26:55 ] >>190 どっからヘッダファイルで using なんて考えが出てきたんだ? *.h と *.cpp では書くものが違うのはあたりまえだろうが。常考。
192 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:32:23 ] using なんて使わなくても 名前空間のエイリアス作ればいいだろ。
193 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:35:08 ] >>188 namespace fuga1 = hoge1::hogeA::hogeX; namespace fuga2 = hoge2::hogeB::hogeY; namespace fuga3 = hoge3::hogeC::hogeZ; …… みたいな解決策もある。
194 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:36:58 ] using は関数増えた時に別の関数が選択される恐れがあるから怖い。 エイリアス作ろうぜ。
195 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:40:22 ] >>194 例は? using 指令と違って using 宣言では名前が衝突するとコンパイルすら通りませんが?
196 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:41:57 ] そもそもネームスペースが上手く使われてる大規模プロジェクトって見たことないな。 パッケージ名を接頭辞に持つプロジェクトの方が上手くいってたりする。
197 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:44:54 ] >>195 そりゃ嘘を教えられたな。 確かにエラーになることは多いが、エラーにならない事もある。 ========== namespace Hoge { void Foo(); } namespace HogeHoge { void Bar(); } using Hoge::Foo; namespace HogeHoge { void Bar() { Foo(); } ← Hoge::Foo } ========== namespace Hoge { void Foo(); } namespace HogeHoge { void Foo(); void Bar(); } using Hoge::Foo; namespace HogeHoge { void Bar() { Foo(); } ← HogeHoge::Foo }
198 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:48:05 ] >>193 の方法でいいんじゃない? これなら普通は namespace の数 < 識別子の数 なので先頭部分は少し短くなる。 ただし、その代わりにコードは少し長くなる。 どっちにしろ先頭が namespace で埋め尽くされるのは変わらないが。
199 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:54:22 ] そだよ。エイリアスが一番マシ。 ただ、エイリアスは .cpp のグローバルでのみ作るべし。 名前空間内で作っちゃうとまたややこしい問題が生じる。
200 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:59:57 ] グローバルで using してたら意味ないだろ。 namespace HogeHoge { using Hoge::Foo; void Foo(); } で普通にエラーでたぞ。
201 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:43 ] >>200 あらホント。
202 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:57 ] namespace Hoge { void Foo(); } namespace HogeHoge{ namespace Hoge { void Foo(); } void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo } 別に間違いようはいくらでもある。
203 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:06:33 ] 名前空間って厄介だよな。
204 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:08:55 ] >>202 これって防ぎようなくね? どうすんの? これ。
205 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:11:53 ] >>204 ::Hoge::Foo() でアクセスできるよ。
206 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:12:27 ] >>205 なるほど・・・。 でも、常日頃から :: から始めないと防げないよな。
207 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:13:53 ] そもそも他人の名前空間と同じ名前の名前空間を 後から作るという時点で間違いだとは思うが、 開発中に後から導入したライブラリが・・・ということもあるか・・・。
208 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:17:40 ] ちなみにこんなのも。 namespace Fuga { void Foo(); } namespace Hoge = Fuga; namespace HogeHoge { class Hoge { public: static void Foo(); }; void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo(); }
209 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:22:31 ] 名前空間はクラス名・関数名・変数名なんかと違って規約がなかったりするから、結構みんなテキトーにつけてたりする。 酷い話だとグループ全員が自分用の関数を mylibs に入れていた例が...
210 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:25:14 ] 幾何学ライブラリで geom が衝突したりとかだな。
211 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:28:54 ] かといってJavaみたいにドメインを逆さにするのもなぁ
212 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:32:14 ] >エイリアスは .cpp のグローバルでのみ作るべし。 グローバルに alias 作るとヘッダが変わったときに突然コンパイルが通らなくなることあるよ。
213 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:35:49 ] 前に関ったプロジェクトは常にフル指定?でメソッドを呼び出すべし という規約があった 基底クラスのメソッドさえも Hoge::Foo:Base:Dosomething(); 多重継承を多用していたからという事情もあるんだけど 面倒だけど、安全ではある
214 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:46:38 ] その面倒なのがイヤだから using を使いたい、alias を使いたいってんだと思うが。 ぐるっと一周してきた感じだな。
215 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 14:07:49 ] グローバルにエイリアス量産するぐらいなら名前空間内で using 宣言した方がいいと思う・・・
216 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 18:53:06 ] しかしだな、エイリアスと別の名前空間が衝突することもあってだな・・・。
217 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 19:00:54 ] 無限下降スパイラル
218 名前:177 [2008/01/26(土) 19:12:06 ] >>181 すいません、文字列クラスがcharacterDataではなくDatabaceでした。 >std::listを使って一本のリストを作って listやmapを使うことも考えたんですが、リスト化した後のタイプの分岐判定のアルゴリズムが思いつかず断念しました。 なのでその辺のアルゴリズムのアドバイスも出してくれると助かります。 >コンパイルが通りそうなコード コンパイルも通って動作確認もしてあるので正常に動作しているとは思います。 ただ、これだけ乱雑になると可読性に欠けてバグの温床になりそうなのでアイディアを聞きたいと思った次第です。
219 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 01:56:06 ] >>175 遅レスだけど、 そういう場合は鼻から悪魔がでますか?って聞けばいいよ。
220 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 11:37:37 ] //xxx.cpp namespace { namespace ns = long::longlong::longlonglong::ns; } void F1() { ns::Foo(); }
221 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 13:21:55 ] template <typename T> //primary template class Test { public: enum { Result = 1 }; }; template <typename T> //T const に対する partial specialization class Test<T const> { public: enum { Result = 2 }; }; template<typename T> void f(T t) { cout << Test<T>::Result << endl; } int main() { int i = 1; f(i); // @ --> 1が表示される int const j = 1; f(j); // A --> 1が表示される }
222 名前:221 mailto:sage [2008/01/27(日) 13:22:31 ] 221です。続きです。 >>221 のtype functionについて疑問があります。 main関数内のAの呼び出しでは、渡している引数の型は確かに int const の はずですが、結果はprimary templateが呼び出されます。Aでは T が int const に deduction されて、T const に対する partial specialization が呼ばれ、結果が2 になると思ったのですが、そうはなりませんでした。 明示的に f<int const>(j); とすれば 2 が表示されます。 何故 A の呼び出しで T が int const に deduction されないのでしょうか?
223 名前:221 mailto:sage [2008/01/27(日) 13:54:47 ] int const val; のように変数valを定義した場合、valの型にconstは含まれるのでしょうか? int const& ref; の場合は、refの型は int const& となりconstは含まれますよね?
224 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:46:48 ] int const val; と const int val; は等価。 val の型に const は含まれる。
225 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:57:41 ] >>222 パラメータリストのconst修飾は関数の型としては無視される、 ということからだろうと思われる たとえばvoid f(int);とvoid f(int const)の型は全く同一になる f<int const>(j); とすれば 2 が表示されることに保証があるのか 俺は知らない
226 名前:221 mailto:sage [2008/01/27(日) 16:45:57 ] レスありがとうございます。 >>224 >int const val; と const int val; は等価。 それは知ってます。 やはり型の一部ですよね。 >>225 >たとえばvoid f(int);とvoid f(int const)の型は全く同一になる value functionに関するそのルールは知っています。 このプログラムはvalue functionではなく、type functionなので 引数のdeductionの問題になると思います。f<int const>(j); は 明示的に型を指定しているのでpartial specializationが使用 されることは間違いないです。ただ、constが型の一部であるにも 関わらず、int const型のテンプレート引数である j を渡しても specializationが使用されていないのが理解できません。 結果を見る限り、const修飾子が無視されてint引数として扱われてること になりますが、これはテンプレートの標準における正しい仕様なのでしょ うか? VC++ 2008 と g++ v4 ともに同じ結果でした。
227 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 16:49:54 ] そもそも const int を int な引数の関数に渡せるしね。 規格でどうか知りたいなら、規格を読むのが一番だ。
228 名前:221 mailto:sage [2008/01/27(日) 17:09:22 ] >>227 それはvalue functionのパラメータ及び引数のルールであって、 テンプレートのtype parameterのdeductionはまた別の問題のよ うに思います。もう少し規格を見てみます。
229 名前:221 mailto:sage [2008/01/27(日) 17:12:18 ] >>227 >>228 は撤回します。 確かにそれが理由のような気がします。 そうすると、const int と T を比べると T が intに deductionされるのも頷けます。
230 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:14:12 ] >>226 >partial specializationが使用 されることは間違いないです ああそりゃそうか >これはテンプレートの標準における正しい仕様なのでしょうか? 14.8.2 -3-にあった
231 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:17:06 ] 手元にドラフトがあるのでそれで調べてみたが、14.8.2.1 p2 にそれらしきものが。 14.8.2.1 Deducing template arguments from a function call If A is a cv-qualified type, the top level cv-qualifiers of A's type are ignored for type deduction.
232 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:18:11 ] あー、そっちかもしれん。>>230
233 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:19:04 ] >>226 type function とか value function とか、何の方言? 意味がわからない。
234 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:20:09 ] 最新のドラフトを見ると怖いことが書いてあった [ Note: f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type. .end note ]
235 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:24:04 ] >>234 まあ明示的に指定する分には違っててもいいんじゃね?
236 名前:221 mailto:sage [2008/01/27(日) 17:34:09 ] >>230 >>231 >>232 >>233 >>234 >>235 みなさんレスありがとうございます。 >>231 まさにそれかと思います。同じことがJosuttisのC++ Templateにも 書いてありました。 こういう事情のようでです。 template<typename T> void f(T); template<typename T> void g(T&); int const ci = 123; f(ci); // T is int g(ci); // T is int const すっきりしました。
237 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:40:02 ] int const& の const はトップレベルの const じゃないからそうなるわな。なるほど。
238 名前:221 mailto:sage [2008/01/27(日) 17:47:45 ] >>233 詳しいことは知りませんが、 現段階で標準で規定された言葉ではないと思います。 テンプレートの本に書かれていました。 value functionはいわゆる通常の関数を指します。 パラメータがtype、引数が値。 type functionとは、通常クラステンプレートで 実現されるものらしいです。 パラメータがテンプレートパラメータ、引数がtype。 struct Widget{}; Test<Widget>::Result; >>221 のTestクラステンプレートの場合、Widgetが引数で type functionの戻り値がTest<Widget>::Resultと考え ると通常の関数のように関数とみなせるというもだと 理解してます。
239 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 18:03:50 ] >>238 「テンプレートの本」ってどれだ? 普通に「関数」と「クラステンプレート」って言ったほうがいいと思うよ。 意味の違いを正しく表している呼び名だとは思えないからね。 後者は「(テンプレート)メタ関数」とか呼ばれるもののような気もするなぁ。
240 名前:221 mailto:sage [2008/01/27(日) 18:36:02 ] >>239 ここでいうtype functionとは 最近の言葉で表せばメタ関数でしょうね。 Boost::mplなどの最近のメタプログラミングで 使われていますが。 本はC++ Template The Complete Guideです。 著者は標準化委員会の現メンバーでもあり 信用できないものではないと思います。 通常の関数と対比して、コンパイル時に型を引数 とする”関数”という概念的に上手い言葉だと感じ ているので自分はなるほどと思いました。
241 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:21:38 ] >>240 メタ関数でいいならそう言ったほうがいいでしょ。 わざわざ廃れた用語を使い続ける理由もない。
242 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:32:18 ] meta function == type function 別に正式な名前じゃないけど、 type functionってのはそこそこみる表現だから覚えておいてもいいと思うよ
243 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 23:07:12 ] >>241 別に廃れてるわけではないよ。 概念を表した言葉だから。
244 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 11:46:24 ] 適当なオブジェクトのポインタが与えられたとき、そのオブジェクトのクラスがある特定の 名前と引数のタイプを持ったメンバ関数を持つときに限りその関数を呼んで処理したい のですが、C++ で可能でしょうか? あ、オブジェクトは必ずしも共通のスーパークラスを持たないとします。要はそういう 場合でも仮想関数的なことをしたいというか... その特定のメソッドをもつ別クラスを作って、それを全てのオブジェクトで多重継承、 というのも考えているのですが、ちょっとダサいかな? と思って。あとソースのないクラス では無理ですよね(今のところはソースのあるクラスだけでいいんですが)。 そもそもこんなことを考える事自体ナンセンス、と言われるとアレなんですがw
245 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:35:21 ] ポインタの型がテンプレート引数で与えられているならば、可能
246 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:41:29 ] >>245 嘘だろ。怪しいからソースを晒してください。
247 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:44:38 ] >>244 おとなしく多重継承すべし。
248 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:52:14 ] >245が言いたいのは「コンパイル時にクラスが確定できる」場合だろ。
249 名前:245 mailto:sage [2008/01/29(火) 13:41:34 ] おかしいな。VC9だとhas_xxxが通らない。 自分で書いてみても、やはり通らない。 こんな風にSFINAEを使ってやればできるはずなんだけど。 struct BjarneStroustrup { void hage() ; } ; struct Others { void fusafusa() ; } ; template < typename T > struct has_hage { struct Yes { char a[1] ; } ; struct No { char a[2] ; } ; template < typename Y > static Yes test(typename Y::hage const *) ; template < typename Y > static No test(...) ; static bool const value = ( sizeof( test<T>(0) ) == 1 ) ; } ; BOOST_STATIC_ASSERT(( has_hage<BjarneStroustrup>::value )) ; BOOST_STATIC_ASSERT(( has_hage<Others>::value )) ;
250 名前:245 mailto:sage [2008/01/29(火) 13:42:58 ] 最後の一行間違ってるけど気にしないで
251 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:42:17 ] template < typename Y > static Yes test(typename Y::hage const *) ; はおかしくないか? マッチしなかったぞ。 やるなら template < typename Y > static Yes test(void (Y::*)(void)); か? でも、これじゃあ関数名の一致の評価はムリだな。 何か仕組みが必要か。
252 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:42:50 ] struct BjarneStroustrup { void hage(){cout << "hage" << endl; } }; struct Others { void fusafusa(){cout << "fusafusa" << endl;} };
253 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:43:13 ] template <typename T> struct has_hage { typedef char One; typedef struct { char a[2]; } Two; template < typename Y > static One test(void (Y::*)(void)); template < typename Y > static Two test(...); enum { value = sizeof(test<T>(0)) == 1 }; } ; template <typename T> void func(T) { cout << "too bad" << endl; } template <> void func(BjarneStroustrup* p) { p->hage(); } template <typename T> void call(T* t) { if(has_hage<T>::value) func(t); }
254 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:44:52 ] int main() { BjarneStroustrup b; call(&b); Others o; call(&o); }
255 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:02:09 ] struct BjarneStroustrup { typedef void HAGE; void hage() const {cout << "hage" << endl; } }; こういう風に typedef 定義して(擬似的な名前一致) template < typename Y > static One test(typename Y::HAGE *); じゃだめかいな。
256 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:34:33 ] これじゃあシグニチャが合わないか。
257 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:45:03 ] ちょっと変更 struct HAGE{}; struct BjarneStroustrup { template <typename T> void hage(); template <> void hage<HAGE>() {cout << "hage" << endl; } }; template <typename T> struct has_hage { ・・・・・ template < typename Y > static Two test(...); ・・・・・ } ; template <> void func(BjarneStroustrup* p) { p->hage<HAGE>(); }
258 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:46:00 ] こっちだった。 template <typename T> struct has_hage { ・・・・ template < typename Y > static One test(void (Y::*)(HAGE)); ・・・・ } ;
259 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 17:12:00 ] このスレって頭悪い奴多いね
260 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 17:20:47 ] そもそもプログラミングしてる時点でアレだしな
261 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 17:55:27 ] ググったらこんなのが出てきた。 www.gamedev.net/community/forums/topic.asp?topic_id=435173 これを基に少し改造してみた。BjarneStroustrupとOthersは>>249 の定義を使用。 #include <iostream> #include <boost/mpl/bool.hpp> //#include <boost/type_traits.hpp> struct SFINAE { typedef char one; typedef struct { char c[2]; } two; }; template<typename T> class has_hage_impl { template<void (T::*)()> struct Wrap {}; template<typename U> static SFINAE::one Determine(Wrap<&U::Hage>* w); template<typename U> static SFINAE::two Determine(...); public: static const bool value = sizeof(Determine<T>(0)) == sizeof(SFINAE::one); }; template<typename T> struct has_hage : boost::mpl::bool_<has_hage_impl<T>::value> {}; //boost::integral_constant<bool, has_hage_impl<T>::value>も可 int main() { std::cout << std::boolalpha << has_hage<BjarneStroustrup>::value << '\n' << has_hage<Others>::value << std::endl; }
262 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 18:26:26 ] >>259 ほんとだね
263 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 18:27:59 ] >>259 具体的な解決策はありますか?
264 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 18:31:49 ] クラステンプレートのテンプレイート引数をバインドしたいと思っています。 考えたのは template <class T1, class T2> class A {...}; template <class T1> class AInt { public: typedef A<T1, int> type; }; このような方法ですが、AInt<Hoge>::typeとしないといけないところに不満が残ります。 typedef A<T1, int> template <class T1> AInt; こんな感じで完全にバインドしてしまう方法はないでしょうか?
265 名前:デフォルトの名無しさん [2008/01/29(火) 18:33:14 ] 0,1,2,3,4 から 2個取り出すときの全組み合わせ 3個 4個 5個(は1通りだけど) を文字列(stringでもcharでも)として吐き出すプログラムを 書きたいんですがアイディアだけでもいただけないでしょうか?
266 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 18:41:20 ] >>265 それなんて宿題?
267 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 18:44:37 ] >>264 今のC++にはない。0xに乞うご期待。 その方法が嫌なら、使える場合が限られるけど継承するか、 template <class T1> class AInt : public A<T1, int> {}; あとはプリプロセッサマクロで何とかするか。
268 名前:デフォルトの名無しさん [2008/01/29(火) 18:47:21 ] や、宿題じゃないんですが自分でプログラムかいててハタと迷ったので・・ スレチならすいません
269 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 19:03:09 ] >>265 なにが固定でなにが引数になるか書いてくれないと答えようがないぜ。
270 名前:264 mailto:sage [2008/01/29(火) 19:03:55 ] >>267 そうなんですか。 ありがとうございました。
271 名前:268 mailto:sage [2008/01/29(火) 19:03:59 ] すいませんネットから拾ったプログラムを改変したら多分出来ました。 #include <stdio.h> int main(int argc ,char *argv[]){ int a=0,b=0,c=0,d=0; for (a=0;a<=4;a++){ for (b=0;b<=4;b++){if(b==a || a>b)continue; for (c=0;c<=4;c++){if(c==a || c==b || b > c)continue; for (d=0;d<=4;d++){ if(d==a||d==b||d==c||c>d)continue; cout <<a<<b<<c<<endl; } } } } return 0; }
272 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 19:06:23 ] スレ違いだな。 ここは見ての通り、C++の規格書を暗記している奴が、 C++の文法で、Bjarne Stroustrupがハゲているかどうか、 コンパイル時に判定するスレだ。 ソースコードが実用的かどうかは、どうでもいい奴らなんだよ。 重要なのは規格違反かどうかということだけだ。 まあ、大方のスレ住人もハゲてるんだけどな。
273 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 19:07:30 ] ゆとり教育のカリキュラムには順列・組み合わせとかないの?
274 名前:268 mailto:sage [2008/01/29(火) 19:08:50 ] >272 thx 俺はケツ毛までフッサフサです。
275 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 19:20:28 ] >>267 Template aliases for C++ www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1406.pdf のこと?
276 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 19:43:27 ] >>244 テンプレートじゃ無理なんか?
277 名前:245 mailto:sage [2008/01/29(火) 20:05:40 ] >>261 お、それだとVC9でもBOOST_STATIC_ASSERTが通った。 でもおかしいな、確か昔、C++ Templatesで読んで、実際に自分で試してみて、 スゲーと感動した記憶があるんだけど。 たしかVC7だったかな。 あとBoostのhas_xxxって、これ関数じゃないんだね。知らなかった。
278 名前:デフォルトの名無しさん [2008/01/29(火) 20:17:41 ] VC++6.0で開発してます。 CHttpFile::SendRequestEx() にて、 CInternetException以外の例外が発生するケースが稀にあるようなんですが、原因が特定できず悩んでいます。 そもそもCInternetException* の例外以外がスローされることってあるんでしょうか? どっかのサイトでは、CFileExceptionもスローされると書いてあったんですが・・・。 どなたか、このような経験が方いらっしゃいましたら御教授下さい。
279 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:20:17 ] スレ違い。
280 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:24:40 ] >>277 で、結局、>>244 のやりたいことは可能なのか?
281 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:26:51 ] オナニーレスばっかりだな
282 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:32:21 ] しこしこ
283 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:35:25 ] ズルムケ
284 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:35:45 ] それは鈴木ムネオの秘書だろ
285 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:46:26 ] >>280 さー? >>244 が静的な多様性でいいのかどうか分からないからなんとも。 しかし動的な多様性がほしいとすると、引っかかることも。 「ポインタで与えられる」、しかし共通のベースクラスがあるわけではないってことは、void *型で渡すんだろうか。 それだと特定のメンバ関数云々よりも、そもそもオブジェクトのクラスの型は何だってことになるし。 動的な多様性がほしい、 しかし、既存のコードはいじりたくないので、共通のベースクラスに純粋仮想関数は使えないというのなら、 例えばBoost.Anyに使われているType Erasureのテクニックが使えるかもしれない。 あの単純すぎるテクニックを使えば、かなり変態的なことができる。
286 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 20:51:54 ] >>285 変態ということはわかった
287 名前:デフォルトの名無しさん [2008/01/29(火) 22:36:43 ] あるクラスを継承しているクラス群のみを対象にメモリ割り当てをカスタマイズしたいです class Base{} class Derived1 : public Base{} class Derived2 : public Base{} そこでこれらクラス群の内、最も大きいサイズのクラスを基準に配列を静的に用意、 Base、Derived1、Derived2をnewする時に使いたいと思ってます struct AllocUnit{ char[???] buf;} ←ここのバッファのサイズを静的に求めたい static AllocUnit[MAX_UNIT] memory; //sizeof(AllocUnit)*MAX_UNIT分のバッファを静的に確保 ???の部分を求める方法がわかりません MPLを使えばできそうな感じなんですが・・・ 言い換えると、任意の数のクラスの内、サイズが最大のものをコンパイル時に取得する方法はないか? という事です↓こんなイメージ char[max_size<Base,derived1,derived2>] buf;
288 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 22:49:25 ] >>264 俺はそういう時、 template <class T1, class T2> class A { ... public: typedef A<T1, T2> this_t; }; として、バインドするクラスは template<class T1> class AInt : public typedef A<T1, int>{}; のようにpublicで継承する。 そしてクラスを記述する時はどんなものにしろ必ず A::this_t; AInt::this_t; と最後に::this_tとつける気持ち悪い習慣を身に着けている。 もしくは、 #define hogehoge(class) class::this_t のようなマクロを使うとか、いろいろ手はあるけど 結局どれもいたちごっこかうへへへへへへへへへh
289 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 22:55:38 ] >>287 こんなのでどう template <typename A, typename B> struct max_size { enum{ value = sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) }; }; template <typename A, typename B> struct max_size_chain { enum{ value = A::value > sizeof(B) ? A::value : sizeof(B) }; }; template <typename A, typename B, typename C> struct max_size3: max_size_chain<max_size<A, B>, C>{}; template <typename A, typename B, typename C, typename D> struct max_size4: max_size_chain<max_size3<A, B, C>, D>{}; template <typename A, typename B, typename C, typename D, typename E> struct max_size5: max_size_chain<max_size4<A, B, C, D>, E>{}; char buf[max_size5<char, int, short, long, void*>::value];
290 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 22:57:36 ] boost mpl if_cとかとsizeof使えばいい
291 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 22:57:48 ] template <size_t x, size_t y> struct size_t_max { static const size_t value = x > y ? x : y; } struct AllocUnit { static const size_t size = size_t_max<sizeof Derived1, sizeof Derived2>::value; char buf[size]; } 基底クラスより派生クラスの方がサイズ大きいの分かってるから 2つの比較だけでいいべ。
292 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 22:58:38 ] ミスって途中送信してる・・・。 こっちが本物。 #include <iostream> struct Base { int x; }; struct Derived1 : public Base { int n; }; struct Derived2 : public Base { int n, m; }; template <size_t x, size_t y> struct size_t_max { static const size_t value = x > y ? x : y; }; struct AllocUnit { static const size_t size = size_t_max<sizeof (Derived1), sizeof (Derived2)>::value; char buf[size]; }; int main(){ std::cout << AllocUnit::size << std::endl; } 基底クラスより派生クラスの方がサイズ大きいの分かってるから 2つの比較だけでいいべ。
293 名前:244 mailto:sage [2008/01/29(火) 23:09:34 ] 皆さんどうもありがとうございます。 なるほど、テンプレートの特殊化を利用って感じですか? こんな風に使えるんですね。 が、しかし、 >>285 >「ポインタで与えられる」、しかし共通のベースクラスがあるわけではないってことは、void *型で渡すんだろうか。 ビンゴでございます。テンプレートの場合変数の型で挙動が変化してるわけですよね。 自分は Objective-C も使うことがあるので今回のような疑問を持ったのですが。 >しかし、既存のコードはいじりたくないので、共通のベースクラスに純粋仮想関数は使えないというのなら、 とりあえず多重継承で共通のベースクラスを足すことをを検討しています。 >例えばBoost.Anyに使われているType Erasureのテクニックが使えるかもしれない。 そうですか、参照してみます。
294 名前:244 mailto:sage [2008/01/29(火) 23:15:51 ] あ、あれ、でもvoid *で渡さなくてもいいかな? ちょっと考えてみます。 でもやっぱ多重継承の方が自然かなあ。
295 名前:287 mailto:sage [2008/01/29(火) 23:16:19 ] >>289 ありがとうございます。参考にします >>292 なるほど。確かにsizeof(Base)<=sizeof(Derived)ですもんね よく考えたらgreater<T1,T2>的なモノを用意して、それを連ねていくだけでよかったんですね しかし派生クラスの数が増えるたびにmax_sizeの引数増加版を定義するのが面倒・・ 可変引数のtemplateがあればなぁ・・・
296 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 23:20:40 ] >>287 template<typename T1, typename T2, typename T3> struct MaxSize { typedef typename if_c<(sizeof(T1) > sizeof(T2)), typename if_c<(sizeof(T1) > sizeof(T3)),T1, typename if_c<(sizeof(T2) > sizeof(T3)),T2,T3>::type>::type, typename if_c<(sizeof(T2) > sizeof(T3)), T2, T3>::type >::type SizeT; static const size_t sz = sizeof(SizeT); };
297 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 23:27:59 ] マクロをゴニョゴニョすれば DEFINE_MAX_SIZE(3, 100); で max_size3〜max_size100 まで定義、みたいなこともできそうだが、 実用的には生成プログラム書いた方が楽だと思う。
298 名前:デフォルトの名無しさん [2008/01/30(水) 14:46:54 ] C++で継続(continuation)、あるいはそれっぽいことができるライブラリや、 C++で継続に関するページがあれば教えてください。
299 名前:デフォルトの名無しさん mailto:sage [2008/01/30(水) 15:44:42 ] まずお前の継続に関する経験について聞こうか? 全くC/C++以外の経験が無いとかいうレベルだとかなり大変だぞ。
300 名前:デフォルトの名無しさん [2008/01/30(水) 16:21:20 ] >>299 rubyでcallccを知り、その関連ページで勉強した程度しか知識がありません。 やりたいことは、まさにrubyのcallccで実行できるようなことです。
301 名前:デフォルトの名無しさん mailto:sage [2008/01/30(水) 16:34:55 ] 「なんでも継続」は読んだ? (Cの)setjmp/longjmpは理解してる?
302 名前:298 [2008/01/30(水) 16:40:15 ] >>301 「なんでも継続」のページ、良さそうですね。 まずここから始めてみます。 setjmp/longjmpは、Unix C上がりなので知ってます。使った記憶は1回しかありませんが…。
303 名前:デフォルトの名無しさん mailto:sage [2008/01/30(水) 18:00:53 ] >>298 Boost.Coroutine Hamigaki C++ Libraries
304 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 00:14:39 ] Hamigakiってなんかのギャグかと思って調べたらほんとにあるんだな…。
305 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 00:17:48 ] なんか最近はスーパーマリオみたいなのつくってなかったっけ
306 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 07:01:14 ] BoostにLokiのタイプリストみたいなものってありありますか?
307 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 08:16:40 ] cons list?
308 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 14:59:51 ] >>306 Boost.MPLのmpl::vector等
309 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 18:29:56 ] >>308 は?
310 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 21:06:00 ] >>309 へ?
311 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 21:18:01 ] >>310 ん?
312 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 22:17:13 ] >>311 え?
313 名前:デフォルトの名無しさん mailto:sage [2008/01/31(木) 22:18:19 ] >>312 ろ?
314 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 00:43:26 ] >>313 す?
315 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 00:49:58 ] >>314 け?
316 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 01:17:15 ] やめんか
317 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 05:30:19 ] C++的に配列はどんなものでも<vector>ライブラリを使うべきなんでしょうか?
318 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 05:43:56 ] >>317 そんなことはないけど、 ruby や python みたいな言語を触ってる人から見て 配列といって当てはまるのは std::vector でしょうね。組み込みの配列はいろいろ 歴史的な問題も残ったままだし。
319 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 07:29:58 ] >>317 サイズが完全に決まってるなら 巨大でさえなければ、 組み込みの配列を使った方が効率がいい。
320 名前:デフォルトの名無しさん [2008/02/01(金) 07:53:11 ] tr1::array早く来い来い。
321 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 12:08:03 ] 普通の配列ならスタックに蓄えられるとか、newすればヒープから領域を取ってくるとか、 配列を扱うならそこら辺の知識もあってほしいな。
322 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 14:50:07 ] alloca()
323 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 21:09:38 ] まぁ、スタックに蓄えられるとか、newすればヒープから領域を取ってくるとか 規格には書いてないけどな
324 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 21:12:53 ] new はフリーストアから領域を取ってくるんです!
325 名前:デフォルトの名無しさん mailto:sage [2008/02/01(金) 21:18:22 ] mallocはヒープから領域を取ってくるんです!
326 名前:デフォルトの名無しさん mailto:sage [2008/02/02(土) 02:37:39 ] stroustrupはどこから毛を取ってくるんです!?
327 名前:デフォルトの名無しさん mailto:sage [2008/02/02(土) 03:14:27 ] >>326 お前らがnewするたび、stroustrupから領域を割り当てられているのに ちゃんとdeleteしない奴が多いから…。 そろそろstd::bad_allocが飛んでくるぞ。
328 名前:デフォルトの名無しさん mailto:sage [2008/02/02(土) 12:39:36 ] stroustrup「virtual hair hair() = 0 はただのインタフェース! 実際のインスタンスはもっとふさふさなの! バヤには見えないんだよーだバーヤバーヤ!」
329 名前:デフォルトの名無しさん mailto:sage [2008/02/02(土) 13:50:24 ] 散々ネタに去れてるのにstroustrupのAAってなんでないんだろう。 俺が作ってやる。
330 名前:デフォルトの名無しさん mailto:sage [2008/02/02(土) 21:17:56 ] ttp://www.raw-paradise.com/
331 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 12:00:17 ] 毛量保存の法則 頭髪の少い場合、顎髭や胸毛、ギャランドゥなどで補い、最終的な毛量は一定
332 名前:デフォルトの名無しさん mailto:sage [2008/02/04(月) 12:15:26 ] ハゲで体毛も薄い人間は 代わりに心臓に毛が生えまくってるとか
333 名前:デフォルトの名無しさん [2008/02/06(水) 04:31:06 ] www.research.att.com/~bs/bs_faq2.html#delete-zero > C++ explicitly allows an implementation of delete to zero out an lvalue operand これ訳すと 「C++ は delete の実装が左辺値である対象をゼロにすることを明示的に許している」 ってことだよね? int* p = new int; delete p; delete した時点で p == 0 になるような実装もアリってこと? 規格見てもそんなことしていいなんて記述は見当たらなかった。 それとも、ただの読み違い?
334 名前:デフォルトの名無しさん mailto:sage [2008/02/06(水) 06:32:38 ] そうだよ。 auto_ptrあたりなんかはそれを頼りに実装してる
335 名前:デフォルトの名無しさん mailto:sage [2008/02/06(水) 07:40:08 ] 食い違ってるような
336 名前:デフォルトの名無しさん mailto:sage [2008/02/06(水) 07:52:37 ] 許しているだけなのにそれを頼りにしちゃいかんのでは。
337 名前:デフォルトの名無しさん mailto:sage [2008/02/06(水) 08:26:25 ] 便利のようでそうでもないかな。変な副作用はなさそうだから気にしないでおこう。