■過去ログ置き場に戻る■ 1- 前250 次250 最新50


[memo] "9999999999_00.html#R20" という感じで、URLの最後に "#RレスNo" を追加すると幸せになれます。

C++相談室 part48
501 名前:デフォルトの名無しさん :2006/04/02(日) 00:30:45
>>500
誤解してるやつが多いんだが、 const, volatile をつけるときは const_cast 使わなくていい。
危険なキャストを洗い出すときに const_cast 検索するから、つけるときは static_cast で。

502 名前:デフォルトの名無しさん :2006/04/02(日) 00:47:56
>>501
すまん、意味がわからん。
C style のキャストも const_cast も使用せずに
どうやって const, volatile を付けるん?
暗黙の変換のこと?

503 名前:デフォルトの名無しさん :2006/04/02(日) 00:48:41
>>502 「つけるときは static_cast で」

504 名前:デフォルトの名無しさん :2006/04/02(日) 01:06:33
void*からint*等へのキャストはstatic?reinterpret?
いつもはreinterpretを使ってたんだけど
あちこちでstaticの方でやってるのを見かけて自信がなくなってきてる

505 名前:デフォルトの名無しさん :2006/04/02(日) 01:08:08
>>503
ああ、すまん。そーゆー意味か。

506 名前:デフォルトの名無しさん :2006/04/02(日) 01:18:07
>>504
void* からオブジェクトポインタへの変換は static_cast 。
reinterpret_cast は間違い。

507 名前:デフォルトの名無しさん :2006/04/02(日) 01:32:10
reinterpret使うくらいならCスタイルかなぁとか思ったりする。
検索はしづらくなるけど

508 名前:デフォルトの名無しさん :2006/04/02(日) 01:32:55
reinterpret_castはbit表現のレベルで、無理やり変換する場合だけって考えていいのかな

509 名前:デフォルトの名無しさん :2006/04/02(日) 01:36:59
>>508
ビット表現が保持されると決まっているわけじゃない。

510 名前:504 :2006/04/02(日) 01:41:22
>>506
thanks

staticは安全なの、reinterpretは危険なのを強引に、
dynamicはvtable付きクラスをダウンキャスト、constはconst,volatile外し
ってイメージで使ってた。
無チェックなダウンキャストとか、継承関係に無いポインタ間のキャストは
危険そうだったからreinterpretのイメージだったけど
危険さ具合がイメージとちょっとずれてたみたい。

511 名前:デフォルトの名無しさん :2006/04/02(日) 01:41:34
>>509
む、そうなのか・・・
ちょっと適当に自分でいろいろ試すことにする

512 名前:デフォルトの名無しさん :2006/04/02(日) 01:48:42
>>510
無チェックなダウンキャストは static_cast 。
継承関係が無ければエラーになる。
reinterpret_cast だとエラーにならない。

513 名前:デフォルトの名無しさん :2006/04/02(日) 02:05:07
コンパイラの実装依存のがreinterpretで
特殊用途のdynamic,constの他は全部staticすか

514 名前:デフォルトの名無しさん :2006/04/02(日) 02:23:51
プリミティブ型のポインタ変換はstatic_castでよかったのか。

どうもいまいちreinterpret_castの使いどころがわからないんだよな。


515 名前:デフォルトの名無しさん :2006/04/02(日) 02:25:23
int i をストリームにバイナリ出力するとき、
out.write(reinterpret_cast<char*>(&i), sizeof(i));
してるんだけど、これって実装依存になるのかな?

規格中に
・ int* から void* に変換したとき、変数の記憶域の先頭を指す。
・ void* と char* は同じ内部表現を持っている。
っていうのは見つけた。
だから static_cast<char*>(static_cast<void*>(&i)) なら大丈夫そうなんだけど、
これは激しくウザイ。

516 名前:デフォルトの名無しさん :2006/04/02(日) 02:32:56
構造体をfstreamのread,writeで書き込むときって、char*にキャストするよね。
この場合はreinterpret_castでいいのかな。

517 名前:デフォルトの名無しさん :2006/04/02(日) 02:38:03
>>516
普通、絶対そんなことしないと思うが、 alignとか考えたことある?

518 名前:デフォルトの名無しさん :2006/04/02(日) 02:44:20
結論
皆キャストも満足に扱えてない。

519 名前:デフォルトの名無しさん :2006/04/02(日) 02:48:50
struct Data {
int i;
char c;
} d;
write(fp, &d, sizeof(Data));

520 名前:デフォルトの名無しさん :2006/04/02(日) 02:54:56
>>517
read, write の引数は char* なわけだが、「普通」はどうするのかね?

521 名前:デフォルトの名無しさん :2006/04/02(日) 02:56:11
>>520
void*じゃねーの

522 名前:デフォルトの名無しさん :2006/04/02(日) 03:02:16
>>521
POSIX の read, write は void* だな。
でも今話してるのは iostream の read, write で、こっちは char* になってる。

523 名前:デフォルトの名無しさん :2006/04/02(日) 03:06:02
あるクラスのインスタンスへのポインタをlistに入れた場合、
そのlistをdeleteすればそのクラスの実態まで消えるのでしょうか?

524 名前:デフォルトの名無しさん :2006/04/02(日) 03:07:47
>>523 消えない。

525 名前:デフォルトの名無しさん :2006/04/02(日) 03:14:56
>>524
別途削除ですか……

526 名前:デフォルトの名無しさん :2006/04/02(日) 03:16:29
>>525
Effective STLとかにそのへんのこと詳しく載ってる

527 名前:デフォルトの名無しさん :2006/04/02(日) 03:24:49
>>525
即レス乙です。ちょっと憂鬱読んで気になったもので……

528 名前:デフォルトの名無しさん :2006/04/02(日) 03:26:40
自分にレスしてどうする!
>>526でした。

529 名前:デフォルトの名無しさん :2006/04/02(日) 08:02:38
static_castでコンパイラに怒られたらそれっぽいcastに書き換えてるようじゃダメなのか…

530 名前:デフォルトの名無しさん :2006/04/02(日) 08:03:34
>>529
なんのためにキャストしようとしているか理解していればそんなことはおき得ない

531 名前:デフォルトの名無しさん :2006/04/02(日) 08:08:38
>>525
その他に、ポインタが指す先がすべて new で確保したもので、2カ所以上からポイントされていないという保証も必要
ポインタの列を list で扱うというパターン自体が、そもそも自動 delete を望まないか、list で作っているのが部分集合で
全体集合を作っているコンテナに破壊の仕掛けがあるような場合に使うもの

532 名前:デフォルトの名無しさん :2006/04/02(日) 08:11:23
素直にポインタでなくオブジェクトそのものを突っ込めばよくね?

533 名前:デフォルトの名無しさん :2006/04/02(日) 08:16:51
>>531
そんなときこそ delete して 0 代入イディオムですよ

534 名前:デフォルトの名無しさん :2006/04/02(日) 09:40:43
っ[boost::shared_ptr]

535 名前:デフォルトの名無しさん :2006/04/02(日) 09:48:01
>>517
alignは#pragmaでごにょごにょしました。
やっぱり変数ごとに一個ずつ読んだり書いたりしないとだめなんかな。
ファイルヘッダとかは一気に構造体で扱っちゃったほうが分かりやすいと思ったんだけど……。

536 名前:デフォルトの名無しさん :2006/04/02(日) 09:57:57
基本型しか使ってない構造体ならwrite(&struct)でいいとおもうけど。
互換性をいいだせば整数とかも文字列に変換せんといかんのじゃないか。


537 名前:デフォルトの名無しさん :2006/04/02(日) 11:29:33
えーっと、例えば、#pragmaかなんかでalignを1バイト境界に揃えた構造体、
struct A{
unsigned int data;
} a;

ifstream.read((char*)&a, sizeof(a));
したときの互換性?で致命的な問題って何があるでしょうか。
エンディアンぐらいしか思い浮かばない自分は半年ROMるべきでしょうか。


538 名前:デフォルトの名無しさん :2006/04/02(日) 14:15:52
intのサイズとか。

