1 :
デフォルトの名無しさん :
2007/10/20(土) 16:45:05 C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。
3 :
デフォルトの名無しさん :2007/10/20(土) 16:56:41
4 :
デフォルトの名無しさん :2007/10/20(土) 16:57:48
5 :
デフォルトの名無しさん :2007/10/20(土) 16:58:31
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
これは、削除依頼を出すべきなのか?
だね どう見てもスレ立て荒らしでしょ
janeの隠し機能1 1.まず半角入力に切り替える 2.Wキーを押しっぱなしにする 3.Wキを押しっぱなしにしながらsageのチェックするところをおもむろにクリック
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
>>STLでファイルが十倍に きっと vector<int>; vector<char>; vector<string> とかコンテナクラスの乱立になっているんだろうなぁきっと… コンパイラオプションは弄ってないでしょうなきっと…。
iostreamをインクルードするとexeが太っちゃうです。
>>10 ショートカットが働いているだけっしょ。隠し機能でもなんでもないじゃん。
なんで bool って 32ビットもあるの? 重いから bool :1 って定義してるけど、32ビットも保持する意味あるの?
真実を伝えるのに 1ビットで足りるとでも?
実装によりけり
32ビットの方が軽いじゃん
20 :
デフォルトの名無しさん :2007/11/08(木) 23:03:05
age
いいじゃん32bitくらい
vector<bool>はダメダメよ
24 :
デフォルトの名無しさん :2007/11/19(月) 19:55:18
traitsとpolicyとconceptの違いをおしえてくださいですぅ〜 英語のサイトに詳しく書いてあるぽいのですが英語読めないorz
traitsは英語の意味そのまま、特徴とか性質 具体的には型の特徴をメンバとして持つクラステンプレート policyも英語の意味のまま、方針 具体的には型の機能の一部をテンプレート引数としてMix-Inできるように書かれた型 conceptは型の型、つまりメタ型 C++0xではHaskellのclassに近いものになる
26 :
25 :2007/11/19(月) 23:52:40
>具体的には型の特徴をメンバとして持つクラステンプレート ああ、テンプレートである必要はないか
クラスの概念がイマイチ分からん。 クラスA、B、Cがあって、 class A { ... C c; }; class B { ... C c; }; みたいな感じにした際、Aクラスを介してアクセスするcの色々と Bからアクセスするcは同じもの? 違うもの? 自分でも言ってる意味がわからないのだが、これは A用に使うCのオブジェクトが生成されて、 B用にもCのオブジェクトがみたいなものが生成されて 別物をアクセスしてるんじゃないかなって。 実際はどうなんでしょうか?
A a1; A a2; このとき a1.c と a2.c は別インスタンスだよな、それはOK?
実際そうだよ。
>>27 >27のclassをstructに置き換えても理解できない?
すんません、適当に加算するプログラムを作って理解できました
>>30 の言うとおり、structみたいなのを考えると当たり前ですね。
失礼しました
あと、staticを付けた変数は共有できるんですね。 頑張ります
>>27 クラスって型のことだよ。structと同じ。
あとその型で定義したオブジェクトだけに使える関数があって
これをメソッドという。
バカヤロウ。 C++ スレではメンバ関数といえ。
別にどっちでもいいっすよー。
いつも、けいしょ・・・派生クラスって言い直してしまう(´・ω・`)
>>35 わかるw 俺の場合メンバ関数も、メソ・・・メンバ関数と言い直してしまう。
マサルさんネタかよっ
38 :
デフォルトの名無しさん :2007/11/24(土) 10:14:16
大きくABCと3つの処理に分かれていて、テンプレートを使ってBの部分だけ処理内容を自由に変えたいと思ったのですがうまくいきません。 A B1 <--> B2 <--> B3 etc. C Bの部分の関数呼び出しの引数が固定ならなんとかなるのですが、 テンプレートパラメータとして可変長引数を扱うにはどうすればいいと思いますか? 誰か教えてください
想定する引数の数だけテンプレート用意したらいいんじゃね? それか、引数を構造体にまとめて1つとして扱うとか。
40 :
38 :2007/11/24(土) 14:13:13
他人に(好き勝手に)使ってもらうように作るので無理です なるべく自由につかってもらいたい
>>38 なんで固定の A, C の間に挟む処理の引数が可変長になるんだ?
無理にテンプレート使おうとしてうまくいってないだけじゃね?
42 :
デフォルトの名無しさん :2007/11/24(土) 14:30:09
可変長パラメータやデフォルト値を使うのじゃダメなのか
Bの部分をファンクタにして渡せばいいだけだろ。 ファンクタはメンバも持てるんだから追加の引数はそこに入れて渡せ。
45 :
38 :2007/11/25(日) 14:52:25
やっぱり無理かなあ AとCは自分で作るからいいとして Bには制限をつけたくないんです 基本的にBを使うのは何もわかってないアホだと思ってください
だれも無理だなんて言ってないのに、なんでそうなる?
38のレベルの誰でもが使えるように、というのならば、無理かもしれない。
何もわかってないアホが C++ 使う時点でかなり無理があるからな。
Java使わすほうが適当だな。
本質的な解決になっていない気もするけど。
アホが使うなら制限付けるだろ、常考。
44で答え出てるじゃん。
53 :
38 :2007/11/25(日) 20:15:13
みんなまじめに考えようよ 難しいとは思うけどさ…
部品をやるよ。 boost::any std::vector
55 :
38 :2007/11/25(日) 20:29:57
答えはもう出てる。
57 :
38 :2007/11/25(日) 20:33:39
↑キミ偽者 理想はラムダ関数なんですけどね。
ずばり答え言ってやれよ いくつかある異なるゴールへのヒントばかりでかわいそうになってきた
それにはエスパーが必要だ。情報が足りなさすぎる。
情報足りなくて答えられないのにえらそうにしてたのかw
情報が足りないのが回答者のせいだとでも思ってるのか?
もうやめろよ 38
63 :
38 :2007/11/25(日) 20:45:33
俺のせいではないな 問題はA、B、Cと3つの処理があってBを自由に取り替えたいだけだからな A B1 <--> B2 <--> B3 C みたいな感じだな
65 :
38 :2007/11/25(日) 20:53:09
関数オブジェクトは駄目 わかんない人いるから
67 :
38 :2007/11/25(日) 20:58:33
本当にここは役に立たないインターネッツですね
68 :
38 :2007/11/25(日) 21:00:25
↑キミ偽者 自分で作れないから聞いてるんですが…
69 :
38 :2007/11/25(日) 21:00:45
ちょっと鍛えてあげようと思って お題を投下してやったらこれだ 意欲も才能もないのになんで プログラムやろうと思ったの、きみら?
38 大杉
71 :
38 :2007/11/25(日) 21:18:27
キミも偽者 いやほんとマジでお手上げなんですが…
だから何? ってか、A, CだけじゃなくてBも【全部】自分で作ればアホに提供できるだろが。
73 :
38 :2007/11/25(日) 21:30:55
ライブラリ屋なんで上のレイヤーまで面倒みれないです
>>73 どんなライブラリを提供したいのか、もそっと具体的に書ける? ロギング?
Bはコールバックなの??? だったら関数仕様を明確にするだけでいいんじゃね?
ABCをメソッドに持ったクラスXを作って、 Bに渡す引数は全部Xのメンバ変数にしておけ。 そうすりゃBに引数はいらない。
ファンクタはだめなのに、ラムダ関数ならいいのか。ウンコ
78 :
デフォルトの名無しさん :2007/11/25(日) 21:50:07
In function `main': /main.cxx:23: undefined reference to `Environment(double, double, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: ld はステータス 1 で終了しました というエラーがg++で出ました。 -lmはつけてるし仮想関数でもないし、ちょっと意味がわかりません。 どこを考えればいいのか思いつく方いらっしゃいませんか?
Environmentへ渡してる引数の型が間違ってんじゃねーの?
>>65 でもさ、理想はラムダ関数って
>>57 でいっているよね。
関数オブジェクトを受け取るようにしておけば、
Boost.LambdaやC++0xで導入されるかもしれないラムダ関数なども受け付けられる。
関数オブジェクトがわからなければとりあえず普通の関数を作って渡せばいい。
こんな関数オブジェクトのどこに問題がある?
81 :
デフォルトの名無しさん :2007/11/25(日) 21:59:46
>79 ありがとうございます! 引数を確認するときにdoubleかstringかーしか見てませんでした。 宣言のところ(自作ヘッダーファイルの中)と定義のところで 参照の&がついてるかついてないかという違いを見落としていました。 くだらんミスでごめんなさい。ありがとう!
82 :
38 :2007/11/25(日) 22:10:03
世の中の人間が全員関数オブジェクトを理解できると思っては駄目です。 アホなんです。基本的に。 今のC++の仕様では不可能ということで結論も出たのでもう寝ます。 ありがとうございました
>>82 そういうときはこう答えないと相手にしてもらえないよ
> 言葉が悪いな。それで教えているつもりか。
> まぁヒントぐらいにはなったな。
> うむごくろう。
84 :
80 :2007/11/25(日) 22:18:30
>>82 誰も、というより少なくとも俺は全員理解できるなんて言っていないぞ。
なんなら関数へのポインタを引数に取るものを多重定義しておくか。
そうしたら今度は世の中全員が関数へのポインタを理解できると思うな
とでも言ってくるんだろうな。
正直そんなレベルの職場で一人だけ張り切って柔軟性がどうだとか滑稽だと思う
結局どういうものを要求してたのかよくわからない
>>85 同意。
もちろんチームのスキルの底上げをやり遂げられる人もいるが、
>>38 にはそのつもりもないようだし、それなら程度に合わせてコードを書くべきだ。
すいません。 2次元配列 d[3][3] に対するポインター (*p)[3] を作って p=d とやったのにcannot convertとかエラー出たんですがわかりませんか?
>>88 2次元配列だろうが何次元だろうが、関係ない。
int d[3][3];
int *p;
p = d;
91 :
88 :2007/11/25(日) 23:14:21
エラー詳細は error: cannot convert `int[((unsigned int)((int)ObjNum))][((unsigned int)((int)DataNum))]' to `unsigned int (*)[6]' in assignment です どういうことでしょうか?
92 :
38 :2007/11/25(日) 23:18:35
自己解決しました
2次元配列に対するポインタは (*)[][] でしょうに。 でもって p=&d; だろうに。
p = &d[0][0]; で代入すりゃいいんじゃねーの?
96 :
88 :2007/11/25(日) 23:29:38
void Entry(void) { (省略) int d[ObjNum][DataNum];// ちなみに4と6です //[]の2つはグローバルなint変数です (省略) for(int i=0;i<ObjNum;i++){ fp >> n[i]; for(int k=0;k<DataNum;k++){ fp >> d[i][k]; } } data=d; } ソースを分割してて main関数のあるところでグローバルとして以下を宣言 int (*data)[6]; でエラります。(91の書き込みのときのunsignedは気にしないでください) アドバイスしていただいたものイチから試してみます! ありがとうございます!
97 :
88 :2007/11/25(日) 23:43:51
どれも駄目でしたorz
>>96 double (*p)[DataNum];
こんな感じで。
dataに代入する目的は?
doubleじゃなくてintだった int (*data)[DataNum];
101 :
88 :2007/11/25(日) 23:59:31
>99 そういえばコレ外部で使おうとするときには ポインター先消えますね汗 2重に馬鹿でした。 ポインターに代入したのはファイルからロードしたデータをプログラム内 どこからでも参照できるようにしたかったからです。 じゃあ配列自身をグローバル化しろよって話ですね。。。 >100 そのとおり書いてあるはずなんですが・・
102 :
88 :2007/11/26(月) 00:08:26
配列をグローバル化しようとすると要素数を決めておかないといけないので それが嫌で中で宣言したんです。 ポインターを作るときにも要素数が必要だってのがわかったので今となっては 意味のない代入かもしれませんが出来ないってとこがどうしても納得できません。
C++なんだから、STLおぼえたほうがいいよ。 std::vectorで動的配列作れる。
>>102 >int d[ObjNum][DataNum];// ちなみに4と6です
このDataNumは定数じゃなくて動的な値? これってCの新しい規格の奴だよね。
使ったことないから詳しくは知らないが、型のサイズが動的に決まる、
つまりコンパイル時に特定できないのなら、そこから int(*)[6] へのキャストは無理でしょ。
105 :
88 :2007/11/26(月) 03:24:33
みなさまアドバイスありがとうとざいましたm(__)m
うんうん唸って結局以下の様にしました。
main関数のあるソースファイルで
vector<vector<double> > *data;
Entry関数のあるソースファイルで。
vector<vector<double> > d(ObjNum, vector<double>(DataNum));
および
data=*d;
別の関数でdataを使うとき
ac = (*data)[x][y];
配列の大きさを自動判別にしたかったためこのようになりました。
103、104、および
http://gimite.net/bcbqtree/qtreemain.cgi?mode=thread&thread=424 とても参考になりました。
みなさまほんとにありがとうございました!
int *p = NULL; ... delete p; ってコードみたんだけど、pがNULLかどうかチェックしてなくてdeleteしてるの。 これってNULLをdeleteしてもOKみたいなこと規格にあるの? 規格厨ヘルプ!
deleteの対象がぬるぽである場合、何もしない(ISO/IEC 14882:2003 5.3.5.2) なんで問題ないでしょう
なにーサンクスです。 じゃぁ結局ifでチェックするコードは無駄なんですね
Releaseと紛らわしいからどっちもifつけてる俺は異端か
>>109 ・効率が悪い
・知らないと思われるのが腹立たしい
よって、つけないのが良いと思います。
古いコンパイラだと NULL 渡すと落ちたことあったような気がする。
規格が出来る前のやつだとそういうのもあるかもしれませんね
最適化で消えるなら、古いコンパイラを考慮して if つけてもいいとは思う。
NULLじゃなくて0じゃね? ほとんどの場合int(0)だとは思うけどさ。
無理に難しい事言おうとして変な事言ってるな。
NULLは(void*)0か(int)0しか見たことないな。
Cの規格ではヌルポインタ定数(NULL)は整数定数0かそれをvoid*に変換したもの と言われてるからなあ C++ではヌルポインタ定数は0だからNULLマクロを使うなら(int)0と すべきか????
今は NULL は処理系定義だよ。 __null 拡張キーワードで定義されてたりする。
>>118 Cのヌルポインタ定数の定義が規格でも変わったの?
俺が見たのはJIS X 3010 (2003年)だけど。
C++はプログラミング言語C++しか見てないから
わからない。
C は C99 で変わった。 C++ はいつからなのかは知らん。
とりあえず g++ だとこれで __null と出力される。 VC++ はどうなのかな? #include <iostream> #define BARE_2(macro) #macro #define BARE_1(macro) BARE_2(macro) #define BARE(macro) BARE_1(macro) int main() { std::cout << BARE(NULL) << std::endl; }
VC++6.0ってコンパイルしてexeやDllが作成された時点でANSI規格に準拠しるって言えるのでしょうか? 知っている人います?
VC6はC++98より前なんで割と準拠度低い
言語拡張を使用しない という感じのオプションを付けてコンパイルすれば まあ C なら C89 にはおおむね準拠できてると思うけど、100% じゃないんじゃないかな。 C++ に関しては VC++ 6.0 は C++ の規格が固まる前に出たというものもあってか、 C++ の規格への準拠率は酷いもん。
126 :
デフォルトの名無しさん :2007/11/26(月) 22:42:21
そうなんですか。。。 ANSI準拠かどうかの判断をしたいのですが、何かいい手段(方法)ありませんか? コンパイルオプションZaを指定するとコンパイルエラーが出ちゃうし。 ANSI準拠が今回の案件の用件の一つに入っているのでなにかいい案ないでしょうか。
C なら lint があるけど、C++ ではあったっけ?
>>126 g++ -ansi -pedantic -fsyntax-only -Wall -Wextra
ってか、ビルドされたものに対してANSI準拠とかあんの?
コードなら他のコンパイラでも(ANSI準拠なら)問題ないんだから
>>128 みたいなかんじでいいんでね?
C は ANSI → ISO/IEC の順だから ANSI でいいけど C++ は ISO/IEC → ANSI の順だから ISO って言った方がいい気がする。 まあどうでもいい話だが。
JISもあるよ☆
132 :
デフォルトの名無しさん :2007/11/27(火) 00:18:02
void ○○○::□□□(int a){ } ってこれなんですか?C++の自作関数ですか? この関数が他に使われてるところを調べるにはどうしたらいいんでしょう?
名前空間内の関数か、クラスのメンバ関数の定義。 どこで使われているかを探すには、Cと大差ない。 IDEの機能に頼ったり、grepしたり。Cより見付けにくいかもしれないけど。
134 :
デフォルトの名無しさん :2007/11/27(火) 00:39:23
>>133 ありがとうございます!恩にきます!
ですが、すみません。Cもあまりよくわかってないのですが、
○○○::□□□
だけでgrepしたところ、一件もヒットがないのです。
○○○だけで検索すべきでしょうか?□□□の方が真髄なのでしょうか?
>134 □□□の方が関数の名前なのでそっちで検索する…んだけど、○○○::□□□じゃない□□□も 引っかかる可能性があるんで、それ以上は C++ 勉強してくれって感じ。
□□□で検索すべきだろう。 類似する関数があれば○○○がクラスなら継承の有無を確認する必要がある。
137 :
デフォルトの名無しさん :2007/11/27(火) 00:53:49
>>135 大変助かります。ありがとうございます。
□□□がメンバ関数にあたるのでしょうか?
すみませんが、もう一つだけ!
○○○::~□□□()
となってるのがありますが、これはちょっと何か特殊なのでしょうか?
>>137 入門の本なりサイトなりを参考にするといいよ。
○○○::~□□□←これはデストラクタ。
この程度の内容なら猫でもなんでもいいから一読すりゃ覚えられる。
139 :
デフォルトの名無しさん :2007/11/27(火) 01:08:26
今更感がある。恩恵も少なそうだし。
>>139 あ、有名だから出したってだけでそこにあるコードがいい物じゃないんで、一応。
大体の基礎的なことが猫の20章までにあるからそこまで読めば十分。
C++で使われる単語(コンストラクタとかデストラクタ、継承、オーバーロード等)が
多少理解できるようになればいろんなサイト回ったほうがいい。
143 :
デフォルトの名無しさん :2007/11/27(火) 01:39:38
>>142 ひとまずは目の前にある大量のソースを読めるようになり、簡単な修正が
できるようになることが目標ですので、基礎が身につけばいいです!
コンストラクタとかデストラクタ、継承、オーバーロードなどが目安ですね!
Cを一通りやったはずなのに、目の前のコードの意味が分からず、C++だったことに
気付き、涙目になってたところでしたので、本当に大っ変、大っっ変助かりました!!!
展望が見えてきました!!!ひとまずやってみます。ありがとうございました!!!
>>141 やっぱりそう思う?
でもここでも毎度毎度でてくるじゃん。
もう何度この手のやり取りを見たことか。
おい、NULLとは何だ規格厨ども?
マクロに決まってんだろボケ!
値は0か? それとも((void *)(0))か?
いや、それは処理系依存だ。
規格でも0だと決まっているぞアホが。
いや、しかしだな、実際昔のある処理系では云々。
何かしら必要とされているんじゃない?
>>144 必要なものっていうなら、ずっと昔からある C FAQ 5 で十分。
どうせ互換性は捨てられないんだから 0 も NULL も残る。そこにさらに nullptr を
追加しても、混乱は増すだろう。一部の問題を解決するのは確かなんだけれども。
146 :
デフォルトの名無しさん :2007/11/27(火) 02:06:08
すいません。ある返り値の組(1,2,3)があって 例えば 1 2/3 2 1/6 3 1/6 の確率で返すことが決まっているときにどのように書けば この確率どおりに返り値を返すことができるでしょうか?
C++では今の0でいいじゃん。コンパイラ作る奴らしっかりしろ。
>>146 int foo() {
switch (rand() % 6) {
case 0:
return 2;
case 1:
return 3;
default:
return 1;
}
}
ここでアセンブラの事聞いてもよろしいでしょうか? ここしか人いなさそうなので…
rand()は実用で使おうとすると問題あるんじゃなかったかな 例えばサイコロを再現しようとしても、均等に値が分かれないとか… なんか実用的な乱数ライブラリあった気がするけど、思い出せない
>>152 ありがとうございます
一応アセンブラスレには書き込んだんですけど
こっちでも聞いてみてもいいでしょうか?
とりあえずrandomとかrand_sでお茶を濁す。
>>151 srandとtime関数使って種別変えてもダメなの?
>>152 >プログラムサイコロの再現なんて、ほんとにできたらノーベル賞もんだけどな。
知らなかった
>>155 関係ないはず
本物のサイコロ使うと 6 が連続して出るなんてことも結構な頻度で起こるけど
コンピュータの乱数だと、そんな風にならない…という話だったような
157 :
146 :2007/11/27(火) 02:38:08
>>148 ,149,154
ありがとうございます。
分母を最小公倍数で消して
1 4
2 1
3 1
とした上でrandom関数にmax6min0で返り値吐かせて
0〜4なら1を、4〜5なら2を、・・という風にしようかと思います。
返り値の組は変動するのでswitchには乗せられないと思ったので。。
>>156 サイコロのかわりに (rand() % 6) + 1 なんてしてると、そんなことになりやすいかもね。
C FAQ にある方法使えば、値域が十分小さいときにあんまりひどい結果にはならないと思うよ。
159 :
デフォルトの名無しさん :2007/11/27(火) 10:41:50
STLのmapを2重に使う場合インサートはどうやってやればいいんでしょうか map<string, map<int,int> > a; こんな感じでKeyをstringとintにしたいんです・ 使うときa["test"][100]++;という具合にカウントしていきたいんですが
普通にinsertできるが、コンテナの中にコンテナはどうかと…… Keyをstringとintの構造体かクラスにして、Compare指定したらどうだろ
161 :
159 :2007/11/27(火) 11:10:04
>>160 ありがとうございます。
では自分で自作する方針で行きたいと思うのですが
Compare指定について勉強するサイトを教えていただけませんか・・
(浅いものでコンペア指定という語を初めて聞きました)
サイトが見当たらなかったので、使用してるSTLのソースを参考にしてみると良いかも こんな感じに: template <class T> struct less_key2 { bool operator()(const T& s1,const T& s2) const { return s1.first < s2.first && s1.second < s2.second; } }; typedef std::pair<std::string,int> Key2; std::map<Key2,int,less_key2<Key2> > a;
163 :
159 :2007/11/27(火) 12:17:04
返事遅くなりました! すみません、わざわざソース探していただいて。 参考にしつつ考えてみます!ありがとうございましたm(__)m
164 :
鈴木 :2007/11/27(火) 13:12:56
MiniDumpWriteDump をつかって、Dumpを出力しているのですが、 どのようにしてファイルの中身は見れるでしょうか?
>>164 仕様にそんな名前のものはありません。環境依存スレにでもどうぞ。
166 :
鈴木 :2007/11/27(火) 14:56:16
>>165 仕様って何ですか?
C++って1つじゃないんですか?
MiniDumpWriteDumpはWindowsのAPIであって、 C++言語の話ではないってこと
>>165 こういうレスする奴って性格悪そうだな
普通に誘導すりゃいいじゃん
このスレに人がたくさん居ることに驚いたぜ
172 :
165 :2007/11/27(火) 15:12:25
>>170 私の性格を云々したいのなら、雑談スレへどうぞ。
どうせそちらもチェックしていますから。
>>170 鼻から悪魔を召喚したいのですがどのスレが適切でしょうか?
規格書を読んでundefinedって書いてあることを片っ端から試していくと良いです
176 :
鈴木 :2007/11/27(火) 20:40:23
>>162 なんか初心者スレに似たような比較関数で嵌ってる奴いたな。同一人物か?
ちゃんと Strict Weak Ordering にしないとダメでしょ。
>>177 Strict Weak Ordering ですが、
>>162 の例で言うと
どういう規則になるんですか?
s1.first < s2.first && s1.second < s2.second
これがStrict Weak Orderingを満たしているということは
どういう意味?こういうのは直感的に分かるもの?
s1.first < s2.first && s1.second < s2.second なんかこれ違う気がする。。 s1.firstとs2.firstが一致した場合、secondを調べないで falseを返すことになるけどいいのかな?条件が複数あると 混乱してくる。
if (s1.first != s2.first) return s1.first < s2.first; return s1.second < s2.second が正しい。 というか、 std::pair<T, U> は標準で比較演算子持ってるから 基本的に自分で書かなくてよい。
>>180 なるほど。
例えばboostのtuple使った場合、Strict Weak Ordering は
if( t1.get<0>() != t2.get<0>() ) return t1.get<0>() < t2.get<0>();
else if( t1.get<1>() != t2.get<1>() ) return t1.get<1>() < t2.get<1>();
else if( t1.get<2>() != t2.get<2>() ) return t1.get<2>() < t2.get<2>();
・
・以下続く
・
となるんですか?
>>181 汎用的なコードにするためには、 operator != が定義されていない場合も考慮して
↓のようにしたほうがいい。これなら operator < しか使わない。
if( t1.get<0>() < t2.get<0>() ) return true; else if( t2.get<0>() < t1.get<0>() ) return true;
if( t1.get<1>() < t2.get<1>() ) return true; else if( t2.get<1>() < t1.get<1>() ) return true;
if( t1.get<2>() < t2.get<2>() ) return true; else if( t2.get<2>() < t1.get<2>() ) return true;
・
・以下続く
・
return false;
ポインタが入ってることを考えると厳密には std::less を使わないといけないんだけど、
激しくメンドイ。
183 :
182 :2007/11/28(水) 11:00:55
ミスった。行末の return true は return false の間違い。
>>181 辞書式比較を実装するならそう。
(ただし、型によっては != 演算子を実装してないかもしれないので
そこは回避する必要があるかも)
ただ、 strict weak ordering を満たす順序づけは一通りではないので、
別のやり方で順序を定義してもいい。
一般には、以下の条件が満たされる比較順序なら何でもいい。
ある型の値 x, y, z に対して
1. x < x は false
2. x < y が true ならば y < x は false
3. x < y と y < z が両方 true ならば x < z も true
4. x < y, y < x, y < z, z < y が全て false ならば x < z と z < x も false
4つ目の条件の意味がよくわからない
>>185 書き換えれば、x == y, y == z が言える状況なら、 x== z も言えないといけないということ。
x < y, y < x がどちらもfalseなら1.から当然、x == y と言えるから。
x < y かつ y < x ってのは x と y が等価(equivalent)であるということ。 このことを x≡y と書くとすると、4番目の条件は x≡y かつ y≡z ならば x≡z と書き換えられる。 要するに、等しい連中同士を比べたら必ず等しくなってないと駄目だってこと。
>x < y かつ y < x ってのは x と y が等価(equivalent)であるということ。 惜しい。この説明だとおかしい。
>>182 != は < で表現できるから、!= が定義されていない場合がある
ということですよね?
この例の場合
>>184 の1の条件と2の条件を使ってるということですね。
確かEffectiveSTLにStrict Weak Oderingの一つとして比較対象が一致
した場合は常にfalseを返すことが必要と書かれていました。これは、
>>184 の1の条件ということですね。
奥が深いです。
みなさん、どのような書籍を読まれてるのですか?
>>188 !(x < y) かつ !(y < x) が true かつ true ならば
つまり『一方が他方の前にあるということはない』
と解釈しました。
>>177 それ書いたの俺だ、しかも比較文を間違えてるね
>>159 さん、巻き込んだみんなもごめん
演算子はoperator<とoperator==は実装されていると思うけど、
他の人が言うとおり、operator==(!=)は極力避ける方向で
>>162 の比較は下になります
if (s1.first < s2.first) {
return true;
} else {
if (!(s2.first < s1.first)) {
return s1.second < s2.second;
} else {
return false;
}
}
x != y を < で表現した場合、 !(x < y) && !(y < x) ということで正しいですか?
193 :
191 :2007/11/28(水) 12:04:06
分かりにくそうなので修正です。
if (s1.first < s2.first) {
return true;
} else {
if (!(s2.first < s1.first)) {//if (s1.first <= s2.first) {
return s1.second < s2.second;
} else {
return false;
}
}
>>192 !(x < y) && !(y < x)
(x >= y) && (y >= x)
(x > y) || (x == y) && (y > x) || (x == y)
(x > y) && (y > x) || (x == y)
(x == y)
(x > y) || (x == y) && (y > x) || (x == y) …× ((x > y) || (x == y)) && ((y > x) || (x == y)) …○
>>193 >(x > y) || (x == y) && (y > x) || (x == y)
間違い。
assert マクロって必ず assert (x) を !!x で評価してくれるのかな。 ってのは、クラスに ! 演算子をオーバーロードしておけば そのインスタンスを assert () に渡せるかなと思って。 一応 VC8 見たら !!x で評価してたけど、処理系依存? クラスの内部状態が整合性ある状態かどうかを自己診断して 失敗なら true、成功なら false 返す処理を ! 演算子で やろうと思ってます。 えと、なんか気持ち悪いけど失敗なら「true」でいいんだよね・・
operator ! よりも operator bool のがいいんじゃないかと思う
使うならsafe bool idiom使おうね…
199 :
196 :2007/11/28(水) 15:38:24
ios_base でも bool operator!() const{ // test if no stream operation has failed return (fail()); } ってやってるし、「ダメ」なときに真を返せばいいのかなぁ。
200 :
196 :2007/11/28(水) 15:39:41
>>197-198 リロードせずに書いてしまった・・・
safe bool idiom ってなにぃ??
ググリマス。
202 :
196 :2007/11/28(水) 18:05:50
safe bool idiom って boost の中でも使われている みたいだけど、上のサイトにのってるテンプレートの コード自体は取り込まれていないの?
>>199 basic_ios<>でもoperator boolではなくて
operator void*() constだからな。
ポインタとboolの暗黙の変換を利用して真偽値の判定を行う。
cin >> x;
if(cin) { ... }
およそ 500 個の cpp ファイルからなる無駄に汎用的なライブラリの開発に関わってるんですが、 モノシックなヘッダを1つ include すれば使えるようにするのと、 500個のヘッダを必要になるたび一つ一つ include してもらうのと、 あるいは両者の中間と、それぞれどんな長所や短所があるでしょうか?
500個のヘッダと、それらをすべてincludeするヘッダを一個作れば問題解決
206 :
デフォルトの名無しさん :2007/11/29(木) 10:11:45
これコンパイルエラー(C2059:構文エラー'{')になるんですけど、どうすればいいですか? class CHoge { static const char Names[][] { "Name1", "Name2", "Name3" }; };
207 :
デフォルトの名無しさん :2007/11/29(木) 10:13:30
あ、= 忘れてた。訂正。 class CHoge { static const char Names[][] { //ここでC2059 "Name1", "Name2", "Name3" }; };
208 :
デフォルトの名無しさん :2007/11/29(木) 10:14:34
やばいテンパッテル。 これが本当の訂正。すまん。 class CHoge { static const char Names[][] = { //ここでC2059 "Name1", "Name2", "Name3" }; };
C/C++では多次元配列で全ての要素数が不定(自動決定)なものは定義できません。
>>208 のように、全ての要素(文字列)の長さが一緒になるとしても、です。
static const char Names[][6] = {
"Name1", "Name2", "Name3",
};
なら通るんじゃないでしょうか(VC++6.0で確認)
210 :
デフォルトの名無しさん :2007/11/29(木) 11:08:03
いや、classのブロックからはずすとコンパイル通るんですよー。 static const char Names[][] = { //ここでC2059 "Name1", "Name2", "Name3" }; class CHoge { }; これならOK。でもクラスの静的メンバーとして二次元配列を持ちたいんですが、どうすればいいですか?
>>210 クラス宣言内に書くのではなく
CPPファイルのほうに書く
staticなメンバは、constな整数型に限りクラス定義中で初期化できる。(9.4.2)
const staticな整数値以外はクラス内では書けない。
かぶった。すまん。
215 :
デフォルトの名無しさん :2007/11/29(木) 13:18:38
引き続きなんですが、どうやったらcppに定義できますか? Hoge.h class CHoge { static const char Names[3][6]; }; Hoge.cpp CHoge::Names[3][6] = { "Name1", "Name2", "Name3" }; C2373 Namesが再定義されています。とコンパイルエラーになります。 よろしくお願いします。
なんでHoge.cppの方に型を書かないの?
>>210-231 ソウイウコトダッタノカ。
早とちりすまん。
>>215 のコードだと、cppの方に型指定が抜けてる気がするんだが。
正確には
cont char CHoge::names[3][6](以下略
じゃなかろうか。
218 :
デフォルトの名無しさん :2007/11/29(木) 14:02:05
おお、できた!ありがとう!
multimap<int, map<long,int> > みたいなコンテナの入れ子ってできるんですか?
できるよ
221 :
デフォルトの名無しさん :2007/11/29(木) 19:58:27
int Nanakano::Check() { int hensu; hensu = (int)toaru_kansu(); return (hensu); } ってこれ何やってる処理ですか?
222 :
デフォルトの名無しさん :2007/11/29(木) 20:04:03
この、 (int)関数() ってのがわかんないです。何ですか?これ。
223 :
デフォルトの名無しさん :2007/11/29(木) 20:13:24
すみません。キャスト変換ってやつですね。 toaru_kansu()が long型の関数だから、無理やり int型に変換してるみたいです。 toaru_kansu()の戻り値をintにして返してるだけの関数のようですね。。これ。
int Nanakano::Check() {return (int)toaru_kansu();}
225 :
デフォルトの名無しさん :2007/11/29(木) 20:21:06
return の引数って () をつけてもつけなくてもいいんですか?
returnは関数じゃないので、引き数なんてありません。
むしろ、つけちゃダメ retrun(0) って関数を呼び出しちゃうときがある
228 :
デフォルトの名無しさん :2007/11/29(木) 20:42:14
>>227 わかりました。ありがとうございます。
>>226 return
のあとの数字をなんというのでしょう?戻し値?
229 :
デフォルトの名無しさん :2007/11/29(木) 20:44:28
coutとかで画面に出力した文字を簡単にファイルに記録することなんてできる?
戻り値、返り値、返値 好きなの使え
>>229 たとえばこんなのどうでしょ「a.exe > out.txt」
Cならstdoutをファイルでrefopen(こんな名前だっけ?)すればいいけど
iostreamも基本、同じかな?
232 :
デフォルトの名無しさん :2007/11/29(木) 21:07:46
>>231 スゲーーーーーーーーーできました。
ありがとうございました。
233 :
デフォルトの名無しさん :2007/11/29(木) 21:22:08
ifstreamクラスでテキストファイルを読み込む際に、 consoleアプリで行った場合には問題なく動くのですが、DLLとして作成すると同じコードなのにファイルの読込に失敗します。 原因わかりませんか?
エスパーすると、実行時のパスが違うというオチでは
235 :
デフォルトの名無しさん :2007/11/29(木) 21:30:50
>>234 excel VBAでDLLを読み込んでいるのですが、実行時のパスってどこにあるんでしょう?
exeファイルの場所??
>>235 Excelのある場所になるのかのぉ?
悪いこと言わないから絶対パスですればよろし
C:\Documents and settings\〜 とか、そのへんの予感
238 :
デフォルトの名無しさん :2007/11/29(木) 21:48:30
作戦1 : ファイルの絶対パスまで含めてみた → 変なエラーがたくさんでて終了 作戦2 : パス通してみた → 結局読み込めない がーーー意味がわからないです…。 Consoleでちゃんと読み込めていることにさらに疑問。
なめてんのか?
241 :
デフォルトの名無しさん :2007/11/29(木) 22:23:20
>>240 ソースは全部会社にあるので確認ができないわけです…
242 :
デフォルトの名無しさん :2007/11/29(木) 22:41:47
>>240 俺のエスパーはたぶん \\ だと告げている
うーん・・・ a.cpp namespace a { void func() { } } // namespace a といった、名前空間内にある関数を、他のファイルから参照する方法は無いんですかね? 名前空間に閉じ込めてなければ、 extern void func(); でいいんですけど…
え? namespace a{ extern void func(); }; でいいんじゃないの?
namespace a{ extern void func(); }; で宣言、 a::func(); で使う。
247 :
デフォルトの名無しさん :2007/11/30(金) 03:41:57
>>245 ,246
(・∀・)ありがとう!
分かってみると単純ですね(´・ω・)お騒がせしました。
248 :
デフォルトの名無しさん :2007/11/30(金) 10:28:07
ラッピングって何ですか? 「この関数はラッピングしてるだけ」ってのは、その関数は別の関数を呼んでるだけで処理をやってない って意味でしょうか?
adapter patternでぐぐれ
250 :
デフォルトの名無しさん :2007/11/30(金) 10:38:39
ある関数をプロトタイプ宣言しているヘッダファイルは見つけたんですが、 そのヘッダファイルを開いても意味不明の構造体が並んでるだけで、 その関数の処理自体がどこにも書かれていません。 この関数はどこにあるのでしょうか? printf()関数などもそうですが、中身がどこにも書かれてなくても使えるものなのでしょうか? その場合、その関数の使い方などはどこで知ったらいいですか?
>>250 ふつうは、ライブラリの中にコンパイル済みのコードが入っている。
Windowsだと 〜.lib 〜.dll、UNIX だと lib〜.a lib〜.so とか。
使うだけなら、そのソースは必要ない。使い方はマニュアルを読む。
static link library 使い方はドキュメント見れとしか言えないね でも引数と戻り値、概要、例外安全性、計算複雑性(?)等のインタフェースが分かったらそれで使えるでしょ
253 :
デフォルトの名無しさん :2007/11/30(金) 10:49:44
>>251-252 なるほど。.lib や .dll にあるんですね。ありがとうございます。
じゃあ、その関数の中身がソース上どこにもなかったら、外部で作って渡された部分と思って間違いないですね。
254 :
デフォルトの名無しさん :2007/11/30(金) 12:49:44
void Kansu(int karihikisu) { } という関数で、return 文のない関数がありました。 これはどういうことですか?なくてもいいんでしょうか?
returnがない場合はコンパイラが勝手にretrunを挿入してくれてると思われ ただい返り値がvoid以外の場合はコンパイラエラーになると思われ
>>255 returnを「挿入」するわけではないので念のため。
インライン展開してしまうかもしれないし、ジャンプに置き換えているかもしれない。
関数のスコープ範囲から抜ければ、その関数から呼び出し元に戻るので、 voidの関数においてはreturnを明記しなくても問題ない、処理の途中でreturnさせるなら必要だけど。 環境依存と言語仕様は別じゃない? returnを書いてある関数がインライン展開される事だってあるだろう。
258 :
256 :2007/11/30(金) 14:15:32
>>257 あーまぁ、言いたいのは1行目だけだから。2行目は確かに余計だったかもね。
259 :
デフォルトの名無しさん :2007/11/30(金) 16:36:47
よくは分かりませんが、main()関数だと、retrun文がないとエラーになったような?? なので、main以外の関数では、コンパイラによっては正常にコンパイルでき、あった場合と 挙動になんら変わりはない。ってことで・・・いいんでしょうか・・
260 :
デフォルトの名無しさん :2007/11/30(金) 16:37:42
Windows フォームアプリケーションのソース入りのプロジェクトフォルダを別の環境の Visual Studio 2005 で呼び込むと、 「 ソース管理 ! プロジェクト○○.vcprojはソース管理下に存在しているようですが、関連付けされた ソース管理プラグインがこのコンピュータにインストールされていません。 このプロジェクトのソース管理は無効になります。 □次回からこのダイアログ ボックスを表示しない(D) [ OK ] [ ヘルプ(H) ] 」 と出て、その後 「 ソース管理 - データベースにアクセスできません ●一時的に管理なしで作業する(T) ○ソース管理の関連付けのバインドを完全に削除する(P) [ OK ] [ ヘルプ(H) ] 」 と出ます。これはどういう原因で起こっているのでしょう?
261 :
デフォルトの名無しさん :2007/11/30(金) 16:42:25
>>260 続き
この状態で、「一時的に管理なしで作業」し、コンパイルした場合、何か
実行後のファイルに影響が出ますか?
中間ファイルや実行ファイルなどのゴミが混ざっていて、実行後のファイルにはなんの影響も
ないのであれば、コンパイルに必要なファイルだけをあれば教えていただきたいです。
あるファイルはこんな感じ↓です。
└「A」フォルダ
├「Release」フォルダ
│ ├BuildLog.htm
│ ├B.obj
│ ├A.dll.intermediate.manifest
│ ├A.obj
│ ├A.res
│ ├mt.dep
│ └vc80.idb
├A.vcproj.MEX.administrator.user
├A.vcproj.vspscc
├mssccprj.scc
├ReadMe.txt
├resource.h
├StdAfx.h
├vssver.scc
├B.cpp
├A.cpp
├A.def
├A.h
├A.rc
└A.vcproj
>>259 そのKansuは戻り値がない(void)が、mainには戻り値がある(int)。
戻り値がある関数は、returnが必須。
戻り値がない関数は、その関数の最後まで実行する場合はreturnが要らない。
>>260 スレ違い。VCスレにでもどうぞ。
>>259 main()は一般的に、int main()なので戻り値を「戻さないといけない」のでreturnが必要になる。
但し、c++の場合は省略が許されているし、void main()とした場合には戻せないので必ずしも必要ない。
その他の関数の場合は、voidじゃない限り戻り値を戻すことを明示する為にreturnが必要になる。
仮想関数の引数にイテレータを渡したいんですけど、どうすればいいですか? class Base { public: template <class Iterator> void f(Iterator first, Iterator last)=0; }; このようなことがしたいんですけど、仮想関数を関数テンプレートにすることができず困っています。 引数を具体的な型にすると、汎用性がなくなってしまうし、う〜ん・・・。
テンプレートクラスじゃダメなの? 簡単に出来ない理由を説明すると、複数の.cppファイルなどで使われるテンプレート関数の型を、 1ファイルずつコンパイルするコンパイラが認識できないので、仮想関数テーブルが作れないんですよ。
267 :
264 :2007/11/30(金) 19:32:32
レスありがとうございます。
>>265 DLしてサンプル見てみました。
これ使って解決できそうです。
>>266 ポリモフィズムしたいので、Baseをテンプレートにできないです。
268 :
デフォルトの名無しさん :2007/12/01(土) 09:39:44
class TestClass { static int x; public: TestClass(); //default constructor 以下略 }; int TestClass::x = 0; こんなインクルードヘッダを複数の *.cpp ファイルで インクルードしまくったら,TestClass::x の実体は それぞれに確保されてしまって,リンカが混乱しますか?
やってみろ
270 :
デフォルトの名無しさん :2007/12/01(土) 11:23:56
staticでないメンバ関数のリンク時のアドレスを得る方法はありませんか? struct A{ int func(); }; void *p = (void*)&A::func; 手持ちの環境はVC6ですが、キャストできないというエラーが出てしまいます。 static_castやreinterpret_castも試しましたがダメでした。 標準的なプログラムから外れているのは承知しているのですが、リンク時の アドレスがどうしても必要なのです。(メンバ関数ポインタのアドレス以外の 情報は不要で、アドレスの取得はリンク時に静的に解決したいのです) 最近のC++の仕様的には書きようが無いのでしょうか? よろしくお願い致します。
普通にメンバ関数ポインタを使えばいいのでは? typedef int (A::*func_ptr)(); func_ptr p = &A::func;
unionに入れて取るかだけど、メンバ関数ポインタは条件によっては 8バイトになったり、16バイトになったりするからなー。
メンバへのポインタと普通のポインタって 何が違うの?何かの本ではメンバーへのポインタは 相対位置を表すみたいに書いてあったけどよくわからん。
staticじゃないんだから実行時に決まるんじゃないの??
多重継承されたクラスがあったとして、thisポインタの 調整情報なども入れねばならないとか何とか。 一時期のg++は「メンバ関数」を「第一引数が明示的なthisをとる普通の関数ポインタ」 に変換する機能があったけどなー。そんなサンクくらい自分で作れってことかなー。
>>270 非staticなメンバ関数へのポインタは通常のポインタとは
違うから、void *p = (void*)&A::func; はエラー。
funcがstaticならvoid *p = &A::func; はOK。
278 :
270 :2007/12/01(土) 12:40:40
みなさん御指南ありがとうございます。
>>275 それっぽいプラグマだと思ったのですが、やり方が悪いのか、うまく行きませんでした。
>>276 古いコンパイラだと普通にキャストするだけで取り出せたんですよね。
thisの変位に関する御指摘が複数ありましたが、その辺は無視して
リンク時のアドレスが欲しいんです。
ひと手間増えますが、とりあえずstatic関数経由で逃げることにしました。
ありがとうございます。
メンバ関数ポインタが理解できないヘタレか? コイツは。
そのアドレスを何に使うんだろうな
*uck
**ck
struct hoge void f(); }; 上から下のようにmem_fn的な使い方なら用途はあると思う。 void hoge_f(hoge& h) { h.f(); }
それなら静的メンバ関数で十分だろ。
bindみたいなの作ろうとしてんじゃね?
その用途じゃアドレスだけ取ってもthisを調整できないし仮想関数テーブルも引けないから正しく呼べない気がするが… 動的バイナリ変換とか自己書き換えでもやりたいのかね?でもそれじゃstatic関数を挟んだら意味ないよなぁ
俺のエスパー能力で答えると、
たぶん
>>278 はメンバ関数ポインタが理解できないヘタレ。
そこでこんな関数でも作ってつかってるんじゃね?
class Foo
{
public :
static void func1(Foo *this_ptr /*必要に応じて引数とか*/) ;
static void func2(Foo *this_ptr /*必要に応じて引数とか*/)
} ;
void (*p)(Foo *) ;
Foo foo ;
//どちらかを呼び出す。
p(foo) ;
普通はこうするんだけどな
void (Foo::*p)() ;
(foo.*p)() ;
>>287 メンバ関数ポインタと通常の関数ポインタの違いを説明してもらえますか?
メンバ関数ポインタの使い方なんか本見りゃアホでもわかると思う。 mem_fun以外でどういうときに役に立つの?
>>288 メンバ関数ポインタはメンバ関数を指すポインタ
通常の関数ポインタは通常の関数を指すポインタ
違いは明確
>>290 具体例を挙げて、どこが明確に違うのか
説明できますか?
292 :
デフォルトの名無しさん :2007/12/01(土) 16:13:42
メンバ関数を指すポインタと、通常の関数を指すポインタ 違うよね!うん!違うね!
メンバ関数と通常の関数の違いもわからないのか?
実装上の違いを求めてるんならスレ違いだな
メンバ関数だからって面罵するなよ
質問なんですが #include <iostream.h> int main() { int a; cin >> a; if(a == 0) cout << "0000" << endl; else cout << "1" << endl; return 0; } 文字を入力されたとき1を返すようにしたいのですが何か良い方法はありませんか?
なんかうだうだ話でてるけど、
>>270 の場合、ただ単に、
void*型へのメンバ関数ポインタのキャストは禁止されてる。
>>291 使うときにthisポインタが必要だからややこしいのが
メンバ関数ポインタじゃないの?
変なこと言ってたらスマン。
>>296 何の文字よ。
char a;
cin >> a;
とか?もうちょっと詳しく
>> 299 数字以外が入れられたときに1を返すようにしたいです。 例といたしましては abc など 入力された場合 1を返す。
>>300 こうか?よくわからんが
int a;
cin >> a;
if(cin) cout << "0000" << endl;
else cout << "1" << endl;
>>301 申し訳ないです。
数字だけの処理をしたいだけで 0の入力がされれば0000を出力し、
それ以外の数字を入力されれば1を返す。
しかし、ユーザーが例外的に文字を入力した時1を返す処理をしたいと
思っています。
数字か文字かを判断できる処理があればと思い質問させていただきました。
>>303 if(cin && a == 0) でいいんじゃない
>>305 できました。
if(cin) これはどういった処理なのでしょうか?
もしcinがtrueならば
ストリームの failbit を確認している 不正な入力(例えばintを要求しているのに文字を入力した)があるとストリームに failbit がセットされる なので failbit を確認すれば過去の入力が正常であったか判る
>> 307 そうですか。 これは、複数 cin を使った場合一番最後につかったものが 適応されるのでしょうか?
いや、クリアされるまでずっとセットされっぱなし
>>307 今 書き直しました。
#include <iostream.h>
int main()
{
int a;
cout << "数字を入力してください。" << endl;
while(1){
cin >> a;
if(cin){
if( a == '0') cout << "0000" << endl;
else cout << "1" << endl;
break;
}
else cout << "数字以外が入力されました。 もう一度数字を入力してください。" << endl;
}
return 0;
}
やっぱり無理で 文字が入力されると無限ループになってしまいます。
数字以外の文字を読み込んでないんだから、その文字はずっとcinの中に残りっぱなし、毎回読み取りエラー
cin.clear()とかcin.ignore()とか
>>314 文字が入力されるともう一度入力させるようにするにはどうすればいいでしょうか?
cinの中に残ってる文字を読み捨てて failbit をクリアする
318 :
312 :2007/12/02(日) 12:56:23
cinを使わず違うやりかたで誤字入力を回避できる方法はないでしょうか?
いったん文字列として読み込んでから 自前で数値か判定すりゃいいやん
>>319 isdigit関数とatoi関数で出来ました。
>320 どうせなら strtol() とか使えば?
>>321 ありがとうございます。 使わせていただきました。
std::string( 1, '\0' ) == "" が false になってしまいます。 std::string( 1, 'a' ) == "a" は成り立つのに、なぜ?
>>323 std::string( 1, '\0' )は長さが1だが、""は長さが0だから。
file.hに void F1(); void F2(){ puts( "F2" ); }; file.cppに #include "file.h" void F1(){ puts( "F2" );} と書いて、mainを呼んでるmain.oとリンクさせると F2()が多重定義されてるぼけってエラーが出るんだけど これどう解決すりゃいいですか?
static void F2(){ (ry
単にインクルードガードしてないだけじゃない?
>>326 普通は.hにはプロトタイプ宣言飲のみを書いて中身は.cに書く。
解決方法は>327を始めいくつもあるし ここで教えるのも簡単なんだろうけど それよりは#includeというものがどういう操作かちゃんと理解しないと 同じエラーを繰り返すだけだよ。
> mainを呼んでるmain.o ここも変
>>328 インクルードガードはしてる。
>>329 .hにプロトタイプ宣言だけするのは普通なんだけど、
ちょっと書きたくなった。
>>static
やってみる。
>>331 何が変なのかわかんね。おせーて
いや、mainを再帰しているかもしれない! って、mainの再帰は規格違反だっけか?
ぁーごめん。 mainを呼んでるmain.cppをコンパイルってmain.oになった ってこと。 mainを呼んでるって語弊あったすまん。
呼んでる->定義してうr
語弊っていうか、正反対。
なんでstaticで解決できるんですかこれ。
staticじゃなくて無名namespaceかinlineの使用を推奨。
>>338 staticにするとコンパイル単位の外からは見えなくなるから
コンストラクタの記述について質問なのですが、 MAT* m_matrix[4] というMAT型データのポインタ配列のポインタを渡したい場合、呼び出す側は &m_matrix で呼び出そうとしているのですが、コンストラクタの方の型指定は どのようにすればよろしいのでしょうか? ( MAT**では通りませんでした)
>>341 いいたいことがよくわからないけど、constructor の型を指定したいの?
書き方が悪くてすみません・・・ コンストラクタに限らず、引数として MAT* m_matrix[4]のポインタを渡したい場合 受け側の関数の宣言ではどのように型を記述すればよいのか お聞きしたかったのです。
f(MAT* (*p)[4])
戻り値忘れてた void f( MAT* (*p)[4] );
gnuplotを使うプログラムの質問なのです 現在、C++の値をgnuplotに渡すとき毎回gnuplotが起動します。(正確にはwgnuplotに値を渡している) これを一回起動したら、以降は起動中のgnuplotに値を渡すのはどうすればいいでしょうか?
>>347 それはC++の問題じゃないのでgnuplot関連スレへどうぞ。
>>348 やっぱりそうでしたか、gnuplotにいってきます。
ありがとうございました。
350 :
347 :2007/12/04(火) 20:47:49
gnuplotではうまくいきそうに無いので プログラムで何とかしたいのですが プログラムのループの中のデータを毎回別のファイルに保存したいのですがどうすればいいですか? 例えば t=0 0.txt , t=1 1.txt , ・・・ のように保存できるでしょうか?
>>350 ループ内で毎回openして書き出してcloseすればいいんじゃないか。
352 :
347 :2007/12/04(火) 21:07:00
今現在は fstream EE ( "1.txt" , std::ios::out ) ; を使って保存しているんですが この1の部分をどうやって変更すればいいのかがわからないので、質問しました。 ループ内に入れるのはわかるんですが、ファイル名の変更がわかりませんという質問です。 文章が下手ですみません
stringstream、strstream、sprintf、snprintf
354 :
347 :2007/12/04(火) 21:16:19
こんな便利なのが・・・
>>353 解決しました。ありがとうございます。
>>352 ostringstream使えば?
例
for(int i = 0; i < 10; ++i) {
ostringstream oss;
oss << i << ".txt"; //ファイル名作成
ofstream ofs(oss.str().c_str()); //ファイルオープン
ofs << "output i = " << i << endl; //ファイルへ出力
ofs.close();
}
コードサイズで質問 aaa()のほうがスタック開放コードが少ない分、コードサイズが小さい? そもそもスタック開放コードって複数生成されるのですか int aaa() { int ret = 1; char buf[1024]; if(...) { ret = 0; } // スタック開放コード return ret; } int bbb() { char buf[1024]; if(...) { // スタック開放コード return 0; } // スタック開放コード return 1; }
>>356 コンパイラにもよるんだろうけど
関数ごとのリターン処理は1箇所でジャンプ(つまりはgoto)で飛んでるものが多いと思う。
スタックの開放コードはスタックポインタを動かすだけだからきわめて軽微。
x86用のVC++2005だとこんなコード。
mov esp, ebp
pop ebp
ret 0
>>357 いまどきは mov, pop の代わりに leave ニーモニックを使ってあることも。
なんで enter ニーモニックは使わないんだろう…
スレ違いスマソ。
C++の規格書?のreinterpret_cast(5.2.10)を読むと 4段落 A pointer can be explicitly converted to any integral type large enough to hold it. 5段落 A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; とあるんですが、整数→ポインタ→整数 と変換した場合は元の値は保たれるのでしょうか? (explicitly convertの意味が良く分からない・・・厳密な変換とは??) 保たれるとして、"large enough"とか"sufficient size"かを確かめるのは、sizeofでチェックすれば十分でしょうか? やりたいこと: 他人が提供するC言語で書かれたvoidポインターのコンテナに、 今はヒープに取った整数型をポインタを介して格納しているが せっかくなのでvoidポインタに直接整数を格納したい。(パフォーマンス上の理由)
>>359 >整数→ポインタ→整数 と変換した場合は元の値は保たれるのでしょうか?
処理系依存のはずだから保障はないはず。表示して確認すればよいと思う。
ただ、たいがい同じビットパターンだと思う。
>(explicitly convertの意味が良く分からない・・・厳密な変換とは??)
明示的な型変換という意味。(暗黙では変換不可)
BCB6の場合、 const char* p1 = "hoge"; short n1 = reinterpret_cast<short>(p1); // エラー。shortはlarge enough to holdではない。 __int64 n2 = 1 << 30; n2 <<= 30; const char* p2 = reinterpret_cast<const char*>(n2); // OK。でもn2の上位32ビットは失われる。 この場合、整数が小さすぎる心配はコンパイラに任せれば安心だけど、 大きすぎるほうの心配はしなくちゃいけない、ってことになるね。
>>359 その「整数」として、intptr_tやUINT_PTRなどの「ポインタと同サイズの整数型」を使うなら。
364 :
356 :2007/12/05(水) 23:54:42
>>357 なるほど、returnの位置に関係なさそうなので、
深く考えないことにします。
typedef void (*pfunc)(); void c_func(pfunc func) { func(); } void cpp_func() { throw 0; } void hoge() { try c_func( }
失礼しました。途中で書き込んでしまいました。 C関数は誰かが作ったC言語のライブラリだとします。 以下のようにC関数内でC++例外を投げるのは規格上大丈夫なのでしょうか? typedef void (*pfunc)(); void c_func(pfunc func) { func(); } // C関数 void cpp_func() { throw 0; } // 例外を投げるC++関数 void hoge() { try { c_func(&cpp_func); } catch(int) {} }
>>366 Cの関数から呼び出された中で例外を投げたらどうなるかは未定義。
Cの関数に限らずC++同士でも、別のコンパイラでコンパイルした関数に向けて例外を投げると未定義の動作。
foo.hpp:
void foo();
foo.cpp:
#include "foo.hpp"
void foo(){
throw 0;
}
bar.cpp:
#include "foo.hpp"
int main(){
try{ foo(); }
catch(const int&){}
return 0;
}
foo.cppとbar.cppでコンパイラが違うと、まずい。
2つのコンパイラのmangleが同じでリンク出来たとしても、
何が起こるかわからない。
「別のコンパイラでコンパイルした関数に向けて例外を投げると」 ってなんか変な表現だな とにかく、例外を投げると関数が終了して呼び出し元にどんどん戻るじゃん、 それで他のコンパイラでコンパイルした部分に達すると未定義の動作になるってことね。
そういえば未定義って言うけど実際やるとどうなるんだろう
鼻から(ry
#pragmaが未定義だったから、大昔のGccはアドベンチャーゲームを起動したりしたんだぜ?
374 :
デフォルトの名無しさん :2007/12/08(土) 09:05:44
自分で定義した operator[] に他のメソッドからアクセスするには (*this)[hogehoge]みたいにしなくちゃダメ? あるいは this->operator[](hogehoge) とか. もっと見やすい書き方ないかなぁ. それもこれも this が参照じゃなくてポインタなのが悪い気がする. しかし参照が仕様に入った時期を考えると仕方ない気もする. いまさらどうしようもないか.
operator[]の中身を別のメンバ関数に移してそっち呼ぶようにしたらいいよ
C++ の for( int i = 0; i < 256; ++i ) って書き方は慣れたし便利だなぁと思うんですが for( char buf[ 1024 ]; fgets( buf, sizeof(buf), fp ); ) って書き方はどうなんでしょう? 変数のスコープは↑の方向が小さいですが char buf[ 1024 ]; while( fgets( buf, sizeof(buf), fp ) ) の方が普通ですか? そもそもfgetsなんか使わねぇよ、ってのは無しでお願いします。
コンパイルしたら同じコードになるからどっちでもいい。 ただwhileは条件でループ、forは回数でループってイメージがあるので、 whileの方が違和感がないし、forだと可読性が落ちるように思う。 (ソースを流し読みするときに、一瞬考えてしまう)
>>376 for の初期化部分に、単なる変数の定義を入れるのは好ましくない。
スコープを制限したいなら、全体をブレースで囲むほうがいい。
関数オブジェクトについて質問です 関数アダプタを使わない場合、 メンバ変数のない単純な関数オブジェクト(比較オブジェクトとか)は通常の関数で代替できる場合が多いと思うのですが、 その場合に関数オブジェクトを使う利点って何でしょう?
コンパイラがインライン展開してくれる とレスしようとしたら既にされてた。
>>381-382 ありがとうございます
関数でもinlineをつければインライン展開されうると思うのですが、
それよりも優れているのでしょうか?
>>383 通常の関数を渡した場合は、関数ポインタを渡したものとされるので、
インライン展開されにくくなる。しちゃいけないってことはないんだろうけど、
そこまでやってくれるコンパイラは見たこと無いな。
関数ポインタの場合はサイズと速度のトレードオフがある 下記の a(b) と a(c) では同じ a がインスタンス化されうるが インライン化しちゃったらそれができない template<class X> void a(X x) { x(0); } inline void b(int){} inline void c(int){} void d() { a(b); a(c); }
>>384 ああ、そうか、ポインタを経由するから……そこまで頭が回りませんでした
参考になりました
ありがとうございます
>>385 なるほど、確かにそういうことも起こりますね
結局はテンプレート関数・クラスを用いる場合に、
関数オブジェクトの方がより限定化された範囲で実体化されるので高速化しやすいってことですね
ありがとうございます
コンパイラによるとしか言いようがないかもしれないけど質問。 関数オブジェクトのoperator()と、それを呼び出すコードが別の翻訳単位になった場合、 関数ポインタとどっちが高速になりやすい? あるいは、あなたならどっちを選択する? foofunc.h: struct Foo{ bool operator()(bool cond); } foofunc.cpp: bool Foo::operator()(bool cond){ return !cond; } main.cpp: #include "foofunc.h" #include <iostream> int main(){ using namespace std; Foo f; cout << f(false) << endl; }
>>388 VC8(VS2005)の結果。
--- main.cpp ---------------------------
#include "foofunc.h"
#include <iostream>
int main(){
using namespace std;
Foo f;
cout << f(false) << endl;
00401000 mov eax,dword ptr [__imp_std::endl (402044h)]
00401005 mov ecx,dword ptr [__imp_std::cout (40203Ch)]
0040100B push eax
0040100C push 1
0040100E call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402038h)]
00401014 mov ecx,eax
00401016 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402040h)]
}
0040101C xor eax,eax
0040101E ret
390 :
デフォルトの名無しさん :2007/12/09(日) 12:58:21
w
const を外すときは const_cast でよいとして、オーバーロードを解決するために const を付けるのも const_cast でいいんですか?
>>391 const_cast は危険なキャストをしてないか調べるときに検索するから、
安全な奴は static_cast にしといてくれたほうがいい。
スタック変数用のメモリというのは、 関数に入った時点で全て確保されているものなのでしょうか? それとも変数の宣言位置まで到達して初めて確保されるものなのでしょうか? 例えば下記のようなコードを書いてしまうと、 getHoge()の呼び出し毎に無駄なスタック領域が確保されてしまうものなのでしょうか? const Hoge& getHoge() { static Hoge hoge; if (hoge.isInitialized()) { return hoge; } // ここでhogeの初期化処理のために変数を大量に使用。 // 以降、hoge.isInitialized()はtrueを返す。 return hoge; }
>>393 たいがいの環境では、関数に入った時点で、ローカル変数全部の領域が取られる。
395 :
393 :2007/12/09(日) 23:55:26
>>394 即答ありがとうございました。
大人しく初期化用に別関数を設けます。
>>393 コードやコンパイラの実装によるだろ。スタックの確保なんて無駄になるって言っても
数命令だろうから気にしないでいいと思うけど、心配ならコンパイル結果のアセンブリ
見ないと確実なことはわからない。
>>393 実行時に処理が進むたびに必要な領域を確保するのはコストがかかって仕方ないんじゃない?
プラットフォームによって違うだろうけど、そもそもスタックってプロセス生成時に
あらかじめ決まった仮想アドレス空間を割り当てて、関数呼び出しのたびに領域を割り当てるのではなく
フレームポインタ(?)だかなんだかをずらしていくだけ、というのが多いと思う。
間違ってたら全面的にゴメン。
>>393 スタックは予め確保されてます、関数毎に確保されるものではないです。
コンパイラはespレジスタ(SH系だとr15など、スタックポインタを管理するレジスタ)が示すポインタに
ローカル変数を積み重ねる形のコードを出力するだけで、スタック領域はOSの管理となっています。
スタック領域が足りなくなったときの振る舞いはOSによって異なるし言語範囲外なので除外。
おまいらそろそろ質問自体が規格の範囲外だということに気づけ
>>398 ヒープとスタックの境界が決められてるだけで確保はされてないだろ
確保されていなければ使えないと思うのですが。 「確保」の概念の違いなのかな?
>>393 そんな簡単なことでオーバーヘッドになったりしないよう
偉い人はちゃんと考えてくれているので気にしなくていい
>>400 staticな変数は確保されているだろうが、一般的な実装では、
auto変数(ローカル変数)は関数がコールされるたびにスタックに積まれる。
そうしなきゃ、再起呼び出しなんてできないよ。
階乗を求める
int kai(int n)
{
if(n=1)return 1;
else return n*kai(n-1);
}
の場合、スタックにn回分のローカル変数(とreturn時に戻り先のアドレス)が積まれる。
403 :
400 :2007/12/10(月) 15:11:45
いやだから、その「スタック」というやつはプロセス起動時にOSによって 「スタック領域」と言う形で用意されているのではないだろうか、という話。
実装の話は他所でやれ
>>403 とは限らない。Cランタイムライブラリが_main()とかで初期化する場合もある。
ヒープ食いつぶすとスタック領域に食い込んで、スタック壊す実装系もある。
407 :
デフォルトの名無しさん :2007/12/11(火) 00:06:28
#define private public !!!!!!
409 :
デフォルトの名無しさん :2007/12/13(木) 06:34:37
#define class struct
411 :
デフォルトの名無しさん :2007/12/13(木) 19:03:17
好ましくない方法だと聞きましたが vector<vector<int> > a; と宣言した領域のたとえばa[1][1]に値を放り込むにはどう書いたらいいのでしょうか?
412 :
デフォルトの名無しさん :2007/12/13(木) 19:04:52
連投ですいません static vector<vector<int> > a; の場合ですと直接 a[1][1]=3; のように書けると自分では思ってるんですが、この場合staticで 全部の値が0だからだと思うんですが、果たして全部ってどこまで 取られているんでしょうか
というか、ちゃんとresizeしてあげないと未定義動作になるんじゃあ。
MSNメッセンジャーなどで見かけるチャットウィンドウ上にURLが張られた場合に 自動的にハイパーリンクにする機能が欲しいのですがどのような関数を使えば いいのでしょうか
416 :
411 :2007/12/13(木) 21:02:37
ありがとうございます けっきょく vector<vector<int>* > a; と宣言し vector<int> *tmp = new vector<int>; a.push_back(tmp); (*a).push_back(x);//xは数値 のようにし cout << (*a)[0]; のように用いることで解消しました
417 :
411 :2007/12/13(木) 21:05:17
またすいません 正しくは右です (*a).push_back(x); →(*a[0]).push_back(x); cout << (*a)[0]; →cout << (*a[0])[0];
418 :
デフォルトの名無しさん :2007/12/13(木) 21:15:38
vector<vector<int> > a(100); for(n=0;n<100;n++) a[n].resize(100); とすればOK a[0][0]からa[99][99]まで使える
vector<vector<int> > a(100, vector<int>(100));
420 :
デフォルトの名無しさん :2007/12/13(木) 21:26:32
typedef vector<int> Dint; vector< Dint > a(100, Dint(100)); とすると、a[]の値をDint(100)型で初期化するって事か なんかどういう仕組みで確保できるのかわからなったよ
421 :
デフォルトの名無しさん :2007/12/13(木) 21:27:29
一次元のときに数値でしか初期化できないものだと思っていたよ
422 :
デフォルトの名無しさん :2007/12/13(木) 21:28:55
vector< Dint > a(100, Dint(100,-1)); cout<<a[0][0]<<endl; という初期化も出来るんだね
無名名前空間使ってる?
使ってる。
426 :
デフォルトの名無しさん :2007/12/14(金) 21:31:27
ソケットを綺麗にラップしたライブラリがほしい
>>425 ファイルスコープの変数に使うくらいしか知らないのですが、
もしよかったらどんな場合に使ったらよいか教えてください。
>>426 それはおいらも欲しい。
中途半端に作ったことはあったけどw
boost::asio::ip
string a; って、 char a[10]; のように、その変数を固定長にしたい(最大長を制限したい)場合どうするの?
気をつける
432 :
デフォルトの名無しさん :2007/12/15(土) 02:58:18
>>429 boost の subversio リポジトリ見てるけど,
最近 asio まわり更新多いね.
>>430 具体的に制限を越える操作をしたときに何が起こって欲しいの。例外?
>>431 >>433 メモリ使用量固定にしたいと考えたんだけど、
どちらで書くにしても、結局事前のチェックをして
から格納しなきゃならないから、確かに
>>431 の
気を付けるしかないってわけですね
>>433 そっか、仕様として想定した範囲以上のメモリ領域
を使った場合に、例外飛ばすようにしておくのも手ですね。
std::sort() について教えて下さい。 std::sort( list.begin(), list.end(), cmpfunc); みたいにしてソート処理させてみました。 string lhs, rhs とすると、cmp func は、 return (lhs < rhs); のようにしています。 これで数字のソートをさせると 10, 11, 12, 1, 2, 3 が 1, 10, 11, 12 ,2, 3 みたいになっちゃうのですが、1, 2, 3, 10, 11, 12 というように 並べるにはどうするのが良いでしょうか?
struct cmpf { bool operator()(const std::string& lhs, const std::string& rhs) const { return (atoi(lhs.c_str()) < atoi(rhs.c_str())); } }; std::sort(ls.begin(), ls.end(), cmpf());
list って sort メンバ関数を使ってソートするんじゃなかったっけ?
そういやそうだな。でも変数名が list なだけで std::list じゃないのかもしれない。
>>434 デフォルトのallocatorを継承してmax_sizeだけいじってなんとかならんかね。
boost::arrayでは如何?
STLの使い方はある程度学習したんですが STLの構造を理解するのに何か良い学習方法 ありませんか? 特にallocatorあたりが理解できてません。
同じものをつくってみる
>>442 allocator<T>のメンバー関数を理解して、独自のコンテナでも作ってみる。
最近C++のいろんな、本読んで勉強してるんだけど 知れば知るほど面白いね 処で参照、引数の参照渡しについて、質問です 引数に関数や、配列等を与える場合は、リファレンスで、組込み型の場合は 値渡しがよいと、認識しているのですが、組込み型の引数が2つ以上の場合でも、 値渡しの方がいいのでしょうか? 例えば unsigned int Foo( const unsigned int n ) const; も unsigned int Hoge( const unsigned int lhs, const unsigned int rhs ) const; でも、値渡しの方がベター?
スマソ ×unsigned int Foo( const unsigned int n ) const; ○int Foo( const int n ) const; ×unsigned int Hoge( const unsigned int lhs, const unsigned int rhs ) const; ○int Hoge( const int lhs, const int rhs ) const; unsignedは考えないでください
>>446 引数それぞれの型に応じて使い分けるのであって、引数の数でどうなるものでもない。
組み込み方かどうかという区分けもあんまり理論的じゃないね。たぶんサイズに応じた
基準を端折って説明されてたのを見たんだろうけど。
引数1つ1つを参照にしても変わらないな 引数をまとめて構造体に入れてそれを参照渡しするなら話は別だが 構造体に入れるときに結局コピーするんだし、 void Foo(long long a, long long b, long long c, long long d){ } void Bar(long long a, long long b, long long c, long long d){ Foo(a, b,c, d); } 引数をそのまま別の関数に渡すんなら、まあ両方とも構造体参照渡しにすれば… (でもそういう場合ってインライン化しちゃうか)
>>448 >>449 >>447 です
サンクスです、
>引数それぞれの型に応じて使い分けるのであって、引数の数でどうなるものでもない。
なるほど、リファレンスのバイト数:値のバイト数との大小関係を考慮しろってことだね
だとすると、VCとかだと、リファレンスのサイズって何バイトなんだろう?
Effective C++ではint型の場合は参照渡しより、値渡しのほうが良いと書いてあったけど
てことは、リファレンスは32バイト以下なんだろうか?
>構造体に入れるときに結局コピーするんだし
そうですね、構造体ってことは、クラスと同じようなもんだとすると、コンストラクタ、デストラクタが
動くから、そのコストもかかることになりますね。
>>447 です、またまた、ごめんなさい
変な日本語になったかな?
インスタンスのサイズ>リファレンスのサイズ
の場合、参照渡しが○
インスタンスのサイズ<リファレンスのサイズ
の場合、値渡しが○
ってことが書きたかった(^^;
452 :
447 :2007/12/15(土) 22:40:33
#include <iostream> using namespace std; int main() { int n = 10; cout << sizeof( n ) << endl; cout << sizeof( &n ) << endl; return 0; } あれ?同じサイズだな? 値渡しの優位性は何処なんだろう?
値ならレジスタで済むので高速
そろそろ、ここはお前の日記帳じゃないといいたい。
>>447 値渡しで一番速いのはCPUの扱うワード長を基準に考えればいいだろう。
まあ、基本型のデータをわざわざ参照にしなくてもいいと思うし。
データのコピーより参照を手繰るほうが早く済みそうなら参照・ポインタを使えばいい。
>>447 それと値渡しでconstを指定する意味はない。
>>453 なるほど@納得した
>>454 まぁそう言うな、どうせお前も暇なんだろww
さて、スキーリしたので、プログラミング言語C++第3版の
続きよーもうっと
457 :
デフォルトの名無しさん :2007/12/15(土) 23:19:24
>>455 受け取った側でポカミス防げるじゃん.
まぁ渡した側としてはどうでもいいけど.
>>445 >>それと値渡しでconstを指定する意味はない。
あ、これね前説が抜けてたけど、
FooやHoge関数内で、引き数をいじって、変えて欲しくなかったからだ
だから意味はあるのよん
大抵typedefで組み込み型にも別名つけてて、 元がわかんなくなっちゃって、えいやってconst 参照で渡すように書いちゃうんだけど・・・
>>458 int Foo( const int n ) const;
int Foo( int n ) const;
のオーバーロードができなくなるという
問題はあるがな。呼ばれた側で値を変えたく
ないなら組み込み型でもconst int&にするわ。
boost::asio::ip って日本語の資料皆無だな
>>458 プロトタイプのほうを
int hoge(int n);
にして、関数を定義してるほうを
int hoge(const int n) { ・・・
すべしって、なんかの本に書いてあったよ。
>>458 オーバーロードではなく
正確には
int Foo( int n ) const;
が定義できなくなるだった。
>>461 書籍に少し載ってる
>>463 ハーブサッターっていう偉人を知ってるか?
>>463 C++ Coding Standards
>>462 >>447 だけど
それは、ないやろ
VS2005だと、error C2511が出るぞ?それとも関数定義のブレスの中で何か
テクニックがあるのかな?
今ちょっと、他の本見てみたら、ピアソンの「C++FAQ第2版」では、
int Foo( const int& n );
オブジェクト変更のポカミスには、これが推奨ってなってるな
>>467 VS2005でためしたけど、エラーにならないよ?
自分もエラーにはならなかった int f(int a); int g() { return f(1); } int f(const int a) { return a+1; } class X { void f(int a); }; void X::f(const int a) {}
>>462 の非constのintだけを宣言・定義はconst,非constで定義できるって話かと思ったけど、
なんか違う?g++では「error: redefinition of `void A::f1(int) const'」っていわれた。
#include <iostream>
struct A {
void f1(int n) const;
// void f1(const int n) const;
};
int main()
{
A a;
a.f1(100);
return 0;
}
void A::f1(int n) const {
std::cout << "call int";
n += 200;
}
void A::f1(int const n) const {
std::cout << "call const int";
n += 200;
}
>>462 のこれってどんな利点あるんだ?
>>467 のconst参照ならわかるが、コピーのnを変更禁止にする利点うかばないのだが....
>>470 void A::f1(int n) const
void A::f1(int const n) const
この二つはオーバーロードできない。
参照、ポインタならできる。
以上。
Exceptional C++ 嫁
>>473 ならば、const int& にすべき。
Exceptional C++
嫁
大体
>>460 はそんなオーバーロードを何のためにするんだ?
Any cv-qualifier modifying a parameter type is deleted. [ Example: the type void(*)(const int) becomes void(*)(int) .end example ] Such cv-qualifier s affect only the definition of the parameter within the body of the function; they do not affect the function type.
>>477 妄想で答えると、
>>460 はconst/非constオブジェクト両方受けたいために
オーバーロードしたいんじゃね。
宣言非const、定義constなんて言ってる "C++ Coding Standards" は糞本?
const int& にすべきなんて言ってる "Exceptional C++" は糞本?
両方ともハーブサッターだろ for(;;)とwhile(true)と同じ
いいや、いい本 本では、constで定義を薦めてるんではなくて constの宣言はよしなさいと言っている
組み込み型でも、const 参照使え 定義const引数でも、宣言非constに汁 と言ってるようじゃ ハーブサッターって糞著者だな
読みもしないで糞と決めつける奴は糞以下だけど
>>481 const int&で全部糞扱いですか
よくわからんが宣言と定義で型が違うのは気持ち悪い
実装の都合をインタフェースに反映させるのはよくないと思う。
値渡しの引数を受け取った側でいじるってやらない? 俺はローカルオブジェクトと同じ感覚でちょくちょくいじるんだけど # f(int)をf(const int &)にするのは時期尚早な不最適化だと思う
>>446 です
@「関数の引数には値渡し、参照渡しがどっちが効率的なのか?」
という質問に、
A「オブジェクトを予期せずに変更してしまうのを避けるにはどうすべきか?」
という、問題が派生してしまったことにより、議論が混乱しているようなので
ここは一度問題を切り分けて、議論する必要があるね、
@のコンセンサスにかんしては
・値渡しよりはconst参照渡しを使う。そうすれば、一般的に効率的で、スライス問題が起こらない。
・ただし、これらは、組込み型とSTLの反復子・関数オブジェクトには適用されない。これらについては、普通、値渡しが適当。
ということでny
ではAに関して、皆さんの意見を語ってください。
>>491 >A「オブジェクトを予期せずに変更してしまうのを避けるにはどうすべきか?」
>という、問題が派生してしまったことにより、議論が混乱しているようなので
関数内でコールもとのオブジェクトを更新を避けたいとき、値渡しかconstの参照/ポインタを
使うことについては異論がないんじゃない?
(一部、混乱している人もいるようだけど。)
今議論していたのはインターフェース(プロトタイプ宣言)で int と引数を宣言しておいて
実装(関数定義)で const int として宣言することの是非ではなかったっけ?
コンパイラの最適化によって、const int& で渡すのはintで渡すのと同じ効率になってくれないかな? そこまで賢くない?
>>493 インライン展開するときに実引数によっては可能だと思うよ。
引数宣言の直接 const が意味無いから付けない。宣言と定義で見た目が変わると いやだから定義でも基本的に付けない。でも付けてもいいし、実際に付ける時もある。
元の話は、const int& じゃなくて const int だというのに気づいてない人がいるような気がする。 >492 >491 の >A「オブジェクトを予期せずに変更してしまうのを避けるにはどうすべきか?」 ここでいうオブジェクトはコール元ではなくて関数内でのオブジェクトだと思われ。 C++ Coding Standards では const int って宣言に書くと混乱が発生するので(このスレですら発生してるし)、「やるんだったら」定義につけろってことじゃなかったっけ? 個人的にはまず@によって渡し方を決定、(俺はやらんけど)やりたければ値渡しでも定義側で const つければ?ぐらいの立場だな。 あと、ここまで出てなかったと思うんで挙げておくと、引数の型については Boost call_traits ってのもある。これだと const int になるみたい。
497 :
デフォルトの名無しさん :2007/12/16(日) 11:20:50
#include "stdafx.h" #include <iostream> #include <vector> using namespace std; typedef struct { double x,y; } _tBullet; class CBullet { public: void Move( _tBullet *bullet ); }; void CBullet::Move( _tBullet *bullet ) { bullet->y -= 10.0; }
498 :
デフォルトの名無しさん :2007/12/16(日) 11:21:25
int _tmain(int argc, _TCHAR* argv[]) { CBullet CBulletFactory; vector<_tBullet> vBullet; _tBullet bullet; int i; for( i=0; i<10; i++ ) { double x = (double)(rand()%64)/10; double y = (double)(rand()%64)/10; bullet.x = x; bullet.y = y; vBullet.push_back(bullet); } vector<_tBullet>::iterator p = vBullet.begin(); while( p != vBullet.end() ) { CBulletFactory.Move(p); // ここでエラー p++; } return 0; }
499 :
デフォルトの名無しさん :2007/12/16(日) 11:23:04
上記のコードを利用しているのですが VC++6.0 では正常にコンパイルされるのですが VC++Express Edition では c:\documents and settings\owner\デスクトップ\hoge2\hoge2\hoge2.cpp(43) : error C2664: 'CBullet::Move' : 1 番目の引数を 'std::_Vector_iterator<_Ty,_Alloc>' から '_tBullet *' に変換できません。(新しい機能 ; ヘルプを参照) with [ _Ty=_tBullet, _Alloc=std::allocator<_tBullet> ] この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません。 とエラーになってしまいます。 どうすればエラーを回避できるのでしょうか?
エラーの記述そのまんま。VC6.0ではvectorのイテレータはポインタにそのまま変換されたが 最近ではならん。邪道かもしれんがその場しのぎならMove(&*p);
>>500 解決しました
しかし &*p って 意味的には同じですよね
ポインタは理解しているのですが、深い部分までは理解してなかったのです。
最近はイテレータはポインタとして変換されないんですね
昔勉強した本によると イテレータはポインタの用に動くと明記されていたので
とても困っていました。
細かくはイコールではないのですね
ありがとうございます。勉強にもなりました。
502 :
デフォルトの名無しさん :2007/12/16(日) 12:38:15
503 :
502 :2007/12/16(日) 12:42:32
>>502 protected だからに決まってる。
それはそうと、
Base::operator ==;
こんな宣言通るんだな。 using ってつけないとダメかと思ってた。
>>501 悪いことはいわん。
先頭をアンダーバーではじめるのはやめとけ。
それ以前に typedef struct { ... もやめとけ。
507 :
502 :2007/12/16(日) 12:52:12
>>504 ピンポイントで
public:
Base::operator ==;
宣言しているので問題ないと思ってました.
ちなみに比較演算子ではなくて適当な関数だと
public:
Base::foo;
で派生クラスから呼び出せます.
これはよく使っていた機能なんで,比較演算子でもやってみました.
呼び出しより前にキャストが起こるからダメなのか.
>>501 > しかし &*p って 意味的には同じですよね
違う。
> 最近はイテレータはポインタとして変換されないんですね
単に一部の古い処理系がvector<T>::iteratorをT*でtypedefしてたせいで偶然コンパイルが通っていただけ。
C++がstrong typedefを持っていないのが原因とも言える。
>>502 public派生ではない場合、is a 関係にはならんよ。
つまり、派生型から基底型への暗黙の変換は不可。
d1 == d2 は d1.operator==(d2)の意味だけど、d2をBase型へは
変換できない。
>>507 エラーメッセージにそう書いてあるだろ。
511 :
502 :2007/12/16(日) 12:58:30
>>509 なるほど,is-a の基本を忘れていました.ちなみに
Derived d1,d2;
Base b1;
assert(d1 == b1);
は問題なく通りました.
d1.operator == (b1) だから当然ですね.
>>508 strong typedef は関係ないだろ。実装が普通の typedef 使ってたら同じなんだから。
>>506 たまにCのソース弄るせいか結構typedefしちまうんだが
なんか弊害あったっけ?
>>513 typedef じゃなくて名無し構造体の弊害として、前方宣言が利かない、
コンストラクタ・デストラクタが書けないってのがある。
名無しじゃなくてもクラス名と typedef 名が違うと前方宣言が使いにくい。
>>513 変数名に同じ名前が使えなくなるってのも、あるかな。使わなきゃいいんだけど。
>>508 どの本読んで勉強したんですか?
MSDNとか?
参考までに聞かせて
>>490 >値渡しの引数を受け取った側でいじるってやらない?
引数名が表す意味と内容が合わなくなるからやめろ
って誰かが言ってた希ガス。
>>517 俺もその意見に同意する。後で元の値欲しくなったとき困るから
よっぽど小さい関数でもなけりゃローカル変数にコピーしてから弄る
構造体を宣言する際、たいがい2回以上その型を宣言しないのに、今まで、無意識に、癖で typedefを付けていたんだが、無駄な事だと最近になって分かった C++歴半年の俺
>>481 Exceptional C++ に const int& でのパラメータ私を推奨する記述はなかった
ちなみに、あれは良書
当時、例外安全をあんなに大きく正しく取り扱った本は少なかった
今でも少ないか
古い本なので、今では陳腐化した情報もあるだろうけど
521 :
デフォルトの名無しさん :2007/12/16(日) 16:27:38
アドレス例外を例外で拾いたいんだけどどうしたらいいの?
アドレス例外なんてのはC++には無い。 環境依存で拾えるかもしれないが、環境書いてないしスレ違い。
CPad for Borland C++Compiler って配布中止になったんですか? C++を始めようと思い解説サイトでおすすめ していたので導入しようとおもったんですが
>>522 おk
セグメント違反やアドレス例外が拾えたらラッキーだと思ったんだけど
少なくとも尋常な手段ではそういうOSがらみの例外は拾えないのね。
>>524 signalでSIGSEGVをキャッチすればいけるんじゃね?
527 :
デフォルトの名無しさん :2007/12/16(日) 17:48:03
>>523 公式BBSになんかのってるらしいと聞いた
528 :
デフォルトの名無しさん :2007/12/16(日) 18:18:05
BCC developerが標準環境だろう
529 :
502 :2007/12/16(日) 18:19:37
Eclipse CDT じゃだめ?
ダメでしょ、cygwinとか必要だし
>504 11.3 Access declarations やね。using ができる前のやつなんで deprecated になってる。
533 :
502 :2007/12/16(日) 20:15:42
>>532 げ,ふつうに常用していた.
もう使うのやめよう.
typedef struct って何が悪いん?
535 :
デフォルトの名無しさん :2007/12/17(月) 01:04:16
C++では、typedef なしで struct X {}; とするだけで、void foo(X x); とか書けるからだよ。 まぁクラス定義をtypedefありで書かないことを考えれば当然とも言える。 ところで、typedef class X_ { ... } X; はコンパイル通るんだっけ?w
Cのときに@struct書くのが面倒」だったのを、 せっかく処理系が面倒見てくれてる(struct省略できる)のに わざわざ旧来の書き方をするのは無駄なんじゃね。
538 :
デフォルトの名無しさん :2007/12/17(月) 01:50:56
神経衰弱のプログラムってどうやったらいいですかね?
カード52枚を格納する配列を作って、 ランダムにソートさせて、 取得したカード2枚を比較するロジックを作って、 一致したら配列のカードが格納されていたところを空にして、 カードがなくなるまでゲームを続ければいけるんじゃね?
540 :
デフォルトの名無しさん :2007/12/17(月) 02:12:08
>>539 なんとなく分かったんですが、
一致しなかった場合に裏返すっていうことできませんよね?
違った場合に裏返すってことをしたいんですが・・・
>>540 できるじゃん
最初から裏返しにしておいて、
カードをめくるってアクションのときだけ、
配列にアクセスして、指定されたカードの情報をとって、
それを元にそのカードを表示させる
違ったら、その表示を非表示に変えればいいだけのこと
というか、俺はもう寝る
おやすみ
543 :
デフォルトの名無しさん :2007/12/17(月) 09:10:24
同じ名前のクラスをあるプログラム上に複数実装しなきゃならないとき、ヘッダーでnamespace〜〜ってしていいの? それともヴァージョンが違うだけでほとんど同じクラスだから、一つにまとめたほうがいいんでしょうか?
>>543 なぜ同じ名前にするのかじっくり考える。
>>543 状況による。
1.そもそもなぜ同じ名前のクラスがでてくるのか
2.1.が問題ないなら、片方のバージョンを保存しておく必要があるのか(後で使うことがあるのかなど)
>>544-556 レスさんくすです。
結局そのクラスは機種依存だったので、一つに纏まりました。
しかし、C++って便利ですね。勉強になりました。
548 :
デフォルトの名無しさん :2007/12/17(月) 22:28:59
学生で、今後のためにC++の勉強をしておきたいのですが、 それにあたって、学習に良いと思われる(書き方がやアルゴリズム良い) オープンソースのプログラムが何かあれば教えていただきたいです。 今はJavaを主に使っているので、オブジェクト指向も理解してますし、 Cも昔やったのでポインタも問題ないです。 本でC++の文法も少しかじり、あとは生きたコードを見たいのですが、 よいものはありますでしょうか?
gcc
糞汚ったないソースコードにも触れておいたほうがいいぜ オープンソースと呼んでいいか分からないが、ソフトバンク・パブリッシングのZIP/LHA本の ソースコードはキレイだった。
551 :
デフォルトの名無しさん :2007/12/17(月) 22:58:55
void foo(std::size_t len) { char a[len]; のようなコードは、C++の言語規格に準拠していますか? C99だと問題ないらしいですが、C++は?
だめ
そんなんできようがないな
>>548 boost ならお手本にしてもいいと思う
C++の最先端の1つでもある
でも初心者には厳しすぎるか
でも、array なんかはシンプルなのですぐに読める
あと、rational も簡単
変態的なものもあるが簡単なものもあるので、簡単なのから読んでいけば大丈夫だと思う
いちおう世界中で使われてる生きたライブラリ
555 :
デフォルトの名無しさん :2007/12/17(月) 23:05:09
ではC++0xでは? g++はいまでも通るんだけど。
関数に必要なスタックサイズがわかんねー気がするんだが どうやって解決してるんだろ…
C99なコード書いて、逆アセンブルしてみればわかるよ。 または昔のCやC++でalloca使ってもいい。
558 :
557 :2007/12/17(月) 23:12:54
>>556 subl $48, %esp
みたいな、即値によるスタックポインタ移動が
movl %eax, 引数で渡された数
subl %eax, %esp
とかになるだけ。
標準ではC++03のC部分はC99ではないはず。 C++0xではC99が取り込まれる予定とか。
ああなるほど しかし引数が原因でスタックオーバーフローで落ちるのはなんかデバッグが嫌だな
562 :
デフォルトの名無しさん :2007/12/17(月) 23:21:50
>>559 VLAは0xでも採り入れられない予定だとおもった
こういう実行時に与えられる値でサイズが変化したりするようなものは あんまり取り入れて欲しくないなあ。 C++はどこまでも静的であって欲しい
自分はVLA欲しい派だな 最大値で確保しておく必要がなくなるから無駄が省けてる感がいい
欲しいけど気持ち悪くて使えない派
自分ら、C#はやらんのか?
allocaやasprintfで十分だよ派
>>567 イラネ。erlangならやるかも。
C++は古い、次世代C#かJavaかって言うが あれに全員が乗り換える未来は想像したくない。 Dなら良い
なんでC++はCの良いところは受け継がずCの悪いところだけ受け継いでしまったのか。 なんでC++はコンパイラの実装のしやすさは放置してしまったのか。 なんで?
親の遺伝子の悪いところだけ受け継いでしまった感じの質問者だね。
誰がハゲやねん!
D&Eでも読め
>>568 allocaはもうMSにも捨てられてるよ
安全でないというより遅いから
576 :
デフォルトの名無しさん :2007/12/18(火) 00:29:39
>>575 何と比べて遅いんだ?
マシン語命令1-2個で実装される関数もどきが遅くなるはずないんだが。
スタック溢れの判定入れても10命令いかないだろう。
>>570 Cの良いところってなんだ?
悪いところは結構思いつくが
流れぶった切って質問です。 void* から安全にキャストする方法って存在します? void*だとdynamic_castは効かないし……static_castはミスると未定義だし……
581 :
デフォルトの名無しさん :2007/12/18(火) 00:52:09
>>580 ない。void*の指し先の先頭1バイトに適当なタグを書いておくくらいか?気休めだが。
boostのanyを使って、void*をエミュレートするといい。
582 :
デフォルトの名無しさん :2007/12/18(火) 00:58:24
void*で失敗ってどんなとき? アドレスってどれでも32bit何じゃないの?
>>582 void*がstruct Xを指しているのに、誤ってstruct Y*にキャストして使ってしまったらまずかろうよ。
584 :
デフォルトの名無しさん :2007/12/18(火) 01:04:29
>>583 void *p; として、(int) pとキャストしても、指すアドレスは変化しないと思うんだけど
コンパイル時に型として通るかどうかだけ何じゃないの?
586 :
デフォルトの名無しさん :2007/12/18(火) 01:09:11
プログラマが何が入っているかわからなくなってしまう場合があるって言うことか それならコード書いてる時点で良く確認すればよい
>>584 アドレスは変わらないが、XオブジェクトをYオブジェクトとして
アクセスしてしまう。
>>586 その理屈だとdynamic_castもassertもいらないな。
コンパイラの警告もいらないし、デバッガも不要だし、OSのメモリ保護ももしかしたらいらないかもしれないな。
・・・お前限定で。
>>584 お前は根本的に問題が分かっていない。
>>580 はむしろ方が違う場合、実行時に例外でも何でもいいから知らせてくれってタイプだ。
やはり
>>581 しかないな。
ただし1バイトだと、アラインメントの問題があるから、
たとえば4バイトとか、環境に応じて適切にしたほうがいい。
Boost.Anyを使うならば、なお良い。
>>586 MFCのうんこコールバックとか使ったこと無いのか?MFCに限らずコールバック関係は
void*が結構使われたりする。
591 :
デフォルトの名無しさん :2007/12/18(火) 01:16:28
592 :
デフォルトの名無しさん :2007/12/18(火) 01:17:27
違うことが予測できているなら、動作がおかしかったらそこを疑えばいいじゃないか? なんの疑いもしないバグは探すのが困難
>>592 実行環境が自動で疑ってくれるほうが楽だとは思わんかね?
594 :
580 :2007/12/18(火) 01:50:40
サ〜ンクス >581 やっぱり無いか…… 実はboost::anyでこういうのをやろうとしたんだけど上手くいかなかったんで、 なんか回避策は無いかな、と探していたところでした…… class A {}; class AA : public A{}; int main() { AA aa; boost::any testAA(&aa); if (boost::any_cast<A*>(&testAA)) { std::cout << "testAA* == A*" << std::endl; } } anyからアップキャストしたポインタ or 参照を取り出したい、というのが希望です。 anyの実装見る限りは出来そうに無いのですが……
Anyはtypeid()を見ているからなぁ。難しいな。 boostスレで効いたら?
596 :
デフォルトの名無しさん :2007/12/18(火) 02:00:02
実行時型情報で、ポインタと同時に種類記録しておけ アドレスと型をもつクラスでも作れ
C++が機能を取捨選択するとはらしくないな。もう手当たりしだいに なんでもかんでも入れちゃうはしたない言語なんだろ?C++は。
残念ながら的外れ
x86専用とかJavaVM、.NET用ならいいが、 多くのCPUでコンパイル可能な言語なんて今さら作れないんじゃないかな。 だからC/C++は高級アセンブラとしてずっと残るように思う。
GCJはC/C++を高級アセンブラとして使う高級コンパイラってところか
>>594 boost::any testAA(static_cast<A*>(&aa));
という手もあるが、今度はAA*として取り出せなくなる罠。
C++ は最優先事項が C との完全互換らしい。 新機能の搭載も、まずは C との互換が大前提。 逆に、搭載されていないものは C のシンタックスを破壊するものらしい。
>>602 の意見に補足すると、C++のコードは一旦Cのコードに変換される
C++の前進が、C with ClassesとBjarne Stroustrupに命名された由縁である
Cとの、というか、過去に書かれたコードの互換性、だと思うが。 仕様変更で古いコードがコンパイル不能にならないように、 あるいは、なったとしてもほとんど無視できる程度になるように配慮している。 以前はCに変換してたけど、今は直接オブジェクト・コードを吐いてるはず。実装依存かな。
禿が自分でcfontつくったわけだから、603の言い方は妙な感じがする。
現行の C++ 仕様でも C へのトランスレータで実現できるのかな?
チューリング完全だからそりゃあできるよ 特に効率も落ちないかもしれないし
HaskellでさえCへのトランスレータでできるよ
C++のテンプレートでhaskellの文法を作るとか
cfront は例外が実装できなくて、開発が止まったと 読んだ記憶がある。
SetWindowPosを使い、既に最前面化されている場合は解除、そうでない場合は最前面化という動作を させたいのですが可能でしょうか? 内部で自分が最前面化したウィンドウを覚えておくのではなく、 最前面化されているかどうかを取得できればいいのですが。
それがC++とどういう関係があるのか。
それでもC++なら・・・C++ならきっと何とかしてくれる
Win32APIは全部Cだな
単なるインターフェースにCも糞もあるか
616 :
611 :2007/12/19(水) 19:47:59
板違いのようで申し訳ない… Win32APIいってきます
VS2005、MFCです 配列を初期化する場合、コンストラクタの初期化子では初期化できないのでしょうか? 初期化したい内容(値)が決まっていればいいのですが、配列の生成時には決まっていないので とりあえず、配列の個数だけ""で初期化したいのですが? 具体的には buff[] = {"","",""}; このような事を、コンストラクタの初期化子で行いたいのですが
出来ない
>>618 617です
そうですか、あきらめました
○○○::□□□ というのは、 クラス::メソッド と思っていいの?
そ れ は 他 人 に 相 談 す る 内 容 な の か
メソッドってなんですか
グーグルにアク禁でも喰らってるのか?
>>620 そうなのか、どうやって書いたらええの?
教えてくれろ
627 :
621 :2007/12/19(水) 23:59:49
>>625 私へのレスですか?久々に受けたww
いえ、ちょっと覚えるのに楽をしようと思って・・・
628 :
621 :2007/12/20(木) 00:01:09
C++を10行ぐらいでまとめて説明してください。
629 :
624 :2007/12/20(木) 00:01:18
いや、俺へのレスだろw C++にはメソッドなんてものはないのだ
630 :
621 :2007/12/20(木) 00:08:07
>>623 名前空間::クラス::メソッド
って感じなんでしょうか?それを
public:
やら
private:
の下に書くと、中のメンバを隠したりできて・・・合ってます?
他にCとの重要な違いとかあったら教えてください。
>>629 マジっすか!
動作がメソッドだ。ってC++の入門書にまことしやかに書いてあるけどなぁ。。
厳密に言うと、「 」と呼ぶ、みたいなこと?
>>628 10行程度で
意味のある説明が
もらえると
考えてる奴には
とうてい
習得不可能な
言語。
あきらめろ。
632 :
621 :2007/12/20(木) 00:13:17
10行で説明できる範囲でいいので!お願いします!
私はC++の神髄を発見したが、 それを記すにはこの余白は あまりにも狭すぎる
C++ = C89 + some improvements + // comments + clases + template meta programming + STL あと3行は任せた
>>630 >他にCとの重要な違いとかあったら教えてください。
入門書を読んでいるなら、Cとの違いとか書いてないの?
Cと比較して説明していない本だとしても、Cを理解しているなら自分で違いが分かるだろ。
この手の掲示板は、やる気や向上心ののある人に対しては教えたがりの人があれこれ構ってくれるが、
楽したい、自分で調べる気はない、なんて奴は相手にされない。
いいから、まずお前が持ってる入門書とやらをちゃんと嫁。
それで分からないところがあれば聞きに来い。
>動作がメソッドだ。ってC++の入門書にまことしやかに書いてあるけどなぁ。
オブジェクト指向の言語で一般的にメソッドと呼ばれているものは、C++では関数だ。
C++の規格としては、メソッドと呼ばれるものは存在しない。
C++それ自体の規格が沈黙していたとしても、 C++が継承・包含しているもののほうに「メソッド」は 定義されていると見た方が良い。
638 :
621 :2007/12/20(木) 00:31:54
どう頑張っても短期には習得できないことがよく分かりました・・・。
>>635 Cとの違いというか、C++だけの大きな特徴というか・・・
Cを覚えるのだけで疲弊しきってしまってC++を覚えるパワーが・・・・
パワーを蓄えてからまた来ます。失礼しました。
>>639 そう、パクリ。
でもいろんな面でほどほどにオリジナル (C)と似ているところもあったから、
付いてくる人間がいた。
ださくても、下手な言語よりはよっぽどましに使える。
>>634 +ハゲ
+ヒゲ
さいごの一行を誰か頼む。
おまいら、つまらんよ スレの情報密度が下がる。自重汁
>>643 自分のレスの情報量と質はどのくらいに見積もってる?
>>630 オブジェクト指向言語でメソッドと呼ばれるものは、
C++では「メンバ関数」って言われてる。
麺バカンス・・・それは小麦粉と長期休暇を組み合わせた、全く新しい格闘技である
>>646 …風雲黙示録を思いだしたよ。懐かしいなぁ。
648 :
谷 :2007/12/20(木) 13:26:20
よくぞ生き残った わが精鋭たちよ!
海外でも"Takeshi's Castle"ってタイトルで結構有名なんだよな。
650 :
デフォルトの名無しさん :2007/12/23(日) 17:52:39
typedef std::vector<int> myvec; のように関数テンプレートについても短いエイリアスを付ける方法はないでしょうか? typedef並にスマートな方法を教えてください。
651 :
デフォルトの名無しさん :2007/12/23(日) 17:58:48
>>650 関数テンプレートの呼び出しは、普通はコンパイラによる型の推測(deduction)があるから
typedef的なものは不要なわけで、
>>650 がどう困っているのかその特殊ケースを晒さない
ことには答えにくい。
652 :
650 :2007/12/23(日) 18:03:29
>>651 template <bool b, typename T> T func(T a){} これを
typedef func<true, char> myalias; こんな感じにしたいです。
>>652 (1) いまはそれをどう呼んでいるんだ?
(2) func()は特殊化する予定?しない予定?
654 :
650 :2007/12/23(日) 18:10:18
>>653 (1) char r = func<true, char>('a'); こんな感じです。
(2) 特殊化する予定は有りません。特殊化するかどうかによって事情が変わってきます?
template<typename T> inline T myalias(T a){ return func<true, char>(a); }
inline char myalias(char a) { return func<true,>(a); }
657 :
デフォルトの名無しさん :2007/12/23(日) 18:16:37
>>654 char r = func<true>('a'); と、Tは省略できる。それで我慢したらどうよ。
>>655-657 回答ありがとうございます。やはりtypedefのようにはいかないみたいですね。
ラッパー関数を作るか、#define の使用も検討してみます。
何故defineを検討するのか理解に苦しむ
660 :
デフォルトの名無しさん :2007/12/23(日) 19:27:06
関数が引数を取るとき、プロトタイプ宣言はどうすればいいんですか? void JicharaMove(int movable){ } のようなときなんですけれど…
>>660 よくわからんな。そのままだろ。
自分でどうやって、期待した結果と何が違ったのか書いてみれ。
662 :
デフォルトの名無しさん :2007/12/23(日) 19:30:35
void JicharaMove(); とヘッダーでプロトタイプ宣言しているのですが、 Error: 外部シンボル 'JicharaMove()' が未解決 とでてしまうのです
intは何処いったんだ
664 :
デフォルトの名無しさん :2007/12/23(日) 19:56:43
intをどうすればいいかが…
void JicharaMove(int);
おお!ありがとうございます!
667 :
デフォルトの名無しさん :2007/12/23(日) 23:58:42
C言語かC++か分からないのですが、こんな↓構文に出くわしましたorz for ( counter=counter1=1 ; ; counter++) { .... } 何者ですか、これは・・・・Orz ここで何が起こってるんですか・・・
ループ条件が省略されてるだけ。 常に真として扱われる。
最初の部分なら単に counter = (counter1 = 1) ってだけだから
670 :
デフォルトの名無しさん :2007/12/24(月) 00:11:35
>>668 for ( int counter=1,int counter1=1 ; counter=1,counter1=1 ; counter++) {
....
}
てな意味でしょうか??(あてずっぽうで書いてます)
むしろこう。 for ( counter=counter1=1 ; true; counter++)
672 :
デフォルトの名無しさん :2007/12/24(月) 00:14:49
>>671 すみません、これ↓
counter=counter1=1
が既に分からないです。
counter にも、counter1 にも 1 を代入してるってことでしょうか?
これは C++?
>>672 int counter1 = 1:
int counter = counter1;
をまとめたもの。
代入文は代入された値として評価されるから、
printf( "%d\n", ( i = 5 ) );
だと 5 が表示される。
674 :
デフォルトの名無しさん :2007/12/24(月) 00:25:18
>>673 あ、なるほど・・
最初に counter1 に 1 が入って、その counter1 を counter に代入して、、って感じですね。
for ( counter=counter1=1 ; true; counter++)
だと、counter の値は回を重ねるごとにどう変化していき、いつ、この for文は終わるんでしょうか?
675 :
デフォルトの名無しさん :2007/12/24(月) 00:30:08
実行したら無限ループ突入しましたorz
そりゃそうだw
677 :
デフォルトの名無しさん :2007/12/24(月) 00:39:21
ステップ実行したら分かりました。 counter1 はずっと 1 のままで、counter だけ永遠に 1 足されて表示 されるんですね。どうもありがとうございました。
>667 ついでに言うと、counterとcounter1は前に宣言されているのを流用している。 ……こりゃあ、あんまり良いコードじゃないな。 コードの意図が判らんと何とも言えんけど、 - counterとcounter1はループの外で代入した方がいい。 - counterのインクリメントはループのブロックに取り込んだ方が良い。 だとオモ
679 :
デフォルトの名無しさん :2007/12/24(月) 03:46:56
C++の問題で、 ・正の整数値を読み込みその桁数を出力する ・1からnまでの和をfor文で求める この2つがわかりません;;教えてください;;
>>679 下、動作未確認。
#include<iostream>
int main(void){
int n;
std::cin >> n;
int sum = 0;
for(int i = 1; i <= n; i++){
sum+=i;
}
std::cout<<sum;
return 0;
}
>>679 上、動作未確認。
#include<iostream>
int main(void){
int n;
std::cin >> n;
int digit = 0;
for(;n>0;n/=10){
digit++;
}
std::cout<<digit;
return 0;
}
>>679 unsigned nofdigit(unsigned foo) {return unsigned(log(double(foo)) / log(10.)) + 1;}
template<int N>sum1() {return (N + 1) * N / 2;}
つーか、スレ違い。宿題なら宿題スレへ、そうでないなら初心者スレへ。
>>679 下
int sum( int n ) {
for(;n;) {
return n + sum( n-1 );
}
return 0;
}
すみません、共変の戻り値について教えて下さい。 struct A {}; struct AA : public A { void test() { std::cout << "Test " << std::endl; }; }; struct Base { virtual A& data() { static A a; return a; }; }; struct Derived : public Base { virtual AA& data() { static AA aa; return aa; }; }; int main() { Derived d; d.data().test(); Base* pb(&d); //pb->data().test(); // コンパイルエラー static_cast<Derived*>(pb)->data().test(); }; ということで、多態して使おうとするとエラーになってしまいます。 こういう使い方はNGなのでしょうか?
Aにvirtual void test()持たせればいいんでないの
>>684 pb->data()が返す型は、あくまでBase::dataで宣言されたA&。
だからAAのメンバは使えない。
void JicharaMove(int);
最初のインスタンスが生成される前に (つまり最初にコンストラクタが呼び出される前に) 静的変数の初期化をしたいよ・・・
689 :
デフォルトの名無しさん :2007/12/24(月) 20:37:44
RTTIって言語仕様なのかライブラリなのかなんか中間的だよね. typeid は演算子なのに,その返り値のクラスは #include <typeinfo> で定義されてるんですよね. まぁそれって sizeof 演算子の戻り値が size_t なのと 似ているのかもしれないけど,それもなんか気持ち悪い気が するのは俺だけ?
>>688 現状でもその要件は満たしているようだが、何が不満なのかね?
691 :
デフォルトの名無しさん :2007/12/24(月) 20:48:08
C# の静的コンストラクタ Java の静的初期化子のようなものを想定していました
悪いが C# や Java のそれらを知らない奴にもわかるように説明してくれないか?
>>691 (1)シングルトンパターンを使う
(2)Schwarzカウンタを使う
まあ、そもそも単純な初期化なら単にソースコード上で代入すればいいわけだが
*stringデータ内の"<br>"を探して'\n'に置き換える 誰か教えてお願い
boostのソース見てたら、 struct hoge {}; struct hogehoge : virtual hoge {}; ってな書き方してあるんだけど、どういう意味? 継承するときに使えるアクセス指定子は、 public, protected, private のみだと認識してたんだが
699 :
697 :2007/12/24(月) 23:38:51
>>698 なるほど!!
初めて知ったぜ。
サンクス!
下記のプログラムを実行したらメモリリーク起こしますか? (main等は省略) 01 class Test{ 02 int *p; 03 unsigned int m; 04 public: 05 Test(unsigned int mm){ 06 int (*pp)=new int[mm]; //配列ppを生成 07 p=pp; 08 m=mm; 09 for(unsigned int i=0;i<m;i++)p[i]=0; //テキトーに値を代入 10 }; 11 ~Test(void){ 12 delete[]p; //配列ppを削除(できてるのか心配) 13 }; 14 }x(10);
>>700 その一部分を見た限りではメモリリークはしないと思うけど?
>>700 コピコンと代入演算子がないのでメモリリークする。
コピーも代入もしてないが
省略してるところでしてたら メモリリーク+二重解放だな。 してなければメモリリークしないが。
普通は vector 使うからね。
>>701-706 ども、ありがとございます。
自分で考えたのでこんなソースは見ないと思う。
vectorは勉強してないからわからないんだ。
>>707 安心しろ。>700みたいな心配する暇でvectorくらい使えるようになるから。
わたくしC++で一行も書いたことないのですが STLとかBoostとかの仕様をパッとみると、 スクリプトのようにお手軽でしかも美しいコードが ネイティブコードでコンパイルできちゃうという 夢のような話に思えてくるんですが、 実際のところどうなんでしょうか。
間違ったコードを書いたその瞬間になる前までは、そう思っていていい。 気が付くと、これなんかのスクリプティング言語だろ、と思いたくなるコードになっていることはある。 話は逸れるけど、VC++で#importを使うときもVBS、JSみたいなノリだなあと思う。
まあネイティブじゃない、って意味ではx86機械語もCPUの内部で 「評価」されて順番が変わったり無くなったりするわけで。 つまりあらゆる言語はスクリプトなんだよ
なんだってー!!ΩΩΩ
C++のtemplateの特殊化について質問です。 「基底クラスBaseから派生するクラス全て」という条件で特殊化するにはどうしたら良いでしょうか。 今は派生するクラス全てに対して一つ一つ特殊化しているので一般化したいのです。 サンプル #include <iostream> using namespace std; class Base { }; class Sub: public Base { }; template<typename T> void test(T* tp) { cout << "T" << endl; } template<> void test(Base* bp) { cout << "Base" << endl; } int main(int argc, char* argv[]) { test(new Base());// Base test(new Sub());// T (ここをBaseにしたい) return 0; }
>>713 そういう特殊化はできないような覚えがあるんだけど、
> void test(Base* bp) {
こいつをテンプレートにしなけりゃやりたいことはできるんじゃね?
>>713 boost::mplとboost::type_tritsを使うと簡潔
#include <boost/type_traits/is_base_of.hpp>
#include <boost/mpl/if.hpp>
#include <iostream>
struct Base {};
struct Sub:public Base{};
struct Another{};
struct tag_specialized{};
template <typename T> void test_() {
std::cout << "T" << std::endl;
}
template <> void test_<tag_specialized>() {
std::cout << "Base" << std::endl;
}
template <typename T> void test(T*) {
test_< typename boost::mpl::if_< boost::is_base_of<Base,T>, tag_specialized, T >::type >();
}
int main() {
test(new Base);
test(new Sub);
test(new Another);
}
>>713 すぐに加速しちゃうのは嫌いなので、
>>714 さんを参考に地道に書いてみました。
#include <iostream>
using namespace std;
struct Another { void foo() { cout << "Another::foo invoked." << endl; } };
struct Base { virtual void bar() { cout << "Base::bar invoked." << endl; } };
struct Sub: Base { void bar() { cout << "Sub::bar invoked." << endl; } };
template <typename Lhs, typename Rhs> struct IsBaseOf {
struct True {};
struct False { int i; };
static const bool result = sizeof(testAssignable(static_cast<Rhs*>(0))) == sizeof(True);
static True testAssignable(Lhs*);
static False testAssignable(...);
};
template <bool Cond, typename Then, typename Else> struct If;
template <typename Then, typename Else> struct If<true, Then, Else> { typedef Then result; };
template <typename Then, typename Else> struct If<false, Then, Else> { typedef Else result; };
template <typename T> void test_(T* p) { p->foo(); }
template<> void test_<Base>(Base* p) { p->bar(); }
template <typename T> void test(T* p) { test_< typename If<IsBaseOf<Base, T>::result, Base, T>::result >(p); }
int main() {
test(new Base());
test(new Sub());
test(new Another());
}
717 :
713 :2007/12/25(火) 23:15:11
>>714-716 ありがとうございます。
とても参考になりました。
複雑なtemplateは書いたことがなかったのですがこれを期に学習します。
>>711 X86においてネイティブは存在しない(全てInterpretative)という意味では概ね同意する。
質問です。 左右が反転しているだけで他は同じ処理をする木構造のコードを、 今までは関数へのポインタを使って一つにまとめていました。 get_right( p ){ return p ? p->r : NULL; } /* 右枝 */ get_left( p ){ return p ? p->l : NULL; } /* 左枝 */ hogehoge( p, get_right, get_left ); /* 左側 */ hogehoge( p, get_left, get_right ); /* 右側 */ hogehoge( p, right, left ) { return left( right( p ) ); } このコードの left( right( p ) ); という内から外へ読まなければならない部分が個人的には嫌いでした。 最近C++を習い始めて、テンプレートや演算子定義などを使えば p->right()->left(); のように左から右に読めるコードが書けるのではないかと思うようになりました。 ・左から右に読めるようにする。 旧 get_right()/get_left() を CNode のメンバ関数にした。 ・関数内の左右の意味を反転させる。 関数テンプレートとファンクタで出来た。 というところまでは試してみたのですが、最後に2つを1つにまとめるところで苦労しています。 どのような解決方法があるでしょうか。 どうぞよろしくお願いします。
関数は諦めて引数で分ける。 単純に p->get(right)->get(left); とすればできる。 別にCでも書ける。 p->get(p, right)->get(p, left); ほら。
C++なら、普通にメンバ関数ポインタでできると思うけどな typedef Node* (Node::*getNode)(); Node* hogehoge(Node* n, getNode left, getNode right){ return n->*left->*right; } まあleftとrightの2種類しかないなら、定数で指定でもさせた方が楽だとは思うけど
間違えた typedef Node* (Node::*getNode)(); Node* hogehoge(Node* n, getNode left, getNode right){ return ((n->*left)()->*right)(); } 確かに括弧が多くて嫌だなこれ
ちなみにC++だと参照を返すことになると思うから代入も出来るな。 Cだと、、、たぶん綺麗には不可能だな。 C++: Node *&get(bool left){return left ? m_l: m_r;} p->get(1)->get(0) = q->get(1); // O.K.!! p->left->right = q->left; と同じ! C: node_t *get(node_t *p, bool bleft){return bleft ? p->right: p->right;} p->get(p,1)->get(p,0) = q->get(q,1); /* p->left->right = q->left; の意味だができない、、、 */
最初の版からNULLチェックが消えてるな。 Null Object で解決できそうだが。
オペレーターオーバーロードについて4つほど質問があります。 どうにも説明しにくいので、(1)〜(3)については次レスに具体的なコードを載せておきます。 コンパイラはbccです。 (1) template <int N> void operator ()(int x); 上記のような引数による推論ができないタイプのテンプレートオペレータの場合、 どのようにテンプレート引数を指定すればいいのでしょうか。 とりあえずは(3)に示すようなやり方でできるにはできたのですが、もっと自然な記法は無いでしょうか。 (2) (1)に関して、とりあえず (object.*(&Class::operator()<5>))(4);のように呼び出したら、 "このコンテキストではオーバーロードの意味が曖昧"と怒られました どのような状況と曖昧でしょうか? (3) 最終的にキャストすることでテンプレート引数を指定しつつ呼び出すことはできました。 typedef void (Class::&CP)(int); (object.*(CP)(&Class::operator()<5>))(4); が、どういうわけかこれを続けて呼び出すと前のテンプレート引数を引きずってしまいます。 (分かりにくいと思うのでコードを見てください) 何故でしょうか。 (4) メンバ関数ポインタを宣言する際、 void (Class::*p)(int);のようにやりますが、()よりも::の方が優先順位が高いのだから、 void Class::(*p)(int);とやっても大丈夫かと思ったのですが、ダメでした。 何故でしょうか?
726 :
725 :2007/12/26(水) 18:43:28
#include <iostream> using namespace std; class Foo{ public: template <int N> void func(int n){ cout << N+n << endl; } template <int N> void operator()(int n){ cout << N*n << endl; } }; typedef void (Foo::*FP)(int); int main(){ Foo f; f.func<6>(8); //14 f.func<9>(2); //11 // f<7>(5); ERROR // f(5)<7>; ERROR "一致するものが見つからない" // f(<7>5); ERROR "構文エラー" // (f.*((&Foo::operator()<3>)))(9); ERROR "曖昧" (f.*((FP)(&Foo::operator()<3>)))(9); //27 (f.*((FP)(&Foo::operator()<7>)))(12); //36(84と出て欲しい) return 0; } お願いします
727 :
725 :2007/12/26(水) 18:45:53
すいません、(4)は勘違いでした。 ::よりも()の方が優先順位が上ですね
>>725 f.operator()<6>(8);
とかじゃ嫌?
729 :
725 :2007/12/26(水) 19:10:28
>>728 あ、そんなやり方できたんですね……
何でわざわざメンバ関数ポインタにしたりしてたんだろorz
ありがとうございます。
>>725 の(2)と(3)については引き続きお願いします。
730 :
725 :2007/12/26(水) 19:28:28
すいません、少し質問を変えます
>>726 に示したような状況特有の問題かと思ったんですが、もうちょっと簡単な例でも起こりました。
#include <iostream>
using namespace std;
class Foo{
public:
template <int N> void func(int n){
cout << N << ',' << n << endl;
}
template <int N> void operator()(int n){
cout << N << "." << n << endl;
}
};
typedef void (Foo::*FP)(int);
int main(){
Foo f;
f.func<6>(8); //6,8
f.func<9>(2); //9,2
f.operator()<2>(9); //2.9
f.operator()<10>(-1); //2.-1
f.operator()<100>(3); //2.3
return 0;
}
このように、オペレータに限り最初のテンプレートを引きずってしまいます。
bccのバグでしょうか?
VC8,gcc3.4なら正常に動作した
VC6にも似たようなバグあったな。
733 :
725 :2007/12/26(水) 20:31:52
じゃあこれもバグか……コメントが実行結果で #include <iostream> #include <vector> using namespace std; template <template <class> class T> class Foo{ public: template <class T> void func(const T &x){ std::cout << typeid(T).name() << std::endl; } }; template <class> class Hoge{}; int main(){ Foo<vector> f; //int f.func(1); //int f.func(2.8); //int f.func<double>((double)4.889); //int Foo<Hoge> f2; f2.func(1); //int f2.func(2.8); //double f2.func<double>((double)4.889); //double return 0; } 何故か自作クラスではOK 他にdeque,list,stack等で確認
734 :
725 :2007/12/26(水) 20:33:17
あ、funcのとこでTが被ってるせいかと思ったけどUにしても同じでした
template template parameterっすか・・・ それでもgcc3.4とvc8ではちゃんとにi,d,d,i,d,dになっとりました 多分にバグですね
VC6とBCC5.5とgcc2.9は、もはやC89コンパイラ とでも思ってたほうがいいんでないの。
>725 の (2) は解決したの?
bccのテンプレート実装は古いから結構なバグ持ちだと思うね。
739 :
725 :2007/12/27(木) 01:51:20
C++を習い始めたばかりなのですが本によってデフォルトのコンストラクタやデストラクタの宣言が微妙に違うようです。 古いCでは proc() と proc(void) とでは意味が違ったのですが、C++では同じ意味なのでしょうか? また、皆さんは実際に自分では何れのスタイルで書いていますか? style A: Class(); ~Class(); style B: Class(void); ~Class(); style C: Class(); ~Class(void); style D: Class(void); ~Class(void);
>>740 C++ では同じ。だから (void) は面倒なだけで書かないほうが多い。
最新の C でも () は (...) と同じだから (void) と書かないといけない。
同じ意味の2つを混ぜるのはありえないので style A がいい。
俺は (void) 派。
昔、デストラクタにvoidでかいたらエラーになったので、空にしている。今もそうなのかな?
質問です。 dynamic_castがよく分かりません。 dynamic_castは実行時に型を調べて変換できるときだけ変換する物、と思っていたのですが、 型を覚えているならvoid*型からだって変換できるはずじゃありませんか? 何故できないんでしょうか。 #include <iostream> class Base {public:virtual ~Base(){}}; class Derived : public Base {}; class Foo : public Base {}; int main(){ Base *p[2] = {new Derived, new Foo}; for(int i=0; i<2; ++i){ if(dynamic_cast<Derived*>(p[i]) == NULL)std::cout << i <<":FAILED\n"; else std::cout << i <<":SUCCEEDED\n"; } void *q = new Derived; // ↓ERROR 'void' 型は仮想関数をもつクラスとして定義されていない // if(dynamic_cast<Derived*>(q) == NULL)std::cout << "void*:FAILED\n"; // else std::cout << "void*:SUCCEEDED\n"; return 0; } dynamic_castは仮想関数を含む物にしか使えない仕様だから、と言われればそれまでなんですが、 型を覚えていることができるなら、このようなvoid*型からのキャストを安全に行うキャストが存在しうると思うんですが、どうなんでしょうか。 それともそもそも「型を覚えている」わけじゃないんでしょうか?
実行時の型の情報は仮想関数テーブルに格納されるので、仮想関数テーブルがないと型を見れない 変換元の型が仮想関数を持つ場合は、仮想関数テーブルの引き方がわかるので大丈夫だが、 void*では仮想関数テーブルがあるのかないのかはっきりしない もし、本当はない型(例えばint)なのに、あると仮定してアクセスすると、アクセス違反で落ちるかもしれん そのvoid*がBase*だとわかってるなら dynamic_cast<Derived*>(static_cast<Base*>(q)) とすればいいだろうけど それすらも不明な状況では無理
bccで以下のコードが通らないんですが、何故でしょうか……。 #include <iostream> #include <typeinfo> int main(){ int x; const type_info& info = typeid(x); std::cout << info.name() << std::endl; return 0; } >エラー E2304 test.c 6: <定数> 変数 'type_info' には初期化が必要(関数 main() ) お願いします。
std::type_info かな?
>>746 なるほど、仮想関数テーブルが型情報を調べるキーになるわけですね……ありがとうございます。
ということは
>>745 みたいな感じでvoid*を通してあらゆるポインタを画一的に扱うには、
typeidを保持しておくvoid*ラッパーでも作ればいいんでしょうか……。
ということで誰か
>>747 もお願いします。
>>748 それだ! できました、ありがとうございます!
こんな簡単なことで悩んでたとは……orz
bccで以下のコメントアウト部分が通らないんですが、特殊化時に戻り値を変えることはできないんでしょうか?
#include <iostream>
struct Hoge{};
struct Foo{
template <typename T> T print();
};
template <typename T> T Foo::print(){
std::cout << "print function." << std::endl;return T();
}
//↓ERROR 'print<Hoge>()' は 'Foo' のメンバーではない
//template <> int Foo::print<Hoge>(){
// std::cout << "print function. parameter is Hoge. return int." << std::endl;
// return 1;
//}
template <> Hoge Foo::print<Hoge>(){
std::cout << "print function. parameter is Hoge." << std::endl;
return Hoge();
}
int main(){
Foo f;
f.print<int>();
f.print<Hoge>();
return 0;
}
>>751 調べてみます。
ありがとうございます。
725=752かな?どっちでもいいけど なんでもかんでも関数テンプレートでする必要はないんだよ? オーバーロードなどと使い分けろ boost::typeみたいな型を使ってオーバーロードすればやりたいことはできる。 struct Foo{ template <typename T> T print(boost::type<T>); int print(boost::type<Hoge>); }; template <typename T> T Foo::print(boost::type<T>){ (略) } int Foo::print(boost::type<Hoge>){ (略) } int main(){ Foo f; f.print(boost::type<int>()); f.print(boost::type<Hoge>()); return 0; } 戻り値の型をtypename boost::mpl::if_<boost::is_same<T, Hoge>, int, T>::type見たいにすれば特殊化でも戻り値の型を変えられたっけ? 試してないけど
>>752 template <typename T> T print();
って宣言されてんだから、どう考えても
(T=intの場合) int print<int>()
か
(T=Hogeの場合) Hoge print<Hoge>()
にしかならない
もう1個テンプレートクラスかませて
template <typename T> PrintReturn<T>::type print();
として
template<T> class PrintReturn { public: typedef T type; };
template<> class PrintReturn<Hoge> { public: typedef int type; };
とすればいいんじゃないかな
そしたら
(T=intの場合) PrintReturn<int>::type print<int>() → int print<int>()
(T=Hogeの場合) PrintReturn<Hoge>::type print<Hoge>() → int print<Hoge>()
になると思う
>>753 そうです、725=752です。
とにかく特殊化では戻り値の型は変えられないってことですね?
boostは全くわからないんですが、ぼちぼち手をつけてみようと思います。
ありがとうございます。
>>754 おお、そんなテクニックが……本当に面白いですねテンプレートは。
ありがとうございます、参考になります。
ついでに質問なんですが、
>>752 とは違い引数から推論可能なタイプの関数テンプレートで、
ある型について特別バージョンを作りたい時に特殊化を用いるのとオーバーロードを用いることの違いは、
戻り値の型を変えられる、ということ以外には何があるでしょうか?
テンプレート関数は、実体化されない限り実体が存在しない。
>>755 ・メンバ関数テンプレートの特殊化はクラス定義内に書けない(ただしVC++では独自仕様でできる)
・関数ポインタを取得する時
たとえば
template<typename T> void func(T);
があってfunc<Hoge>を特殊化した場合は&func<Hoge>としたときに、特殊化版のアドレスが取れる。
一方オーバーロードの場合は常にテンプレート版のアドレスが取れる。
オーバーロード版のアドレスをとりたい場合はstatic_cast<void(*)(Hoge)>(&func)する。
とあるインターフェイスなクラスを継承した派生クラスA/B/Cがあるのですが どうも、ある一つのメソッドだけABCでそれぞれ引数の数が異なる事になりそうです。 こういう場合どのようなインターフェイスを設計すべきでしょうか? 可変長引数を使うか 引数用構造体を用意してその構造体を適切な形にダウンキャストするか と言う方法を考えてみたのですが、可変長引数もダウンキャストもあまり好ましくないと言う話も聞きます なにか良い方法があるのでしょうか?
引数の数が違うってのは、デフォルト引数使えばいいような話じゃなくて?
761 :
デフォルトの名無しさん :2007/12/27(木) 19:35:40
デストラクタにだけvirtual void をつける人を良く見かけるけどなんで? かっこいいとでも思ってるの?
クラスAでは2個引数を、Bでは3つ、Cは今後展開次第で導入予定で未定です 最大数が決まっていれば必要な物以外にはデフォルト引数を使えば良いのでしょうが・・・
画像ファイルフォーマットか何かで、圧縮フォーマットの展開か何かみたいなメソッドなのかな?w 引き数の個数の上限設けるのも難だし、構造体でお茶濁すのが無難じゃないかな。
>>759 インターフェースを使うって事は、ABCどのインスタンスか意識せずに
共通の方法で扱いたいってことだろ?
でも引数の数が異なるってことは、そのメソッドはABCの違いを意識しないとダメなんだろ?
ならABCそれぞれで定義すべきじゃないか?
>>761 戻り値の型を指定してはいけないだろ
voidであってもエラー
>>761 デストラクタに virtual を付けるのにはもの凄く意味がある。
それが分からないのは読んだ本が悪かったんだろうな。
>>759 こういうのでどう
class MyInterface {
public:
virtual void setSomethingParameter(const char *name, const char *value);
virtual void doSomething();
};
各派生クラスはnameを見てvalueを好きに解釈する
その設定内容をメンバに保存しておいて、doSomethingで使う
というか、 呼び出し引数が違う →呼び出し側でそれぞれの子クラスを区別する必要がある →区別できるなら安全にキャストできる →インターフェース側で対応する必要は無く、ただABCでそれぞれメンバ関数を持てばいい だろ?
デストラクタにvirtualをつけないのは犯罪
区別する必要がある時点で、 インタフェイス側で対応すべきものではないな。
デストラクタがデフォルトでvirtualじゃないのはC++の犯罪。 とは言えない。
>>771 それは
無限には存在しないメモリの犯罪
デフォルトデストラクタはヴァーチャルでもいい気がする。
>>772 メモリというより実行速度の問題な気がするが。
継承しない事が分かっていて、頻繁にオブジェクトが生成/破棄されるクラスのデストラクタはvirtualにしないこともある。その他virtualにしない理由ってあるかな?
ほんの少しでも今後継承を行う可能性があるならvirtual指定しておいて問題ないような
継承してもせいぜい機能強化版クラスを作るだけで、まず基底クラスとして使うことはないパターンだってあると思うぞ。 ほとんどの場合、しっかり作りこまれたクラス階層を作るでもなければそっちの方が多いんじゃないか? でもまぁ、しっかり作りこむつもりのクラス階層に属するクラスならvirtualメンバ関数にはしとくよな。 個人的にはさらにそこでvirtual継承も薦めたいところだが。
>>774 ポリモルフィックに使いたくない(使われたくない)
基底クラスのデストラクタはprotectedでvirtualではない
デストラクタにすればいいらしい。
基底クラスのポインタにdeleteされるのを防ぐため。
778 :
デフォルトの名無しさん :2007/12/28(金) 06:12:41
そういやデストラクタって今までずっと public にしてた.
デストラクタを public 以外にするのは
>>777 のようなケース?
というか,そもそもデストラクタって勝手に呼び出されるから
アクセス指定という概念がなかった.
コンストラクタ/デストラクタを隠蔽しないシングルトンなんて嫌だ。
780 :
デフォルトの名無しさん :2007/12/28(金) 16:49:32
オーバーライドした側の関数にvirtualをつける人良く見かけるけどなんで? かっこいいとでも思ってるの?
>>775 問題ある
virtualは今現在の生成物に影響をもたらすトークンであって
今後の設計の遷移の方針を示唆するコメントではない
とはいえ今後の設計の方針を示唆することにも使えるわけだ。 パフォーマンスなんて大したことなんだし、迷ったら付けとくぐらいで問題ない。
>>782 >今後の設計の方針を示唆することにも使える
使えないよ
だって今後じゃなくて今かもしれないんだし
>>784 仮想関数だと分かりやすいという利点と、
別にオーバーライドであることを保証してくれないから
typo してもコンパイルエラーが出る訳じゃないから
紛らわしいこともあるという欠点があるな。
>>786 あと
struct A { virtual void f(); }
struct B : A { void f(); }
struct C : B { void f(); }
とかなってるときにリファクタリングの結果Aを削除したときなんかは
virtual つけてないと意味がかわるし
メイヤーズかサッターは virtual つけるのを推奨してたと思う
789 :
デフォルトの名無しさん :2007/12/29(土) 00:01:20
仮想関数 virtualって、どんなときに使うんですか? 意味はわかったけど、どういう場面で使うべきなのか イメージがわきません。
クラスの機能を拡張するために継承する時、 基底クラスのコンストラクタが呼ばれるのが邪魔な場合がある。 そういう時、基底クラスに何もしない protected なコンストラクタを用意して、 派生クラスではその何もしないコンストラクタを呼ぶようにするといいのではと思った。 こういう手はよく使われるのだろうか?
基底クラス弄れるなら何だって出来るような。
コンストラクタ内だと仮想関数がうまく働かないってのが問題なんだよな。こういう時。 まあ当たり前の動作なんだが、コンストラクタの処理を変更したい時には困る。
>>791 オブジェクトを生成されたくないなら
protectedにするのはコンストラクタではなく
デストラクタでいいだろ
newできる
>>794 チガウチガウ。
クラス A と、そのバージョンアップ版 A2 を作りたい時の話ネ。
797 :
デフォルトの名無しさん :2007/12/29(土) 09:57:06
皆さん、CSVをパースしたいしたいときは、どうしてますか? 環境はlinux上のg++です。
799 :
デフォルトの名無しさん :2007/12/29(土) 11:46:35
面白くないよ
自作パーザに食わせてる
803 :
デフォルトの名無しさん :2007/12/29(土) 12:28:21
基底で virtual なものは派生でも virtual つけないと ダメっていう言語仕様にしてほしかった・・・・・
>>803 その仕様はダメ。
関数名を typo しても通るから。
override ってのを付けさせる言語があるけど、
そういう奴の方が安全。
C# だったっけ? 使ったことないけど
C#といえば最近回りの人間がよく勧めてくるけどそんなに良いのかな?
>>795 newしたらdeleteするのは当然
そしてdeleteでコンパイルエラー
もしdeleteを忘れたなら別次元の致命的エラー
>>796 そういう話ね
>>806 オライリーの本読んだだけだけど
.NetやるならC++/CLIよりははるかに使いやすい
と思った
>>806 言語的にはいいけど、ネイティブじゃないからなあ。
まあ、そのあたりはトレードオフなところもあるから仕方が無いが。
>>808-809 そっか、言語の素性はいいのか
windows環境なら別に.netだからと困ることもないし(´-`)
要は使い分けってこった
ネイティブじゃないから敬遠してたけど ネイティブじゃないと何か困ることはあるのかと言えば 速度以外にほとんど無いからね ちゃんと作れば普通に速いし、ほんとに遅くて困った時 ボトルネックなとこだけ何とか出来るように設計すればいい
C# 1.0 はテンプレートがなくてげんなりしたけどな。 2.0 で良くなった。
俺は C++ でコアを書いて C++/CLI のラッパーを用意してる. あとは見栄え良くアプリにするチームが C# でアプリにしてる.
まあそんなところが賢い使い方だな。
815 :
デフォルトの名無しさん :2007/12/30(日) 00:40:03
下のコードがVC6では動いたのに、VC2005ではerror c2664で”1 番目の引数を 'std::_Vector_iterator<_Ty,_Alloc>' から 'const POINT *' に変換できません”ってでます。どうすりゃいんでしょう? std::vector<CPoint> p; pDC->Polyline(p.begin(), p.size());
p.begin() ↓ &p.begin()[0]
&(*p.begin()) &p[0] &p.at(0) &p.front()
818 :
デフォルトの名無しさん :2007/12/30(日) 07:44:14
******* ヘッダーファイルの定義(一部) ******************* struct List{ char c_Data[100]; double *d_Value; int i_Priority; struct List *next; struct List *prev; }; ******* C++ ソースコード ***************************** bool AddFunction(struct List *pt_List, int i_AddSum, double *pd_AddData) { int i_Cnt; unsigned long ul_ErrorNo; try { if(pt_List->prev->prev == NULL || pt_List->prev == NULL) { // err return false; } } } ここで、if(pt_List->prev->prev == NULL || pt_List->prev == NULL)が分からないのですが。 ポインタ2つをたどって行った先がnullかどうか、又はprevがnullかどうかを判断しているので しょうか。
>>818 そうだと思うよ。でもそのコードだと後ろの(pt_List->prev == NULL)の意味がない。
もし必要なら逆にしないと。
if(pt_List->prev == NULL || pt_List->prev->prev == NULL)
>>804 delphiがそれだね。間違いがなくなって楽。
あと、delphiのinheritedで派生もとのメソッドを呼べるのも間違いがなくなって便利だ。C++で似たようなことができる技ってないかな。
>>806 C#はネイティブコード出力で、Windows以外でもサポートされるようになったら使いたいな。
>>820 自分でtypedef 親クラス inherited;とでも書けばいいから、
C++には要らないというのが委員会の結論。
D&E 13.6 Inherited::
>>821 おお、その通りだ。早速使わせてもらうよ。
でもそれジェネリックには書けないよね。 typedefする箇所で自分の親を知っていないとダメ。
クラス内で宣言すればいいじゃん。
テンプレート引数Tに対して、typename T::inheritedを使いたければ、 テンプレートを使う側に、inheritedを定義しておけと要求しておけばいい。
基底クラスを変更した時に inherited の定義を変更し忘れると悲惨だな。 でも、C++ は多重継承ができるから inherited を言語仕様に入れるのは無理だと思う。
>>823 とりあえず、親クラスを変更したときに修正を忘れないように、一番先頭で宣言することにするかな。
privateで宣言しておけば余計な副作用もないかな。
言語仕様に含まれてるのが一番楽とはおもうけど。
すれ違いを覚悟して書くと、MS拡張で __super が使えまする。
>>826 提案では、inheritedを使うと曖昧になるときはコンパイルエラーだった。
D&Eに載っていた例。
struct A { virtual void handle(int); };
struct B { virtual void handle(int); };
struct D : A, B { void handle(int); };
void D::handle(int i)
{
A::handle(i); //曖昧でない
inherited::handle(i); // 曖昧
}
QtってC++でしたっけ?
俺も多重継承があるから自前で typedef hogehogehogehogeho Base; とかする方がいいと思うな. とりあえず auto 早く来〜い
そこでboost::typeofですよ
プログラムのある部分にprintfすると正常に動作するのに そのprintfをなくすとハンドルされてないエラーとかでてくるのはなんででしょうか? しかも書き込む文字列を変化させてもエラーがでます・・・
836 :
833 :2007/12/30(日) 19:42:15
すいません。なんかいつの間にか直りました・・・ ただ今度はオブジェクトをdeleteするとエラーが・・・ ソースは長いのですこしはしょります↓ 〜 for(){ 〜 MIntegralImage *img = new IntegralImage(src_img); //imgを用いた処理 delete img; 〜 } 5回目でなぜかエラーになります。
>>828 お!それは便利だ。でもMS仕様か残念。
最低限gccとintelC+で使えれば良いのにな。
>>836 コードを見ないとはっきりしたことはいえないけど
多分スタックを破壊している
>>836 deleteが原因ではないと思うです。
VCでdebugビルドなら、newされたオブジェクトのメモリをダンプしながら実行して、オブジェクトの前後のパディングされてるのが壊されてないか見ると良いです。
841 :
833 :2007/12/30(日) 21:53:23
空のプロジェクトから作成したせいかどうかわかりませんが、デバックしようとすると「デバッグ情報がありません」みたいなことを言われるので、デバッグ無しで実行している状態なんです。 とりあえずオブジェクトの処理のほうを見直してみます。
842 :
833 :2007/12/30(日) 21:56:44
何度もすいません。 デバッグ情報のほうはなんとかなりましたので、メモリのほうを確認してみます。
このスレで扱う程の内容かよ。
同名の名前空間内で using 宣言の効果の範囲を区切ることは出来ますか? /* in X.cpp global namespace */ namespace B { namespace C { namespace D { /* 変更不可能 */ struct type_t; }}} namespace A { /* 変更可能*/ using ::B::C::D::type_t; type_t *func( type_t * ); } namespace A { /* 変更不可能 */ /* ここに名前 func は導入したいが、名前 type_t は導入したくない。 つまり明示的に ::B::C::D::type_t と指定させたい。 */ } /* End of X.cpp */
847 :
846 :2007/12/31(月) 15:06:28
ちょっと変更。 namespace B { namespace C { namespace D { namespace { }}}} namespace A { namespace { }} namespace A { namespace { }} です。
ファイル分けるとか。
本当にそれが必要かを考え直したほうが良いんじゃないか?
>>846 これをなくせばいいだけ?
> using ::B::C::D::type_t;
851 :
846 :2007/12/31(月) 17:04:21
>>850 実際には、
namespace A1 { /* 変更可能*/
using ::B::C::D::type1_t;
using ::B::C::D::type2_t;
……以下略……
type1_t *func_1( type1_t *, type2_t * );
type3_t *func_2( type3_t *, type4_t * );
……以下略……
}
namespace A2 { /* 変更可能*/
using ::B::E::F::type1_t;
using ::B::E::F::type2_t;
……以下略……
type1_t *func_1( type1_t *, type2_t * );
type3_t *func_2( type3_t *, type4_t * );
……以下略……
}
……以下略……
みたいに長めのコードになるので、できれば using 宣言を使いたいのです。
自分は幾つかのサブシステムのうちの一つのサブシステムにある数百のファイルのうちの幾つかを扱っています。
自分の扱っている範囲だけで解決できるような策を探しています。
using 使うのはちょっとアイデアが出ないけど namespace BCD = ::B::C::D; namespace BEF = ::B::E::F; みたいな感じでお茶を濁せる気がしないでもないですな
新年明けましておめでとうございます。 今年最初の質問をさせていただきます。 ostrstreamをwchar_tで使いたいと思っているのですが、どうしたらいいでしょうか? 要するに、ostrstreamのwchar_t版みたいなクラスがあればいいと思っています。 環境はVC2005、WinXP Proです。 よろしくお願いします。
wostrstream ただし、どのくらい真面目に実装されてるかどうかは知らん。
>>851 じゃあusingせずにtypedefで短い名前に
>>854 すいません、今MSDNを漁ってみたのですが、wostrstream が見つけられませんでした。
もう少し、詳しく教えてください。というか、これでぐぐっても一件しか出てこないのですが……
ostringstream wostringstream
wostrstreamくらい自分で作れるだろ……
うお。ostrstream の方だったのか。 つーか、そいつは deprecated だから ostringstream 使おうぜ。
861 :
デフォルトの名無しさん :2008/01/01(火) 06:29:49
STLのalgorithmのtransformの使い方で困ってます。以下のソースのコンパイルが通りません。 (実際のソースはdequeコンテナに色々値を挿入する処理とかがあるのですが、省略しました。) #include <iostream> #include <deque> #include <algorithm> #include <cmath> using namespace std; int main() { deque<double> radians, sines; transform(radians.begin(), radians.end(), sines.begin(), sin); return 0; } コンパイルエラーは以下です。 $ g++ transform.cpp -lm transform.cpp: In function 'int main()': transform.cpp:9: error: no matching function for call to 'transform(std::_Deque_iterator<double, double&, double*>, std::_Deque_iterator<double, double&, double*>, std::_Deque_iterator<double, double&, double*>, <unresolved overloaded function type>)' でも、sinをsin<int>とするとコンパイルが通るのですが、sin<double>としてもダメです。 sin<int>で問題なく動作するのですが、なぜこう書けば動くのかわからないです。 どうかよろしくお願いします。 環境はg++ 4.2.1でlinuxです。
861です。 しかし気がつけばもう2008年か。こんな時間にtransformか、オレ。
gccは使ったことがないんだけど、 テンプレート引数をとるsinって何? complexの奴? それとも使ってるSTLは、C関数によく似たテンプレート版のsinでも提供しているわけ? VCの場合で答えるけど、VCの標準Cライブラリでは、sin関数が、floatとdoubleを取るように、オーバーロードされている。 それで、曖昧になって、コンパイルできない。 曖昧にならないようにするには。 std::transform( radians.begin(), radians.end(), sines.begin(), static_cast< double (*)(double) >( &sin ) ) ;
わざわざキャストするのが面倒だったら、こんな方法もあるけど。 struct SinFuncObj { template < typename T > T operator () (T arg) { return sin(arg) ; } } ; std::transform( radians.begin(), radians.end(), sines.begin(), SinFuncObj() ) ;
gcc4.1.2のstdlibc++6のstd::sinはlong doubleとfloatとtemplate関数になってて std::sin<int>はdouble sin(int)みたいなのとしてインスタンス化されるから通るようだ でsin<double>だとダメなのはこのtemplate functionの戻り値の定義が enable_if<double, is_integer<T>::value>::type のようなのになってて、T=doubleだと(略)::typeによってsin<double>が未定義とみなされ 故に<unresolved overloaded function type>と しかしtransformのエラーだけ見せられてもなんのこっちゃわからん罠
みんなありがとう 865が言っているのは下記の部分についてですか? 自分でも読んでみようと思ったのですが、 __enable_ifがわからん(泣) googleしても出てきません。 using ::sin; inline float sin(float __x) { return __builtin_sinf(__x); } inline long double sin(long double __x) { return __builtin_sinl(__x); } template<typename _Tp> inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, double>::__type sin(_Tp __x) { return __builtin_sin(__x); }
http://www.boost.org/libs/utility/enable_if.html boostにそっくり。
メタプログラムみたいだね。
想像だけど
__is_integer<_Tp>は_Tpがintegral型だとtrueで、そうでなければfalseになる
として、__gnu_cxx::__enable_if<__is_integer<_Tp>::__value, double>::__type はテンプレートの第一引数型パラメータがfalseに対して
は__typeをtypedefしてない(故意に)からインスタンス化に失敗してエラーと
なってるんじゃないか。trueの場合はdoubleと評価される。
sin<int>だと
__is_integer<int>::__valueがtrue、sin<double>だと__is_integer<double>::__valueがfalse。
>>861 アルゴリズムに関数テンプレートを渡すのって
標準に関して言えば違反してるんじゃなかったっけ。
sin<int>のように 明示的に型引数与えてコンパイルが通ったとしても。
870 :
デフォルトの名無しさん :2008/01/01(火) 13:24:11
前々から疑問だったんだけど、標準ライブラリとかboostのコードってなんでこう読みにくくしてあるの? _Tpとか__nとかもうちっと気の利いた変数名をつけようとは思わないんだろうか それに改行の位置やインデントもバラバラに見えるし なんか規則があるんだろうけど一般とは全然違うよね なんでこんなわかりづらいコードなの?
Dinkmuwareのソースはわざと読みにくくして、出荷してるんじゃないのかな。 Boostが読みにくいと思ったことはないな。 ソースコードが変態であることには同意するが。
生成コードに影響するならともかく、単に読みにくいだけのような気もするし。なんでだろ?
標準ライブラリとかboostを使う側のコードと名称が衝突しないようにだろ。
名前空間は使えないのかな
>>873 先頭に _ のついた識別子は処理系やライブラリ用の予約語だから、
衝突するしないだけで言えばそれで _ つけるだけで十分だな。
(本当はもうちょっと複雑なルールなんだけど簡単のため割愛)
とすると俺様ライブラリ用の予約語にしてもいいわけだ
俺様用は、アンダーバーを3個___にようか。
酔っ払ってんのか?
>>875 メイヤーズのSTLの46項に書いてあるけど、
同じ数の型パラメータをとるプライマリテン
プレートのオーバーロード解決ができないみたい。
コンパイラによってはコンパイルできるらしい。
以下はVC++ 2008ではambiguousでエラーだった。
template<typename T>
void func(T t);
template<typename T>
void func(T* t);
int main()
{
int a[] = { 1,2,3 };
for_each(a, a+3, func<int>);
return 0;
}
>>875 説明不測だった。以下はVCでもコンパイルできる。
メイヤーズの本では以下も標準では違反してる
らしいと言ってる。とオレは理解した。
template<typename T>
void func(T t);
int main()
{
int a[] = { 1,2,3 };
for_each(a, a+3, func<int>);
return 0;
}
ちなみに面倒くさくて標準を調べたことはない。 関数オブジェクト使えばいいから。
それはアルゴリズム一般でそうなのか? それだと greater とか使えんことになるけど。
>>885 greaterは関数テンプレートではなくて
クラス(構造体だけど)テンプレートでしょ
>>885 お前の使ってるコンパイラのSTLは、greaterをテンプレート関数で実装してんの?
でも、まさかテンプレート関数を渡せないってことは・・・調べるか。
>>882-883 メイヤーズの本を読んだことがないんだけど、
それは単にArgument Deductionが曖昧になる場合があるって話じゃないの。
テンプレート関数をアルゴリズムに渡すのが規格違反ってことは、
テンプレート関数のポインタが取れないってことになると思うんだけど。
>>889 >それは単にArgument Deductionが曖昧になる場合があるって話じゃないの。
そう。メイヤーズの本では、この可能性があるから標準では禁止しているよう
だと書いてある(とオレは理解した)。すまんが原書は読んでいない。
ただ、webで標準のアルゴリズムの章をざっと見たけど何も制限らしいことは
書いていなかった。
実際はどうなんだろ。
質問したものだけど、 芋焼酎を飲んで適当にトランプとかやってるうちに、 どんどん高度な(少なくともオレには)書き込みが。。。 みんな今日は1月1日なんだよ、どうしてんだよ
お年玉ってやつだ
orz
895 :
デフォルトの名無しさん :2008/01/02(水) 14:02:10
inlineで質問なんですが、 Foo.hppで定義したclass Fooのインラインメソッドhoge()があった時に クラスFooのインライン以外の実装をFoo.cppで記述してFoo.oを作成したとします。 この時に、Foo::hoge()を呼び出すclass Barの実装を定義したbar.cppでFoo.hppをインクルードするわけですが、 bar.oを作成するときにFoo::hoge()はインライン展開されるのでしょうか? ここでFoo::hoge()はトリビアルな関数とします
アセンブリコード出してみりゃ分かる
>>895 ま、gccやMSVC++ではインライン展開されるよ。ちゃんと。
なにが疑問なんだ。
inlineもそうだけどtemplateの実装ってどこのオブジェクトファイルに展開されるんだろ?
どういうコードがインラインになるのか、ならないのかは、 ひとえに処理系の裁量に委ねられる。規格には、こういう コードならインラインせねばならない、というような強行規定は 存在しなかったはず。
息を吸うように逆アセンブルすれば万事解決
templateとか、class-staticなメンバ関数なんかは、使用した翻訳単位(≒object file) それぞれで展開され、リンカが、適切に多重存在する実装を纏める、 という処理系がほとんどではないか。
>>898 使っているすべてのオブジェクトファイルにコード吐いて、
リンク時に重複を削除とかじゃないのかな。
newを使ってメモリ確保するときに、必ず失敗はあると思うのだけど、 C++はその例外処理対策をしてないソースばっかり見かける。 Cのmalloc使った時は、アフォみたいにNULLと比べて しっかり作ってたんだけど、そこら辺をしてないのはどうしてですか?
>>903 そりゃ、実際にはメモリ確保できなかったときに対応する必要はあるんだろうけど。
ほとんど、そんなケースは起こらないから、考えてないだけじゃね?
>>903 どこかでcatchしてるからじゃないか?
>>903 ・例外キャッチだけじゃどうせ片手落ちだから何もしない
・例外キャッチしてもterminateくらいしかすることないから何もしない
のどちらかまたは両方。
学生の頃 3次元モデルのシュミレーションやるのに 1000x1000x1000 の double 配列持ったクラスを new しようとして「実行できない!」ってわめいてた 後輩がいたな… # おまえそれでも工学部かと(ry
まさかnewしてる箇所だけ見て言っているわけではないと思うが。
>>903 例外でスコープ飛び出しても、しっかりデストラクタが呼ばれるなど、ある程度コンパイラが自動的に解決してくれてるからとか。
それですまない部分だけ、キャッチするようにしてるんじゃないかな。
newが失敗したら再度newだろ常識で考えて
例外安全性が考えられていないライブラリを使ってたりすると、自分のところでcatchしてもどうしようもない、というのはある。
912 :
デフォルトの名無しさん :2008/01/02(水) 16:49:31
>>903 まず、
どういうときに例外がスローされると思っているか
例外がスローされなかったら何が保証されていると思っているか
を聞こうか。
釣堀だな。
結局、「メモリが足りません」で落ちるか、「NULL触ったよ一般保護違反」で落ちるかの 二択なら、別にどっちでも良いんじゃないの。 そりゃ、メモリが足りないなりにリカバリにつとめるとか 保護違反例外がなくて、NULL触っても動き続ける環境とかなら 話は別だけど。
917 :
デフォルトの名無しさん :2008/01/02(水) 17:00:43
>>916 newがNULLで戻ることは無い(except 馬鹿コンパイラsuch as VC)。
903のOSは何だ?どうすべきかはOSとOSの設定によるだろう。
つstd::nothrowというツッコミはお腹いっぱいな。
919 :
916 :2008/01/02(水) 17:02:41
>917 そこは、 >Cのmalloc使った時は、アフォみたいにNULLと比べて >しっかり作ってたんだけど に対して、別にNULLチェックも要らないといえば要らない、ってはなし。
903はどこいったんだよw
void*myalloc(size_t size){ if(void *m = malloc(size) ){return m;} else { perror("memory allocation error"); exit(1);} } みたいなコードでお茶を濁すのがよくある話。
Cのmallocと違って、C++のnewは、コンストラクタのおかげで確保したメモリ領域に実際に 触ることが多いから、mallocよりは結果のチェックのしがいがあるかもしれんな。 俺はしてないけど。
>>907 8GB確保か。32bit OSじゃ無理だが、64bitだったらもうすぐご家庭レベルでも現実的になるかも名w。
メモリ暴落してるし。
4KbitのDRAMを並べてたころが懐かしい。
コンストラクタ、デストラクタで例外をthrowするな そして、スマートポインタを使え
コンストラクタは投げてもいいじゃん
>>926 コンストラクタで、投げると、デストラクタが呼ばれない。中途半端なつくりかけオブジェクトが残される。
>>927 後始末が必要なことは初期化リストですればいいし
コンストラクタのボディ部分では強い例外保障をすればいいと思う
後始末が必要なものはクラスで包んでおけば、どこで例外が起きるとか気にする必要ないんだけどね。 struct A {}; struct B : A { std::auto_ptr<int> a, b, c; B() : a(new int(1)), b(new int(2)), c(new int(3)) {} }; B* p = new B; 例えばnew int(3)で例外が投げられても、構築済みのメンバa, bと基本クラスAのデストラクタが呼ばれ Bの為に確保されたメモリも解放される。
931 :
929 :2008/01/03(木) 10:33:17
>>930 それを言ったつもりだったけど
端折り過ぎたか
別の話になるけど
auto_ptrをメンバに持つのは、例外指定関連でまずかったような気が
メイヤーズかサッターが言ってたと思う
>>930 その場合、a,b,cのデストラクタは呼ばれて、Bのメモリは開放されるのはわかるが、Bのデストラクタは呼ばれるの?
>>932 呼ばれないよ。だってBのコンストラクタは完了して無いもん。
>>933 すると生成済みのクラスのデストラクタしか呼ばれない。ってことでOK?
生成中のクラスの後始末は、プログラマがするってことかな。
>>932 呼ばれないし、呼ばれる必要も無い。
必要なのはスタックの巻き戻しによる
構築済みオブジェクトの解放と
operator delete()によるメモリ解放。
つpimplイディオム
forのループの途中でbreak;で抜けるのはありですか?
ありだろ
なし
forループ使ったら負けかなと思ってる
廻る回数が不定ならwhileを使うべき。
再帰で十分
俺はbreakが1個ならforを使う。2個以上使う状況では、whileを使ってbreakは使わないようにしている。
俺は積極的にSTLのalgorithmを使って自分でループを書かないようにしたいなぁ
しかし現状だとforループを使うのも視認性的にある程度仕方ないと思う。 C++0xでrangeやlambdaが入ってきたらalgorithm使いまくりになると思うけど。
copy transform for_each あたりは使いまくってるな。 C++0xでlambdaが入ったら、for_eachと組み合わせて 使いまくると思う。あれは凄い便利だから。
947 :
デフォルトの名無しさん :2008/01/03(木) 15:42:58
ほう、0xでlambdaが入ることになったんですか?
>>942 否定はしないんだが, c++ って末尾再帰をまともに扱うような
言語仕様になってないじゃん!
g++ あたりだと, 限られた範囲では末尾再帰を繰り返しに
展開するみたいだが…
949 :
デフォルトの名無しさん :2008/01/03(木) 16:02:05
どこのコンパイラがいいですか? clですか? g++ですか?
icc
>>948 モダンなコンパイラなら、末尾再帰ぐらい普通に最適化するだろ。
VCもするし。
953 :
デフォルトの名無しさん :2008/01/03(木) 16:50:05
iccは高いですね。 clのまま、最適化で対応します。
954 :
デフォルトの名無しさん :2008/01/03(木) 16:55:37
移植性、経済性という観点ならばJava環境が良い。 しかし、cygwinがお荷物になる。
>>952 C++一辺倒なので相互再帰でしかも末尾再帰なんてコードに価値があることすら知らなかった。
試してみたら、VC9では、無理だった。
でも、C++じゃあまり見ないコードだよね。
>>947 現状TR1には入ってないから無理かな。
いや、ライブラリとしてのlambdaじゃないだろ。 Boost.Lambdaも面白いけど、とてもアレを実際に使いたいとは思わん。
>>955 VC++は相互だとダメだと思うが、普通の末尾再帰の最適化ならやってくれるよ。
/CLRは知らんけど。
うーわ、今まで自分で展開してたよorz
ええええ!末尾再帰を展開してくれるの?知らなかった。これからは活用させてもらうよ。
末尾再起はループにならんよ VC7.1だけど int f(x) { if (x) return f(x - 1) + x; else return x; } _f PROC NEAR ; File c:\tmp\x.c ; Line 3 push ebp mov ebp, esp ; Line 4 cmp DWORD PTR _x$[ebp], 0 je SHORT $L794 mov eax, DWORD PTR _x$[ebp] sub eax, 1 push eax call _f add esp, 4 add eax, DWORD PTR _x$[ebp] jmp SHORT $L793 $L794: ; Line 5 mov eax, DWORD PTR _x$[ebp] $L793: ; Line 6 pop ebp ret 0 _f ENDP
#include <stdio.h> int add_r(int sum, int i) { if (i<1) return sum; sum += i; return add_r(sum, i-1);} int add(int i) { int sum = 0; return add_r(sum, i); } int main(){ printf("%d\n", add(100000)); return 0; } とりあえず作ってみた。 CL hoge.cpp でコンパイルするとスタックオーバーフロー。 CL /O2 hoge.cppでコンパイルすると結果が出た。 スタックオーバーフローでなにもメッセージが出ないのは何とかならんのでしょうか?
>>961 > if (x) return f(x - 1) + x;
それ + x がスタックに積まれるから末尾になってない
964 :
947 :2008/01/03(木) 19:38:50
>>957 言語仕様を変える方のラムダも0xには入らないよ。
VC2005で試した。スゲー int SumZ1(int x,int y) { if(x>0) { return SumZ1(x-1,y+x); } else { return y; } } がこうなった。 00401000 mov ecx,dword ptr [esp+4] 00401004 mov eax,dword ptr [esp+8] 00401008 add eax,ecx 0040100A add ecx,0FFFFFFFFh 0040100D test ecx,ecx 0040100F jle SumZ1+1Eh (40101Eh) 00401011 mov dword ptr [esp+8],eax 00401015 mov dword ptr [esp+4],ecx 00401019 jmp SumZ1 (401000h)
966 :
デフォルトの名無しさん :2008/01/03(木) 19:49:02
>>961 static int f_(int x, int a) {
if (x) return f(x-1, x+a);
else return a;
}
int f(int x) { return f_(x,0); }
のように、引数を追加して末尾再帰に変換して実験しないといかんよ。
g++だと相互再帰も最適化されるはず。だれか試してみ。
969 :
デフォルトの名無しさん :2008/01/03(木) 19:58:04
>>959 自分で展開って具体的にはどうしていたんだ?
辞令教えて。
相互末尾ってこんなのでいい?実用的なのは思いつかない。 bool odd(int i); bool even(int i) { return (i==0) ? true : odd(i-1); } bool odd(int i) { return (i==0) ? false : even(i-1); }
971 :
970 :2008/01/03(木) 20:23:26
VC++2005/2008 の/O2 で最適化された。 /O1 では× VC++6は× でした。
>>969 末尾再帰はループぶん回すだけだよ
複雑なのになると、ボトムアップとトップダウンで展開して、
ループに置換できないか考える
再帰の除去とかでぐぐるとよろし
973 :
955 :2008/01/03(木) 23:57:02
あ、そうか、
>>961 じゃ末尾再帰にならないか。
もう一度試してみたら、
相互再帰の末尾再帰は、VC9で最適化された。
そもそも、最適化できなかったのが不思議だったんだよね。
MSほどのコンパイラが最適化できないとは思わなかったから。
VC8以前は試すのが面倒。誰かまかせた。
namespace func { namespace type { typedef type TYPE; } using namespace type; TYPE f( void ); } と namespace func { typedef type TYPE; TYPE f( void ); } は何か違いがありますか? また、長期的に考えて安全そうなのはどちらだと思いますか?
TYPE関数がtypeの名前空間内にあるか否か。 どちらがいいかなんてその時の状況による。
.hとか.hppとかでusingしたら殺す。
前者だと別の名前空間に名前空間 func::type だけを指定して取り込めるな。 namespace type { typedef type1 TYPE1; typedef type2 TYPE2; // 新しく型が追加された場合 } namespace func2 { using namespace func::type; // <= 前者+using 指令の場合は 自動的に TYPE2 が取り込まれる。 // using func::TYPE1; // using func::TYPE2; <= 後者+using 宣言だと、この行を追加するまで追加されない。 }
>>976 仮に *.h で
>>974 の using namespace をしたとして何が問題になる?
>>978 hoge.h(仮)をインクルードしたファイル(又はhoge.h自身)のnamespace func内でTYPE型を宣言したときにぶつかる。
>>979 >>974 は using namespace しない場合は namespace func に直に TYPE 型を宣言するって言ってるんだから、どっちにしろぶつかると思うが。
>>977 974のコードと混ざってるからか意味がわからん。
using namespace func::type; // <= 前者+using 指令の場合は 自動的に TYPE2 が取り込まれる。
何でTYPE2が取り込まれるの?取り込まれるのは、func::type::TYPEでないの?
// using func::TYPE1;
// using func::TYPE2; <= 後者+using 宣言だと、この行を追加するまで追加されない。
名前空間funcにTYPE1やTYPE2は無いと思うんだけど。
>>980 namespace func内にTYPE型を宣言する場合は、TYPEは funcの物になる。func内に他の型を宣言する時はfunc内の名称とぶつからないようにするだけ。
typeの持ち物であるTYPEを*.hのnamespace func内でusingするのは問題。
とはいえ、殺すは言い過ぎた。すまんかった。
namespace func に TYPE を導入することが目的ならどちらも違いはないと思う。
>>977 >名前空間funcにTYPE1やTYPE2は無いと思うんだけど。
説明不足ですまん。TYPE1は旧・TYPEのつもりね。
typedef type2 TYPE2; // 新しく型が追加された場合
namespace func2 {
using namespace func::type; // <= 前者+using 指令の場合は 自動的に TYPE2 が取り込まれる。
using func::TYPE;
using func::TYPE2; <= 後者+using 宣言だと、この行を追加するまで追加されない。
}
前者ではtype definitionだけをusingディレクティブ一発で 取り込めるってことね。
void hoge( void ){ return static_cast<void>( huga ); } がコンパイルできるのは正しいことですか?
わりとね
でも void v = static_cast<void>(hoge); が通らないから使い道ないんだよね。 これが通れば template 書くのが楽そうなんだが。
voidは不完全型? 定義できなだろ
return 文に直接書く場合は普通に使える。
普通に疑問なんだが
>>986 がコンパイルされたばあい、hugaがスタックに積まれて戻り値として処理されるってことなの?
戻り値も無いのに戻り値として処理されるわけがない
ほーち
>>991 static_cast<void>( huga );
return ;
と書くのと同じ。
以下のようなテンプレート関数があり、 template<typename X> typename X::result_type hoge( X x ) { return x(); } で、result_type が void の場合にコンパイルエラーしないために、 void 型の戻り値は許されてる。