539 名前:デフォルトの名無しさん :2006/04/02(日) 14:20:59
>>537
思いつくのは揚げ足取り:
・alignmentを1バイト境界にできないコンパイラが存在したときに困る
・メンバにポインタや参照を含むときに望ましい結果にならない(そもそもやろうとしてないだろうけど)
・バイナリでの入出力は、どうも、C++では熟考されてない雰囲気
・アドバイス「構造体よりクラスを使え」

漏れも、たとえばWindowsBMP(DIB)のBITMAPINFOHEADERのような場合、
#pragma等でごにょってread(&struct)してるよ。ついでにoperator>>()も定義して
BITMAPFILEHEADER bf;
cin >> bf;

540 名前:539 :2006/04/02(日) 14:40:13
> C++では熟考されてない雰囲気

これの意味は、バイナリ入出力では「型のビット表現」そのままを入出力するしかできないので、
型の大きさ(char単位の大きさ)、エンディアン、浮動小数点なら各ビットの意味など
判別・読み書き時にC++ライブラリの支援がない(支援ができない)。

そもそも、読み書きすべきバイナリデータが、C++だけで使われるとは限らない。
アマゴサ星系のエル・オーリアン人が、彼らの特殊言語で読み書きするかもしれない。

バイナリで扱うなら、ファイルの先頭あたりにUTFのBOMのようなものを入れるしかない。
「安全」さを求めるならテキスト入出力を使うべきなんだろう。

非現実的だが。

>>538
その問題は、read((char*)&a, sizeof(a))の問題ではなく、バイナリ入出力自体の問題じゃないかな。

541 名前:デフォルトの名無しさん :2006/04/02(日) 14:49:56
gimpのbmpヘッダ書き込みのところのソースとか見てみたら
構造体のメンバを一つずつファイルに書き込んでたから
アラインメントとか考えるとこういう風になっちゃうのかなー
と思って、おれもそうしてた

まあ、C言語だけど

542 名前:デフォルトの名無しさん :2006/04/02(日) 14:59:04
>>538-539
・実際はtypedefしたdwordなので、intのサイズが違ったらtypedefを書き換えればいいかなぁとか。
・1バイト境界に出来ないコンパイラは考えてませんでした。反省。
・ポインタを含むようなら当然このような手段は取らないです。
・C++ではストリーム使うべきかなと思ったんですが……やめたほうがいいですかね。
・単にデータをバインドするだけの使い方をしたかったので、純粋な構造体を使いました。
 構造体はこういう使い方をするべきではないでしょうか。
 実際はファイルを扱うクラスのreadメンバ関数の中で処理してます。
 virtualメンバ関数があるとsizeofがずれてしまうので構造体なんですけども。
>BITMAPINFOHEADER
 はい、まさにそんな感じです。

ifstream.readを変数分全部書くと、構造体メンバの変更があったときコードにも影響が出ますよね。
もっといい書き方あるんでしょうか。


543 名前:デフォルトの名無しさん :2006/04/02(日) 15:03:10
ファイルフォーマットとかプロトコルっていうものをちゃんと
考えれば、ほぼ必然的に int とか struct をそのまま write
したりは出来なくなるよね。

定義されてる(or 定義した) とおりのデータを、定義どおりの順に
定義どおりのサイズで読み書きする。たまたまパディングを調整
できるコンパイラで、バイトオーダーもあっていれば struct とかも使える。
そんだけのこと。

544 名前:542 :2006/04/02(日) 15:08:52
長々と書いてたらその間にレスが……
>>540
可搬性を求めると問題は尽きないんですね……。
>>541
やっぱりそうなっちゃいますか〜。
>>543
なるほど……良くわかりました。
変数を全部読み込む手間 <-> 一度に読み込むリスク
でトレードオフってことですね。

545 名前:デフォルトの名無しさん :2006/04/02(日) 15:27:22
プラットフォーム固定なら align してベタ書きでいいと思うけどね。
GUI ならどうせ他の色んな所でプラットフォーム固定のコードを書かざるを得ないだろうし、
ファイルの読み書きのところだけ可搬性を重視してもナンセンスかと。

546 名前:542 :2006/04/02(日) 15:34:45
GUI部分は別にして、コアだけ作っていたので、
ある程度汎用性があったほうがよいかと思って色々と考えていました。
でも確かにここだけ可搬性を求めても仕方ないですね。
align指定と構造体で置いておくことにします。
色々とどうもありがとうございました。

547 名前:デフォルトの名無しさん :2006/04/02(日) 18:35:19
C++ なら、読み書きを構造体のメンバ関数として提供しておけば、
プラットフォームを変更したところで、
その構造体のところの定義をいじっただけで済むと思われ。

548 名前:デフォルトの名無しさん :2006/04/02(日) 21:00:28
個人的にはメンバ関数を持った構造体にalignmentを指定したくないんですけど、杞憂でしょうか。
何か気持悪いんですが……。

549 名前:デフォルトの名無しさん :2006/04/02(日) 21:12:14
>>548
個人的には彼女を持ったからオナニーをしたくないんですけど、杞憂でしょうか。
何か気持悪いんですが……。


と言われてる気分だ。お前の勝手にしろ。


550 名前:デフォルトの名無しさん :2006/04/02(日) 21:37:05
ちょっと前からバイナリ出入力と関連してアライメントの話が出てくるが、関係がわからん。
普通に sizeof 使ってたらアライメントも問題にならないと思うんだけど。

551 名前:デフォルトの名無しさん :2006/04/02(日) 21:39:07
>>550
別環境では、ずれる可能性があるって話では?

552 名前:デフォルトの名無しさん :2006/04/02(日) 21:48:24
>>551
別環境だったらサイズやビット表現も違う可能性もあるだろ。
アライメントだけ指定する意味が無い。

553 名前:デフォルトの名無しさん :2006/04/02(日) 22:14:21
>>548
仮想関数さえなければ大丈夫だろ。

554 名前:デフォルトの名無しさん :2006/04/02(日) 22:15:30
>>552
そんなもん織り込み済みで話してる

555 名前:デフォルトの名無しさん :2006/04/02(日) 22:15:48
>>553
仮想関数があってもなくても関係ない。「好きにしろ」で終わり。

556 名前:デフォルトの名無しさん :2006/04/02(日) 22:19:38
お好きなまでに…

557 名前:デフォルトの名無しさん :2006/04/02(日) 22:19:58
>>555
仮想関数テーブルへのアドレスが読み書きされちゃうじゃん。

558 名前:デフォルトの名無しさん :2006/04/02(日) 22:23:31
>>557 それとアライメント指定の是非に何の関係が?

559 名前:デフォルトの名無しさん :2006/04/02(日) 22:28:29
>>554
じゃぁ >>550 の答えは?

560 名前:デフォルトの名無しさん :2006/04/02(日) 22:39:25
>>559
 漏れ個人的にはグローバルなコンパイルオプションなんかで
(ファイル書き出しなどに使う)構造体のレイアウトが変わったら
イヤだから、#pragma pack とかでアライメントは指定してる。

関連プログラム全部同じオプションでコンパイルするしー、とか
未来永劫アライメントなんか変えないしー、
っていう人なら確かにいらんかもしれないな。

561 名前:デフォルトの名無しさん :2006/04/02(日) 23:00:29
VCとx86系を使ってますが、
コンパイラが勝手にintとかshortをワード、ダブルワード境界に揃えてしまいました。
それでは構造体で一気に読み込むとパディングのせいで実際のファイル構造とずれてしまうので、
#pragmaでアライメントをバイト境界に指定するわけですが、
#pragmaの機能は当然処理系依存機能なので余り広範囲に使いたくありません。
(コンパイラを変更したら#pragmaを恐らく変更しなければならない)
エンディアンはこの際おいておいても、同一の性質を持つ記述を散在させるのは気持ちが悪いので、
PODのみを持つ構造体にアライメントを指定しておいて、それを扱うクラスにはアライメントを干渉させないように
したのです。


562 名前:デフォルトの名無しさん :2006/04/02(日) 23:07:28
>>560
なんか感覚おかしくね?
将来的なことを心配するならアライメント依存しない方法を選ぶだろ。

563 名前:デフォルトの名無しさん :2006/04/02(日) 23:10:23
「構造体を一気に読む」自体が処理系依存なわけで。

564 名前:デフォルトの名無しさん :2006/04/02(日) 23:36:39
メモリダンプ・ロードなんてどう考えたってハックじゃん。
そんなの使う場所で環境依存云々言ったって五十歩百歩。

565 名前:デフォルトの名無しさん :2006/04/02(日) 23:44:09
>>勝手にしろ、好きにしろ
皆さんのお考えを聞いてみたかったのです……。

>>558
仮想関数を持ったクラスはsizeofの値が増加します(VCでは増えました、処理系によるかもしれません)。
この場合alignmentではなくこの増加分がどこに収められるかが心配なのです。
sizeofでサイズをとっての読み書きを想定しているので、
sizeofがずれるとread(&struct, sizeofA)では問題があるのです。

>>562
プログラムがalignmentに依存しないとしても、ファイルフォーマットは固定されてます。
構造体で一気に読むとしたらalignmentは少なからず関与してくると思います。

>>563
処理系依存なのはalignとエンディアンとパディングの大きさだけかと思っていました。
構造体一気読み自体が処理系依存とはどういうことでしょうか。
fstreamの仕様に関わることでしょうか。

>>564
ハックになってしまいますか。
メモリダンプというよりバイナリファイルダンプに近いんですけど。

なんだか収まりがつかなくなってきてしまったので、最後に皆様に率直にお聞きします。
私の構造体一気読みのコードを保守する羽目になったら私を殺そうと思いますか?

566 名前:デフォルトの名無しさん :2006/04/02(日) 23:47:25
>>519がまともに使えると思ってるやつばっかり、ってことだろ?

567 名前:デフォルトの名無しさん :2006/04/02(日) 23:48:42
構造体のメンバのメモリ上での順番はC++では規定されてたっけ?
あとchar以外の変数のサイズは処理系依存だけど。

568 名前:デフォルトの名無しさん :2006/04/02(日) 23:52:25
alignとエンディアンとパディングが処理系依存なわけだから、
それを前提にしている構造体一気読みも当然処理系依存だろ。

>565
Win32上の処理系だと、COMの関係で、vtblはクラスの先頭に
もってきてる可能性が高い。

569 名前:デフォルトの名無しさん :2006/04/03(月) 00:04:13
厳しい現実を言うと char のビット数すらも固定ではなかったり

570 名前:デフォルトの名無しさん :2006/04/03(月) 00:11:49
だが、unsigned char の最大値が255以上
sizeof(char)==1
であることは規定されている

571 名前:542 :2006/04/03(月) 00:28:49
>>567
共用体ではないクラスの非静的データメンバがアクセス指定子が間に入らずに宣言された場合、
後で宣言されたデータメンバのほうがクラスオブジェクト内でより高位のアドレスになるように割り当てられる。
(X3014:2003より引用)
らしいです。
型のサイズについては>>542の最初の項のとおりです。

>>568
そうですね……。
3つの条件をクリアしたらいいのだろうか、と思いましたが、
よく考えるとつまりそれが処理系依存でした。

処理系依存でOKなら一気でもOK
ダメなら一個ずつ読み書きしなさい、ということですね。

572 名前:デフォルトの名無しさん :2006/04/03(月) 00:35:10
>>565
結局「勝手にしろ、好きにしろ」としかいえないのが現実なんじゃないの?

構造体一気読みはコードを書くのが簡単だし、パフォーマンス上好ましいことも
あるだろう(fstreamを使っている時点でアレかもしれんが)。

他プラットフォームへの移植性が求められるなら、一バイトずつ読み書きするのが
比較的良い方法になるだろう。それでもC++の規格はすべての環境で同じファイル
フォーマットが使えることを保証してはくれないだろうけど。

その気があれば、移植するすべてのプラットフォームごとにマクロで実装を
切り替えたっていい。

プラットフォームごとの違いを吸収してくれるバイナリ入出力ライブラリ
みたいなものを作ってもいい。

好きにしろ。


573 名前:542 :2006/04/03(月) 00:51:29
>>572
読み込むにしても、もっとよい策が無いかなぁと思ったものですから、
経験豊富そうな方がいそうなここへ書き込んだしだいです。

少なくとも私の考えた策は処理系依存を気にしないなら使えることが分かりましたし、
可搬性や移植性を考えるならすべきでは無いことも分かりましたので、
後は好きにさせていただきます。
色々と為になる書き込みを戴きました。
どうもありがとうございました。


574 名前:デフォルトの名無しさん :2006/04/03(月) 02:05:24
boost::serializationてどうなんだっけ?

575 名前:デフォルトの名無しさん :2006/04/03(月) 02:06:13
Boostのテンプレートライブラリ

576 名前:デフォルトの名無しさん :2006/04/03(月) 02:17:40
どうせ標準ライブラリの範囲だけでプログラムつくらないから互換性なんか無視っす。

577 名前:デフォルトの名無しさん :2006/04/03(月) 09:34:45
>>576 意味不明だな。

578 名前:デフォルトの名無しさん :2006/04/03(月) 16:01:05
もう終わった話題だからアレだけど、
例えばWin32 APIなんかだと構造体の最初のメンバが自分自身のsizeofを保持するケースがけっこうある。
先の例のBITMAPINFOHEADERでも、
 unsigned long biSize; // 構造体のサイズ(バイト)
なんてメンバがある。
バイナリ入出力以前に、alignmentをバイト境界にしておかないと、こういうケースでハマると思うんだけど。
(構造体のサイズをハードコーディングするか、#pragmaごにょごにょ)


で、まぁ、なにがいいたいかというと…
alignment、endian、padding、メモリ上のビット表現を考慮し、
各環境で最適なコードで(一気読みできるならそうして、1バイトずつ変換が必要ならそうする)、
ストリームとバイナリ入出力してくれるような
可搬性のあるバイナリ入出力ライブラリ誰か作って…!

579 名前:デフォルトの名無しさん :2006/04/03(月) 16:29:45
>>578
バイト境界でなくても整合性さえ取れていれば問題ないと MSDN に書かれてます。

580 名前:デフォルトの名無しさん :2006/04/03(月) 20:44:44
>>572
以前実測したが、fstreamとFILE*は、readで一気読みする分には処理速度変わんないよ。
IOがでかすぎるせいで、差が消えちゃう。

581 名前:デフォルトの名無しさん :2006/04/03(月) 20:51:43
っていうか fstream や FILE はバッファ有るからまとめてI/Oしてるよね。
Unix の read() や Windows の ReadFile で細かい単位で読み書きしたり
すると、あるべき速度の10倍くらい遅いプログラムも簡単に作ることができる。

582 名前:デフォルトの名無しさん :2006/04/04(火) 16:41:00
sort用に、Fooクラスの2つの引数を持つ比較関数オブジェクトを作ろうと思ったのですが、
考えてみれば関数オブジェクトから、Fooクラスのprivateメンバにはアクセスできないっす。
これは一々getter用意するなり、friendにせざるを得ないんすかね。

と、言いますか、operator=や、operator<なんかが、他オブジェクトのprivateメンバにアクセスできるのは、
どの辺に規定されてるんすかね。ドラフト見てもいまいち分からないっす…。

583 名前:デフォルトの名無しさん :2006/04/04(火) 16:45:24
>>582
Fooクラスにoperator<を持たせりゃいいじゃん。
それと、operatorなんとかのスコープは関数と同じ。どういう宣言を
されてるかだけによる。

584 名前:582 :2006/04/04(火) 16:53:28
>>583
レスサンクスです。後者は勘違いしてました。
自分と同じクラスのprivateメンバなら、他オブジェクトでもアクセス出来ちゃうってことすか…。
何か納得いかないすが、理解できました。

何通りかでsortしたいんすが、「Fooクラスにoperator<を〜」では、一つしか賄えなくて困ってるっす。
でもgetterなりしか無いようでしたら、諦めるっす。

585 名前:デフォルトの名無しさん :2006/04/04(火) 17:15:03
>>584
関数オブジェクトのコンストラクタに引数をとるという方法は?
引数によって、どういう比較をするか、決めればいいのでは?

586 名前:デフォルトの名無しさん :2006/04/04(火) 17:19:21
内部構造を知らないとかけないコンパレータは内部に書くのが普通。
外部から与えるコンパレータが内部構造に依存するのは道理としておかしい

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Foo {
  int a, b;
public:
  Foo(int a, int b) : a(a), b(b) { }
  bool operator < (const Foo& o) const { return cmp_ab(*this, o); }
  static bool cmp_ab(const Foo &lhs, const Foo &rhs) { 
    return lhs.a != rhs.a ? lhs.a < rhs.a : lhs.b < rhs.b; }
  static bool cmp_ba(const Foo &lhs, const Foo &rhs) { 
    return lhs.b != rhs.b ? lhs.b < rhs.b : lhs.a < rhs.a; }
};
int main() {
  vector<Foo> v;
  v.push_back(Foo(0,2));v.push_back(Foo(1,1));v.push_back(Foo(2,0));
  sort(v.begin(), v.end(), Foo::cmp_ab);
  sort(v.begin(), v.end(), Foo::cmp_ba);
}

587 名前:デフォルトの名無しさん :2006/04/04(火) 18:13:15
>>586
関数オブジェクトの形にしないでもsortって使えるんですね。
見た目もすっきり。ありがとうございました。585さんもサンクス。

588 名前:デフォルトの名無しさん :2006/04/05(水) 18:35:05
皆さんの知恵をお借りしたい。

クラスのメンバ内に次のような宣言があるとします。

public:
  int num0;
  int& operator=(int num1);

int& operator=(int num1); が呼ばれないようにひっそりと num0に
NULL を入れるにはどうやればいいですか?


589 名前:デフォルトの名無しさん :2006/04/05(水) 18:41:09
>>588
代入演算子はコピーには適用されなかったと思うからそうすりゃいいんじゃね?

590 名前:デフォルトの名無しさん :2006/04/05(水) 18:48:07
class A {
public:
  int num0;
  int& operator=(int num1);
};
main()
{
A a;
a.num0 = 0;
}

591 名前:デフォルトの名無しさん :2006/04/05(水) 18:54:37
>>589 コピーには適用されないってどういうこと?
コピーコンストラクタを作れってこと?

592 名前:デフォルトの名無しさん :2006/04/05(水) 19:34:03
int& operator=(int num1);
がnum0に代入するときに呼ばれると思ってるのか?

593 名前:デフォルトの名無しさん :2006/04/05(水) 21:03:02
一瞬コピーコンストラクタと代入演算子の区別の話だと思ったが
よく読むと全く意図の分からない電波質問だな

594 名前:デフォルトの名無しさん :2006/04/05(水) 21:28:33
・int型にNULL
・メンバ変数がpublic
・operator=で何をさせたいのかが不明


595 名前:ガウショ :2006/04/05(水) 22:18:01
さて、ここで低レベルな質問です。

char *型の引数で結果を受け取る関数ありますよね?
あれをstd::stringで受け取れるようにしたいです。

理想(無理だけど)↓
string s;
sprintf(s.data(),"aaa");
とか
string s;
GetDlgItemText(hWnd,ID,s.data(),256);

何かいい方法があったら教えて下さい。

596 名前:デフォルトの名無しさん :2006/04/05(水) 22:19:23
よくわからんけど、コンストラクタで初期化すればいいんじゃね

597 名前:デフォルトの名無しさん :2006/04/05(水) 22:20:54
&s[0]

598 名前:デフォルトの名無しさん :2006/04/05(水) 22:23:41
>>595
一時バッファ用意するしか無いと思う。

>>596
わかってなさすぎだと思う。

599 名前:デフォルトの名無しさん :2006/04/05(水) 22:24:42
#pragma once
#ifdef __cplusplus
BOOL GetDlgItemText(HWND, std::string&);
#endif

600 名前:デフォルトの名無しさん :2006/04/05(水) 22:24:53
>>597
std::stringってvectorの様に連続性が保証されてなかったんじゃなかったっけ?

601 名前:596 :2006/04/05(水) 22:25:09
>>598
すまん、これ>>588への返答のつもり

602 名前:デフォルトの名無しさん :2006/04/05(水) 22:27:44
>>599
特に何も解決してなくね?

603 名前:デフォルトの名無しさん :2006/04/05(水) 22:28:16
>>601
コンストラクタで初期化せんでも、単に代入すればいいじゃん。
publicなんだし、num0への代入にoperator=は何も関与しないし。

604 名前:デフォルトの名無しさん :2006/04/05(水) 22:31:43
>>603
ひっそりと、っていうからクラスを利用する側に意識させたくないのかと思ったけど
それもそうか

605 名前:ガウショ :2006/04/05(水) 22:35:03
>>お答え頂いた皆さん
ありがとうございます!

>>598
やってみます。

606 名前:ガウショ :2006/04/05(水) 23:00:39
解決できましたー

607 名前:デフォルトの名無しさん :2006/04/05(水) 23:03:53
srand((unsigned)time(NULL));
ransu=rand()%100;
とやっても生成された乱数が同じ数字が三連発されたり等でかなり「つかえねー」のですが
もっとゲームなどに適した乱数関数ってありますか?

608 名前:デフォルトの名無しさん :2006/04/05(水) 23:04:53
>>607
Mersenne Twister

609 名前:デフォルトの名無しさん :2006/04/05(水) 23:05:27
boost::random

610 名前:デフォルトの名無しさん :2006/04/05(水) 23:09:06
>>595
sprintfの代替にはboost::formatがある。

後者は自分でstd::string(というよりもおそらくstd::basic_string<TCHAR>)を受け取る関数を作るしかない。
ただし>>600に注意。

スレ違いな回答をするが、
ATL::CWindow::GetWindowTextならATL::CStringで受け取れる。
またATL::CStringにはFormatというsprintfの代替がある。
MFCのCWndとCStringでも可。

611 名前:ガウショ :2006/04/05(水) 23:18:44
コンポジションだっけ?
stringをメンバにして自作クラスつくりまふ。
んでreserveして文字列受け取るメソッド作る。

cString s;
sprintf(s.GetCStr(),"aaa");

みたいな

612 名前:ガウショ :2006/04/05(水) 23:33:45
age過ぎましたorz

613 名前:デフォルトの名無しさん :2006/04/05(水) 23:40:40
>>611
なんかそんなのboostにあったような無かったような…

614 名前:607 :2006/04/05(水) 23:43:54
>>608
サンクス。
早速使ってみますた。
あまりの格の差に笑いすらこみ上げますた。

…rand()なんて薦める本は全部焼却処分したい気持ちだw

615 名前:デフォルトの名無しさん :2006/04/05(水) 23:47:48
それにしてもここまでstd::ostringstreamが全く出てこないとは……。

616 名前:デフォルトの名無しさん :2006/04/05(水) 23:51:12
薦めてる本なんて無いだろ。

boostは標準じゃないんだから、書きたくても書けない。

あと、標準のrandも、実装によってはMTが使われる場合もある。

617 名前:デフォルトの名無しさん :2006/04/06(木) 00:27:28
>>607で同じ数値が三連発、というのは
どこかrandの使い方を間違えてるように見えるんだけど

もしかしてrandを使うたびにsrandしてない?

618 名前:デフォルトの名無しさん :2006/04/06(木) 01:16:44
はじめまして。
お世話になります。
開発環境:WindowsXP VC++6.0 MFC使用

ダイアログベースで画面を作成(A.exe CDialogベース)し、その画面でボタンを押下し
子画面(A_Child)を表示させます。表示方法はDoModal()で。
そのA_ChildはCDialogベースです。

A_Childダイアログが表示されている間(最前面)は、デスクトップ上の操作を
何も出来ない様にしたいのですが、方法はありますでしょうか?
(例:スタート→ログオフでダイアログが表示しますよね。
その時ってそのダイアログ以外は触れないですよね。)

せめて、自分たちが作成したアプリだけでも操作不可能にしたいのです。
SetWindowPos()、ModifyStyle()、色々試しましたが上手くいきません。
DoModalで表示させるのがそもそもまちがいののでしょうか?

何か方法が有りましたらよろしくお願いします。

説明が下手ですみません。

PS
システムモーダルのチェックONで常に最前面に表示されているのですが
後ろの画面等が操作できてしまうんです・・・・。

619 名前:デフォルトの名無しさん :2006/04/06(木) 01:33:30
MFCのモーダルって本当はモードレスで見かけ上モーダルのふりをしてるんだっけ? スレ違いすまそ

620 名前:デフォルトの名無しさん :2006/04/06(木) 01:34:41
>>618
スレ違い

621 名前:デフォルトの名無しさん :2006/04/06(木) 02:10:35
>>617
そうだな。ありがちなのはtime()が一秒ぐらい同じ値を返すから、srandに3回ぐらい同じ値を
渡してるとか。

622 名前:デフォルトの名無しさん :2006/04/06(木) 02:30:12
それとは別に、rand()%100とやるのも良くない。

(int) (100.0 * rand() / (RAND_MAX + 1.0))

のように上位ビットを用いなくては均等な乱数にならない。

623 名前:デフォルトの名無しさん :2006/04/06(木) 02:40:23
>>622
最近ではそれを考慮して実装されてるとどこかで聞いた。
ちょいと実験してみる。

624 名前:デフォルトの名無しさん :2006/04/06(木) 02:46:07
>>623
operator%を定義してるのかなー、とか考えてしまったではないか・・・w
キニシナイでおくれ

625 名前:デフォルトの名無しさん :2006/04/06(木) 04:09:09
operator(・ ・)
みたいなのって定義出来ないの?オッパイ

626 名前:デフォルトの名無しさん :2006/04/06(木) 05:51:08
>>616
rand()をMersenne-Twister使って実装してるような処理系あるか?

627 名前:デフォルトの名無しさん :2006/04/06(木) 12:00:19
typedef struct {
 double X;     //X座標
 double Y;     //Y座標
} SCoord ;      //座標構造体
vector<SCoord*> CoordsList;   //座標構造体へのポインタ列を格納するベクタ
srand((unsigned)time( NULL ));  //乱数の初期化
for (unsigned int i=0; i<10; i++){
 SCoord* pTempCoord;
 pTempCoord = new SCoord;
 SCoord->X = (double)rand();  //乱数で座標を生成、代入
 SCoord->Y = (double)rand();
 CoordsList.push_back(pTempCoord);
}    //座標構造体のインスタンスを10個作ってポインタを格納

念のためファイルに
ofstreamfout("出力先ファイル.txt");
for (unsigned int i = 0; i < CoordsList.size(); i++){
 SCoord* pTempCoord;
 pTempCoord = (BeadsList[i]);
 fout << "X座標 " << pTempCoord->X << ", Y座標 " << pTempCoord->Y << endl;
}
で出力したところ、正しい値のように見えます。

ここで、pTempCoordはスコープの外ですが、そのポインタはCoordsListに保存
されています。また、newでインスタンスを確保しているので、deleteで開放
するまでメモリが開放されるわけではないと思うのですが、問題あるでしょうか?


628 名前:デフォルトの名無しさん :2006/04/06(木) 12:07:59
>>627
問題ない。

>SCoord->X = (double)rand();
pTempCoord->Xの間違いか?

629 名前:デフォルトの名無しさん :2006/04/06(木) 13:05:46
>>628
そのとおりです。(__);



630 名前:デフォルトの名無しさん :2006/04/06(木) 13:19:42
次の質問です。
typedef struct {
 double X;     //X座標
 double Y;     //Y座標
} SCoord ;      //座標構造体
vector<SCoord*> CoordsList;   //座標構造体へのポインタ列を格納するベクタ
srand((unsigned)time( NULL ));  //乱数の初期化
for (unsigned int i=0; i<10; i++){
 SCoord* pTempCoord;
 pTempCoord = new SCoord;
 pTempCoord->X = (double)rand();  //乱数で座標を生成、代入
 pTempCoord->Y = (double)rand();
 CoordsList.push_back(pTempCoord);
}    //座標構造体のインスタンスを10個作ってポインタを格納

使用済み座標構造体のインスタンスをメモリから削除するつもり
for (unsigned int i = 0; i < CoordsList.size(); i++){
 delete CoordsList[i];
}
CoordsList.clear();   //オートポインタなので不要とは思うが、念のためベクタをクリア

ベクタに格納したポインタは特に放置してもプログラム終了とともに自動消滅するでしょうけど、
構造体のインスタンスはプログラム終了後もメモリに残ると思います。それで構造体のインス
タンスを個別に開放しようとしているのですが、プログラムが異常終了してしまいます。
どこに問題があるのでしょうか?


631 名前:デフォルトの名無しさん :2006/04/06(木) 13:54:48
>>630
問題ないようだけど?
> プログラムが異常終了してしまいます
をもっと具体的に。

632 名前:デフォルトの名無しさん :2006/04/06(木) 13:56:52
>>630
for (unsigned int i = 0; i < CoordsList.size(); i++){


633 名前:デフォルトの名無しさん :2006/04/06(木) 13:59:39
>>632
それの何処に問題が?

634 名前:632 :2006/04/06(木) 14:03:11
すまんボケてた


635 名前:デフォルトの名無しさん :2006/04/06(木) 14:46:18
>>630
>構造体のインスタンスはプログラム終了後もメモリに残ると思います。
OS のないシステムなんですか?

>//オートポインタなので
何が?

で、どこでコケてるんですか?

636 名前:デフォルトの名無しさん :2006/04/06(木) 15:06:23
使っている処理系はBorland Developpers Studio 2006のC++Builder10 なの
ですが、デバッガでステップ実行したら、>>630で書いたコードまで終了した
ところで、ソースファイルControls.pasが見つかりません。というダイアログ
が開き、パスを入力するようになりました。
Controls.pasって多分C++BuilderのGUI関連のライブラリのソースで、普通に
インストールすれば、ユーザーが知らなくても処理に必要なら処理系は知ってる
はずと思うのですが...
for (unsigned int i = 0; i < CoordsList.size(); i++){
 delete CoordsList[i];
}
の部分をコメントアウトするとメモリリークしてるかもしれませんが正常終了します。
for (unsigned int i = 0; i < CoordsList.size(); i++){
 SCoord* pTempCoord;
 pTempCoord = CoordsList[i];
 delete pTempCoord;
}

for (unsigned int i = 0; i < CoordsList.size(); i++){
 delete (SCoord*)CoordsList[i];
}
に、変更しても同じなので、ポインタのデータサイズがわからなくなると
いった問題ではなさそうです。


637 名前:デフォルトの名無しさん :2006/04/06(木) 15:07:43
実行ファイルを開いた瞬間他のプログラムを開くという処理はどうすればいいのか教えてくれ。

638 名前:デフォルトの名無しさん :2006/04/06(木) 15:13:44
system

639 名前:デフォルトの名無しさん :2006/04/06(木) 15:14:09
std::systemをmainの先頭からでも呼んだらどうだ?

640 名前:デフォルトの名無しさん :2006/04/06(木) 15:24:17
>>636
標準C++の範囲では、見たところソースコードに問題ない。
あくまでも趣味の違いだが、SCoord生成時はnew代入じゃなく初期化時new、削除はイテレータを使うくらいか?:
Sccord* pTempCoord = new SCoord;
for (vector<SCoord*>::iterator it = CoordsList.begin(); it != CoordsList.end(); ++it) delete *it;

Controls.pasは、処理系依存の問題なので、スレ違い。

C++Builder相談室 Part16
http://pc8.2ch.net/test/read.cgi/tech/1138766165/l50

641 名前:デフォルトの名無しさん :2006/04/06(木) 15:25:40
いや、>>637は、自分の実行ファイルと入っていない。
何か実行ファイルを開いたとき、他のプログラムを開きたいのだろう。
そして、環境もいわないという傲慢さだ。

そうだなぁ……。
大抵のOSでは、実行するシステムコールもしくはAPIなどがあるから、それをフックして……。

642 名前:637 :2006/04/06(木) 15:33:49
WinXP VC++6
組みたいプログラムは実行ファイルを開くと他の実行ファイルをオープンさせるという仕組みのプログラムです。
つまり実行ファイルを開いたらブラウザやテキストエディタを起動するようなプログラムを作りたいってこと。

643 名前:デフォルトの名無しさん :2006/04/06(木) 15:36:48
だからstd::systemで対象のexe叩けばいいだろ


>>636
C++Builderなんていう腐りきった処理系は窓から投げ捨てろ

644 名前:デフォルトの名無しさん :2006/04/06(木) 15:37:48
>>640
ありがとうございました。どうも処理系依存の問題のようですから
C++Builder相談室 Part16に行ってみます。


645 名前:デフォルトの名無しさん :2006/04/06(木) 15:44:50
>>643
windows用のC++用開発ツールで、お勧めの腐りきってない処理系って
何ですか?...VC6からC++Builderに逃げ出したのですが...


646 名前:デフォルトの名無しさん :2006/04/06(木) 15:45:28
>>642
WinだったらShellExecuteだけど、スレ違いだから他行ってね。

647 名前:デフォルトの名無しさん :2006/04/06(木) 15:55:46
>>645 VC++ じゃなんでだめなの?
2005 Express Edition じゃだめ?

648 名前:デフォルトの名無しさん :2006/04/06(木) 16:10:17
>>645
別にC++Builderでもいいと思うぞ。
少なくとも、VCLは優れたライブラリだと思う。いささか古い設計ではあるけどね。
今後の発展(標準C++やC++0xへの準拠)はもう望めないけれど、
Win専用GUIつきユーティリティ開発なら悪い選択肢ではない。

漏れはgcc/icc+wxWidgets でもこれは他人におすすめできない。

649 名前:デフォルトの名無しさん :2006/04/06(木) 16:19:20
>>647
2005 Express Edition ってVCの新バージョンですか?
乗り換えた頃はVC6で、正確には覚えていないけど、
std::でコンパイルできないことがいくつかあったことと
BCB6にはposix互換関数が揃っていて、UNIXやLinuxへの
移植性があるプログラムが書けると思いました。
IDEのエディタがVCより更にひどかったけど、秀丸を
併用して、セーブしてIDEに戻ると、ソースが変更されました、
読み直しますか?と聞いてくるので、Yes、再コンパイルで
エディタの悪さはカバーできたし...VCLのソースが
パスカルって言うのは気になったけど、ブラックボックスだと
思えばWinMain関数まで隠してしまうMFCよりはましに思えたし...

...で、2005 Express Edition ってBCB10と比べてどういいの?


650 名前:デフォルトの名無しさん :2006/04/06(木) 16:21:48
VC++2005は、、、
やたらと重かったりインテリセンスが鈍くて困る
VC++2003から乗り換える理由が見つからん
BCBよりはマシじゃね

651 名前:デフォルトの名無しさん :2006/04/06(木) 16:33:53
VC++2005ExpressEdition使ってるけど別に不便なことはない
リソースエディタ付いてないけどそういうの使わないし
てか発売されてるのは高杉
落とせばいいけど開発者としてなんだか悪い希ガス

652 名前:デフォルトの名無しさん :2006/04/06(木) 16:44:13
>>651
>落とせばいいけど開発者としてなんだか悪い希ガス
なんで?これMSが無償配布してるんだよね


653 名前:デフォルトの名無しさん :2006/04/06(木) 16:46:08
環境依存ネタは他スレでよろ

654 名前:デフォルトの名無しさん :2006/04/06(木) 16:47:18
>>652
それとは別の発売されてる方だろ

雑談終了

655 名前:デフォルトの名無しさん :2006/04/06(木) 16:50:19
VC6の頃、MSDNプロフェッショナルは、年間7万円弱で、
OSとVSが使い放題だった時期があったけど、今は高すぎ。
OS供給だけのMSDNに入ってる。


656 名前:デフォルトの名無しさん :2006/04/06(木) 16:55:27
ここってソースupしたら赤ペン先生してくれますか?

657 名前:デフォルトの名無しさん :2006/04/06(木) 16:56:17
たまにしてくれる人もいるよ
暗号化されたソース読むのも勉強になるし

658 名前:デフォルトの名無しさん :2006/04/06(木) 17:19:07
boost::format というsprintf 相当のモノはあっても、
sscanf に該当するものがないのは寂しいな。

659 名前:デフォルトの名無しさん :2006/04/06(木) 17:20:53
>>658
stringstreamは?


660 名前:デフォルトの名無しさん :2006/04/06(木) 17:25:34
>>659
逆だろ

661 名前:デフォルトの名無しさん :2006/04/06(木) 17:26:59
あーすまんistringstream忘れてた

662 名前:デフォルトの名無しさん :2006/04/06(木) 17:56:03
>>661
いや、stringstream があるのに、boost::format が出来たのは、
マニュピレータの指定が面倒だからでしょ。

たとえば、"0123456789ABCDEF" という入力があったとして、
これを、4桁ずつの16進数と解釈して4つの整数変数に設定したい
みたいな要望があったとき、
sscanf( in, "%4X%4X%4X%4X", out1, out2, out3, out5 );
みたいに型安全に書けたら便利かなってこと。

663 名前:デフォルトの名無しさん :2006/04/06(木) 17:58:32
型安全というからには、フォーマット文字列と型が不一致のときは例外でも投げて欲しかった。

664 名前:デフォルトの名無しさん :2006/04/06(木) 18:17:29
ありゃ、例外発生しないんだ・・・
これから使ってみようかなと思ってたのに。

665 名前:デフォルトの名無しさん :2006/04/06(木) 18:22:43
引数の数が足りないときは例外が投げられるし、投げられないようにも出来る。

>663が言う件では、投げられないとしても問題が無い部分だ。
let's boostの人がそう言ってるから請け売りしてるだけ。

666 名前:663 :2006/04/06(木) 18:31:29
>>665
let's boost の人がそう言っている、というのは知らなかったな。

まあそれはいいとして、俺は以下のコードはとても気持ちが悪いと
思ってるんだが、問題は無いと思うべきなのか?

try {
cout << format("%06d") % 1.23 << endl;
cout << format("%s") % 1.23 << endl;
} catch (...) {
cout << "catch" << endl; // ここにはこない
}

667 名前:デフォルトの名無しさん :2006/04/06(木) 18:34:44
try〜catchの文はあまり頻繁に書きたくない

668 名前:デフォルトの名無しさん :2006/04/06(木) 18:54:15
>>666
だったら、xpressive や、spirit の用に Expression Template で
フォーマット書くようなライブラリを使えばいいじゃん。
例外といわず、コンパイル時に警告してくれるぞ。

print( cout, _0d[6] % _endl, 1.23 ); // (int)1.23 でないと警告
print( cout, _s % _endl, 1.23 ); // コンパイルエラー



669 名前:デフォルトの名無しさん :2006/04/06(木) 19:08:34
>>668

>>666、は
動的にフォーマットを生成できて、
さらに実行時に型が間違っていれば、
例外を投げてくれるようなものを欲しているのではないか?

670 名前:デフォルトの名無しさん :2006/04/06(木) 19:15:10
>>669 の書き込み見てふと気になったんだけど、
書式文字列を動的生成してるひとってどのくらいいるんだろ?

.NET だと自分自身、設定ファイルに書式書き込んでおいて、
読み込むとか(たまに)やるけど、C/C++ だとやった記憶がない。


671 名前:デフォルトの名無しさん :2006/04/06(木) 19:21:49
>>670
ひと、じゃなくて場面の問題。俺は割合よくやる。

672 名前:デフォルトの名無しさん :2006/04/06(木) 19:35:15
>>670
printf()なら"%*.*s"とかできるから余りやらないけど、scanf()だと融通が利かないからたまにやる。
あー、設定ファイルにフォーマット文字列を書くのはしばしばやるか。
例えば、日付で生成するファイル名を変える場合にFILE_NAME_FORMAT=result_%04d%02d%02d.txtとか。

673 名前:デフォルトの名無しさん :2006/04/07(金) 04:23:29
複雑なプリプロセッサマクロを一時的に全て展開して内容を確かめる方法は無いですか?
vc++2005です

674 名前:デフォルトの名無しさん :2006/04/07(金) 04:33:25
コンパイラのオプションにあるよ。
プリプロセッサだけ動かすの。

675 名前:デフォルトの名無しさん :2006/04/07(金) 05:14:57
>>662
sscanfはおそろしく速いよ。
parserの型を保存した場合だと、spiritもほぼ同じ速さ。
istringstreamは糞。


676 名前:デフォルトの名無しさん :2006/04/07(金) 05:25:18
spiritはコンパイルが遅いw

677 名前:デフォルトの名無しさん :2006/04/07(金) 06:41:20
>>674 IDE 上で簡単に角にできればいいのにね。

678 名前:デフォルトの名無しさん :2006/04/07(金) 09:00:28
>>677
かどにできれば?
かくにできれば?

679 名前:デフォルトの名無しさん :2006/04/07(金) 09:22:05
あ〜「確認できれば」のまちがい。
プリプロセッサでの展開後の姿を覗けたらって感じ。
「お前の本性覗いてやるぞ!」

680 名前:デフォルトの名無しさん :2006/04/07(金) 09:39:12
マクロ呼び出ししているところをシングルクリックして [F12] で定義をたどることならできるな

681 名前:デフォルトの名無しさん :2006/04/07(金) 12:40:56
>>680
きっとBoost Preprocessorみたいな複雑なマクロを書いているのだろう。

682 名前:デフォルトの名無しさん :2006/04/07(金) 13:40:34
可変長引数マクロ:
#define F(X, Y, ...) X(Y, __VA_ARGS__)
って、標準C++で対応してたっけ。
g++ 3.4.2は対応してるけれど、標準かどうかがわからず。

683 名前:デフォルトの名無しさん :2006/04/07(金) 14:23:59
してない。

684 名前:デフォルトの名無しさん :2006/04/07(金) 14:36:48
>>682
vc8でも対応しているから別にいいよそんなこと。


685 名前:デフォルトの名無しさん :2006/04/07(金) 19:27:28
変数xの値によって、生成するクラステンプレートの型を変えたい場合にスマートな方法はないでしょうか。

template <typename T>
class C
{
 T value; // 実際にはもっと複雑なクラス
};

enum gen_t { i, d, c };

void f(gen_t type)
{
 switch(type) {
 case i:
  {
   C<int> c;
   g(c); // g()は関数テンプレート
   // ...
  }
  break;
 case d:
  {
   C<double> c;
   g(c);
   // ...

このようにswitch-caseで分岐するしか思いつきません。


686 名前:デフォルトの名無しさん :2006/04/07(金) 19:30:46
>>685
変数xって何。その例でいうところの f の引数の type のこと?

687 名前:デフォルトの名無しさん :2006/04/07(金) 19:34:40
>>686
すんません、変数xではなくて、fの引数のtypeです。

688 名前:デフォルトの名無しさん :2006/04/07(金) 19:42:34
>>687
gen_tは使わなければいけないの?

template <typename T>
void f()
{
C<T> c;
g(c); // g()は関数テンプレート
}

f <int> ();

の方が素直だと思うのだけど


689 名前:デフォルトの名無しさん :2006/04/07(金) 19:43:48
>>688
コンパイル時に型が決まんないんでしょ

690 名前:デフォルトの名無しさん :2006/04/07(金) 19:53:30
>>685
コンパイル時に型が決まらないテンプレートを使いたいとき、
仮想関数と組み合わせるというテクニックがある。
struct f_base{ virtual void f() = 0; };
template <typename T> struct f : f_base {
  void f() {
    C<T> c;
    g(c);
    // ...
  }
};

691 名前:690 :2006/04/07(金) 19:54:35
ごめん。struct fのfは別の名前にしておいてくれ。f()はコンストラクタじゃない。

692 名前:デフォルトの名無しさん :2006/04/07(金) 20:03:48
>>685

boost::variantでvisitorパターンとか

#include<boost/variant.hpp>
typedef boost::variant<C<int>,C<double>,C<char> > val;
template <typename T> val create(){return val(T());}
val(*table[])()={create<C<int> >,create<C<double> >,create<C<char> >};
struct call_g : boost::static_visitor<>{template<typename T>void operator()(T&t)const{g(t);}};
void f(gen_t type){ 
    val v = table[(int)type]();
    boost::apply_visitor(call_g(),v);
}


693 名前:デフォルトの名無しさん :2006/04/07(金) 20:16:13
>>685
enum gen_t { i, d, c };
template <typename T> void h(){
    C<T> t;
    g(t);
}
void(*table[])()={h<int>,h<double>,h<char>};
void f(gen_t type){ 
    table[(int)type]();
}

694 名前:デフォルトの名無しさん :2006/04/07(金) 20:47:42
>>688-693
それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。

いや、冗談です。マジで参考になります。

>>690氏の仮想関数だと、派生クラス(f_baseを継承したクラス)のインスタンス化は
やっぱりコンパイル時に行われませんか。

>>692-693
インスタンス化された関数ポインタをテーブルで持っておくアイディアは思いつきませんでした。
thxです!

695 名前:デフォルトの名無しさん :2006/04/07(金) 21:46:54
>>678
アホ、「すみ」だ

696 名前:デフォルトの名無しさん :2006/04/08(土) 01:32:57
>>695
なんだ、つのじゃなかったのか。

697 名前:デフォルトの名無しさん :2006/04/08(土) 07:39:42
つのだ☆ひろ

698 名前:デフォルトの名無しさん :2006/04/08(土) 12:36:23
>>697

    _, ,_  パーン
  ( ‘д‘)
   ⊂彡☆))Д´) ←>>697

699 名前:デフォルトの名無しさん :2006/04/08(土) 16:16:41
列挙型の列挙子にアクセスする際に↓

enum eHoge{TEST0,TEST1};
int i = eHoge::TEST0;

こんな感じで出来ないんですね

700 名前:デフォルトの名無しさん :2006/04/08(土) 16:19:04
struct eHoge { enum { TEST0, TEST1 }; };

701 名前:デフォルトの名無しさん :2006/04/08(土) 16:19:09
enumは型だから無理だろ
int Zeroに対してint::Zeroとかやってるのと同じ

702 名前:デフォルトの名無しさん :2006/04/08(土) 16:27:39
>>701
は?ぁ?

703 名前:デフォルトの名無しさん :2006/04/08(土) 16:29:58
>>699 それは非標準ながら VC++ 7.1 なら出来た気がする。
VC++ 8 だとどうかしらん。

704 名前:デフォルトの名無しさん :2006/04/08(土) 16:40:29
>>701
バカ?

705 名前:デフォルトの名無しさん :2006/04/08(土) 17:21:33
>>703
VC++8ではC++/CLIなら699のようになった。

706 名前:デフォルトの名無しさん :2006/04/08(土) 17:52:34
namespaceつかえよ!


707 名前:デフォルトの名無しさん :2006/04/08(土) 17:57:48
確かに Enum名::アイテム名 って感じで
値を限定したい気もするよな。
まぁいまさら仕様を変えるのは無理なんだろうけど。

708 名前:デフォルトの名無しさん :2006/04/08(土) 18:10:05
struct/namespace eHoge { enum type { TEST0, TEST1 }; };

とか、enum の方にも名前をつけてないと、
型を使いたい時に困るぞい。

709 名前:デフォルトの名無しさん :2006/04/08(土) 21:43:18
釣り上手の>>701がいるスレはここですか?

710 名前:デフォルトの名無しさん :2006/04/08(土) 21:51:28
いいえ、それはトムです

711 名前:デフォルトの名無しさん :2006/04/08(土) 22:10:17
>>710
それどこの英語の教科書?

712 名前:デフォルトの名無しさん :2006/04/08(土) 22:14:38
int a = 1;
const long& b = a;

って、キャストで一時オブジェクトができて、その一時オブジェクトを
参照するらしいけど、一時オブジェクトって、その式が終わった瞬間
に消滅するから、この記述は無意味?


713 名前:デフォルトの名無しさん :2006/04/08(土) 22:15:43
>>712
うんにゃ

714 名前:デフォルトの名無しさん :2006/04/08(土) 22:17:32
constな参照型の変数の構築に使われた一時オブジェクトの寿命は、
その変数の寿命まで引き伸ばされるという規定が無かったっけ?

715 名前:デフォルトの名無しさん :2006/04/08(土) 22:29:36
>>712
constの参照の場合、一時オブジェクトはスコープが続く限り
消滅しないだろ。

716 名前:デフォルトの名無しさん :2006/04/09(日) 11:25:42
peekmessageループ中でscanf("%s",c)とやってもうまくいかない
(cの値がscanf前後で変わっていないっぽい)のですが
そもそもscanfは「いつ(ex 関数が呼び出されて以降)」から「いつ(ex Enterが呼ばれるまで)」までの
入力を受け取る関数なのですか?

ちなみにこんな感じの使い方です
peekmessage(){



void pushA{//Aキーを押したときの処理
//jyotaiが0のときAを押したらキーボード入力受け取りモードに
   if (jyotai==0){
scanf("%s",c);
 }
}



}


717 名前:デフォルトの名無しさん :2006/04/09(日) 12:21:29
標準入力(stdin)でバッファリングされてたりするから
いつからいつまでってないような気がするが。

718 名前:デフォルトの名無しさん :2006/04/09(日) 14:04:20
cがcharのポインタであり、更にその参照する領域が確保済みであることを祈るよ。

719 名前:デフォルトの名無しさん :2006/04/09(日) 15:23:59
>>716
scnaf()は、関数が呼ばれた時点までに確定している入力を受け取る関数です。
ではいつ入力が確定するかと言うと、標準入力が接続されているデバイスによって違います。

720 名前:デフォルトの名無しさん :2006/04/09(日) 15:25:02
>>719
その説明だと入力待ちは生じないように聞こえるが?

721 名前:デフォルトの名無しさん :2006/04/09(日) 15:25:24
>scnaf()は、関数が呼ばれた時点までに確定している入力を受け取る関数です。
おまえの環境ではscanfはブロックしないのか?

722 名前:719 :2006/04/09(日) 15:29:47
すまん。訂正。
関数が呼ばれた時点までに確定している入力がフォーマットの要請に満たない場合、
エラーが発生しない限り待ちますw

723 名前:716 :2006/04/09(日) 15:48:36
みなさんどうもです。
>>718
char c[81]とVC.netのヘルプのサンプルコードそのままに指定してます。
>>719
ということはpeekmessage中だとキーボードからの入力メッセージはいつまで経っても確定しない?
ってことですかね?

724 名前:デフォルトの名無しさん :2006/04/09(日) 18:41:43
>>723
標準入力可能なコンソールプログラムじゃないような気がするが気のせい?




725 名前:デフォルトの名無しさん :2006/04/09(日) 23:25:48
effective C++の68ページにmerePoolとmemPoolってあるんですけど。
記述ミスですかね?

726 名前:デフォルトの名無しさん :2006/04/09(日) 23:32:05
class A
{
public:
void a1();
void a2(); // <= a1()を内部で使ったメソッド
};

class B : public A
{
public:
void a1(); // <= a1 をオーバーライド
};

この時、オーバーライドしたa1()を使った a2() を呼びたいのですが
このままだと A::a2()が呼ばれます。良い方法はないでしょうか?

727 名前:デフォルトの名無しさん :2006/04/09(日) 23:37:20
つvirtual

728 名前:デフォルトの名無しさん :2006/04/09(日) 23:37:37
a1を仮想関数にしてオーバーロード

729 名前:デフォルトの名無しさん :2006/04/09(日) 23:41:37
class A
{
public:
virtual void a1(); // a1 を仮想関数にして
void a2();
};
class B : public A
{
public:
using A::a1;
void a1(int); // a1 をオーバーロード
};

730 名前:デフォルトの名無しさん :2006/04/09(日) 23:46:19
オーバーライドだったっけ?ややこしいな

731 名前:デフォルトの名無しさん :2006/04/09(日) 23:49:48
726です。

できました。ありがとうございました!

732 名前:デフォルトの名無しさん :2006/04/10(月) 20:10:25
クラスTがあって、T(i)って表記は、どう考えれば良い?

T* a = &T(i);

とかOKなの?

733 名前:デフォルトの名無しさん :2006/04/10(月) 20:16:40
OK。問題なし

struct T{T*operator&(){return new T;}};

int main(){
    T i;
    
    T*a=&T(i);
}

734 名前:デフォルトの名無しさん :2006/04/10(月) 21:43:59
 T(i) <私まんこちゃん!
  ╋
  /\

735 名前:デフォルトの名無しさん :2006/04/10(月) 22:02:10
>>734

    _, ,_  パーン
  ( ‘д‘)
   ⊂彡☆))============= T(i)
  ╋
  /\

736 名前:デフォルトの名無しさん :2006/04/10(月) 22:05:57
ふいた

737 名前:デフォルトの名無しさん :2006/04/10(月) 22:30:06
>>733>>732の回答としてどうなんだろう?
ひょっとしてネタ?


738 名前:デフォルトの名無しさん :2006/04/10(月) 22:52:14
&とTの結合度よりもTと()の結合度の方が高いから、
T(i)はTをiで初期化した一時オブジェクトという意味になるだろう。

739 名前:デフォルトの名無しさん :2006/04/10(月) 23:07:19
寿命が問題

740 名前:デフォルトの名無しさん :2006/04/10(月) 23:31:31
newした時に一時オブジェクトの内容がコピーされるんでいいんじゃない?
deleteしないとメモリリークするが。

741 名前:デフォルトの名無しさん :2006/04/10(月) 23:32:25
ついでに書くと、T(i)と折角書いても、結局operator &()でnew Tが
呼び出されるので、一時変数の内容は無視されている。

742 名前:デフォルトの名無しさん :2006/04/10(月) 23:33:47
忘れ去られた>>732……。

743 名前:740 :2006/04/10(月) 23:37:01
あーしまった。
×newした時に一時オブジェクトの内容がコピーされる
○newした後で折角作った一時オブジェクトがそのまま捨てられてしまう。
 つまりT()でも良いし、T(j) [jはT型のインスタンス]でも全部同じ意味。

744 名前:デフォルトの名無しさん :2006/04/10(月) 23:48:06
T a = T();

745 名前:デフォルトの名無しさん :2006/04/11(火) 00:27:31
>>742
ちゃんとレスしてるけどね

746 名前:デフォルトの名無しさん :2006/04/11(火) 00:58:07
あるオブジェクトのインターフェースで、可変長文字列の可変長配列を処理結果として
返すような場合、一回に1配列分の文字列を返すようにする事が考えられますが、
イテレータとか使って一回で返してしまう方法ってあるんでしょうか?

747 名前:デフォルトの名無しさん :2006/04/11(火) 01:08:15
ごめん、732てスタックに積まれたオブジェクトへのポインタを取っているような
気がするけど、間違い無いよね?


748 名前:デフォルトの名無しさん :2006/04/11(火) 01:12:21
>746
あまり美しくはないが、auto_ptr<vector<string> >を返すのがパターンかなぁ。
vector<string>を直で返すのはさすがに気が引けるし。
あ、もちろんvectorでなくても適当なコンテナなら何でもいいけど。

他に何かもっと美しい方法あるかね?

749 名前:デフォルトの名無しさん :2006/04/11(火) 01:18:24
>>748
std::stringについてのOutputIteratorを取るという方法もある。
面倒だし、異なるイテレータを渡すたびにコードが膨張するという欠点はあるが。

750 名前:デフォルトの名無しさん :2006/04/11(火) 01:23:23
>>746
void f(vector<string>& result) じゃダメなの?


■過去ログ置き場に戻る■ 1- 前250 次250 最新50
DAT2HTML 0.33f Converted.