1 :
デフォルトの名無しさん :
2008/12/27(土) 10:27:23
複数のcppで同じ文字配列を使いたくて、 ヘッダーファイルで extern vector<string> String(10); cppファイルで vector<string> String(10); としたのですが「'String' : 再定義されました」とエラーになりました。 どういう風にやれば良いのでしょうか。
(10)がイケテナイ
地鎮祭だ STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
>>3 なるほど!配列数はヘッダで宣言しないのですね。
教えて下さり有難う御座いましたm(_ _)m
そもそも、それ配列じゃねえし。
>>5 いやもう少しわかりやすくいうと(10)ってstd::vectorのコンストラクタを
呼び出す構文なのね。つまり宣言ではなくて定義になる。
実行速度を測るためのコードを書くと、最適化でコードがごっそり消されたり、 キャッシュのせいか2度目の実行時の速度がめちゃくちゃ速くなったりすることがよくあります。 どういうところを気をつければ、正しい実行速度が測れますか?
>>8 測るためのコードを書かず、測りたいコードを素直に測る。
>>9 ライブラリが提供する1つの機能(STLとか)の速度を測りたい時にそうもいかないです。
>>10 測りたいコードについて、「1つの機能」だけを適用した状態にして測り、元のコードの
結果と比べればいい。
>>10 あんまり意味がないぜそれ
実際のコードで図るしかない
だからみんな実測実測いってるわけだから
そのノウハウだけで商売になりそうなくらい速度計測は難しい。 だが商売になりそうにないくらい需要は薄い。
C++のオナニー機能を使うからそういう困ったことになる C+クラスしか使わなければ素直にアセンブラで検討すればいいだけなのに
またお前か。
>>14 アセンブリコードから速度が検討できるのって、キャッシュや分岐予測のない環境だけだろ。
そう言うと「キャッシュや分岐予測なんて要らない」って言い出すんだろうけどな、あんたは。
>>14 大丈夫、レガシーCのコードでも簡単に計測できないから。
もしできると思っているのなら、ソフトウェアだけでなくハードウェアの知識も10年くらい手前で止まっているという証明。
いまどきアセンブラから速度ってw
ナノ秒オーダーでタイミング取るために実際の正確なサイクル数が必要とかならともかく 二つの方法を比べてどっちが速いかならアセンブラで十分検討できるだろう それすら出来なくしてくれるのがC++のオナニー機能どもだけど
あんた、おつむの更新を10年くらい忘れてないか? そう簡単に事が進まないのが今時のCPUだ。 まぁ、未だにシングルタスクOSで頑張っているなら気にすることもないかも知れんが。
>>11-13 例えばコンテナに対する操作にしても、一概にこれといった速度を計測できないわけですか。
googleで検索しても、この手の情報がほとんど出てこないのも納得しました。
>>21 単品で計測はできるんだろうけど、それじゃあんまり意味は無いってこと。
どうやら検索の仕方も10年前で止まっているらしい。決して少なくない情報さえ見つけられないのだから。
>>25 前後の処理によって速度が変わってくるということでしょうか?
抽象的な一般論で良ければ、 vectorのinsertはO(n)だけど、setのinsertはO(log n)であるというような計算量の規定はあるよ。
>>26 それもあるかもね
とにかく影響するもんが多すぎて調べられない
考えてるほど単純じゃないよ
C++は頼みもしないおかしなものを大量にくっつけるからねぇ…
>>27 大体はそれで間に合うんですが、実際の細かい速度の差が気になりました。
>>28 複雑なんですね。
thxでした。
class Hoge {...}; class Fuga { Hoge hoge_; ... }; class Piyo { vector<Fuga> fugas_; ... }; Fuga1つに対して必ずHoge1つが必要なので、HogeをFugaのメンバにしたのですが、 よく考えたらFugaの中でHogeは使われておらず、getter/setterがあるのみです。 FugaのメンバからHogeをなくして、Piyoのメンバにvector<Hoge> hoges_;と書くべきなのでしょうか?
>>31 Hogeにはgetter/setterのみということは、PiyoはHogeについても一一管理しているのか?
それならばその考え(Fugaのメンバにしない)でもいいと思うが、Hogeのレゾンデートルに
Fugaの存在が不可欠ならPiyoに対してFugaを公開すること自体がおかしい気もする。
>>32 Hogeのメソッドは全て、Piyoが必要とするもの、といった感じです。
HogeはFugaを構成する1つの部品という見方で、Fugaのメンバにしていましたが、Hoge単体で見ても意味のあるオブジェクトではあります。
> Piyoに対してFugaを公開すること自体がおかしい気もする。
すみません意味が分からないんですが、単にFugaとHogeの打ち間違えでしょうか?
>すみません意味が分からないんですが、単にFugaとHogeの打ち間違えでしょうか? あ、悪い、混乱してた。その通りで。Hoge自体に意味があるならFugaが関与する必要もない気がするけど、 常にセットで扱うならセットにしておきたい気もするし、悩みどころだな。
セットで扱いたいならvector<pair<Fuga,Hoge> >で持っとくとか でもFugaとHogeって実は何の関係もないんじゃね?
>>34 うーん、悩みますねぇ・・・。
>>35 pairはfirst,secondが何を指しているかわかりづらいのがちょっと嫌なんですよね。
クラスとクラスが関係するとはどういうことなのかわからなくなってきました。
>>36 pair の first, second がいやなら自分で構造体(クラス)を作れば良いじゃない。
boost::tupleはどうするんだ もっとひでえぞ
あ、今じゃstdext::tr1::tupleか
ぽまえら、C++でfinally的なものを使ってる輩はいるかにょ? 「class finallyを作って、デストラクタにやりたい処理を入れる」は ぽもろ〜なアイデアと思ったのであるが、実際使ってみると 関数とスコープが違う為に、いまいちつかえなりかずき。 よろしく教えてごモンキ〜
俺はfinallyの必要性感じた事ないな。 後始末が必要なもんはカプセル化して、デストラクタに任せてる。
finallyは結局デストラクタをインラインで書いてるようなもんだから RAIIができるC++にはあんまり必要ない 逆に言えばJavaにfinallyが必要なのはデストラクタがないから
いちいちクラス書くのめんどい場合もあるけどな
RAII 使ってると大抵の場合は finally とか必要にならない。 たまに欲しくはなるが。
クラスの継承とアドレスに関して質問です。 たまに、派生クラスのインスタンスのポインタを基底クラスのポインタに入れたり、void*にいれておくと 単純なキャストでは基底クラスの純粋仮想関数が呼ばれたりすることがありますが、そうなる条件というのはどういう時ですか?
>>46 そうなる場合が思いつかないな?そうなる場合のソースプリーズ
多重継承がないなら本当にアホなことをしていると思われる
49 :
デフォルトの名無しさん :2008/12/30(火) 16:40:24
なぜ、void*な変数にいれるんだ?
void*はかなり怪しいな。 慎重にDerived*→void*→Derived*としているなら問題ないはずだが、 例えば、Derived*→void*→Base*とかはまずいだろう。
アップキャストは単なるアドレスの解釈の変更ってだけじゃないことがあるので void* を通す時は必ず void* を通す前の型に戻す必要がある。
近頃思うんですが、あるデータとそれに対する操作を実装するとき、 data.F()という実装より、F(data)という実装の方が、 操作の拡張がしやすい気がします(前者はData.hを書き換えないといけないし、メンバ関数が増えていくのも嫌)。 あと、2種類のデータに対する操作を実装する時に、getter/setterだらけになるのもちょっと・・。 OOPに対する理解が足りてないだけなのでしょうか?それとも別のプログラミングパラダイムで書くべき物なのでしょうか?
dataの公開インターフェースだけで実装できる機能だったら、 F(data)の方がカプセル化という観点ではオススメと EffectiveC++に書いてあったような つまりstd::stringのメンバ関数とかダメじゃねと
>>53 パラダイムの問題というよりは、たぶんC++のシンタックスが古臭いのが原因だと思うよ。
新しく出来てきたオブジェクト指向言語は、どっちの問題もシンタックスシュガーで解決してる。
D とか F(data) って関数を data.F() って呼べた気がする。
ジェネリック関数ってやつか
C++に近い言語での拡張メソッドはC#だけだと思っていた。
>>53 操作を拡張するときは継承を使う。そうすると既存クラスのヘッダーは変更せずにdata.F()を追加できる。
メンバ関数が増えそうなら、継承の階層を分けてメンバ関数を分類すればいいと思う。
F(data)も一応隠蔽の役目を果たすのでありだと思うが、無造作に作りすぎるとわけがわからなくなると思う。
メンバ変数に単純にアクセスするためのgetter/setterが増えると隠蔽するという考え方が崩れていくので要注意。機能を整理して最小限のメンバ関数を作るように検討したほうがいいと思うよ。
機能拡張で安易に継承を使うのはどうかと思うよ。 継承したクラスを通さないと追加した機能を実現できないってのは、 複数の機能を別々のタイミングで追加したい場合に問題になる。
vectorなんかの継承と同じことだな。 デストラクタにvirtualが付いていても、メンバ変数の追加が無くてもだ。 スライシングは動いても気持ち悪いし、既存ライブラリから 引数を与えられる場合に対処できない(まさか無理にダウンキャストしないよな?)し。
>>54 なるほど、publicメンバだけで実装できる場合に非メンバ関数で実装することはよくあるんですね。
しかし、privateメンバにはアクセスできないので、Dataをクラスで書くことによって拡張がしにくくなるのでは?と思ってしまいます。
>>53 にも書きましたが、void F(DataA& dataA, DataB& dataB)という関数を書く時とか特に。
>>55 ,56
そういう書き方ができると便利ですね。
C++0xで使えるようになっていて欲しい。
>>60 インターフェイス以外の継承には抵抗があります。
継承で拡張するときのために、常にメンバ変数をprotectedに書いておくというのもちょっと。
継承するときでもメンバー変数はprivateにしたほうがいいよ。
なんで?
public にしない方がいいのと同じ理由。 でも、実際には面倒くさいので(ry
template<class T>friend class T; これってどういう意味ですか?
コンパイルエラー
69 :
デフォルトの名無しさん :2008/12/30(火) 22:24:57
これが通るBCCはおかしいのかな
それより意味を教えてください!
72 :
デフォルトの名無しさん :2008/12/30(火) 22:38:47
struct Base{ virtual ~Base(){} virtual void func() = 0; }; struct Middle1:public virtual Base{ virtual ~Middle1(){} void func(){} }; struct Middle2:public virtual Base{ virtual ~Middle2(){} void func(){} }; struct Derived:public Middle1,public Middle2{ }; ダイアモンド継承で更に曖昧なオーバーライドを解消したい場合はどうすれば良いですか・・・
Derived でも func を定義する。
Middle1とMiddle2両方でfuncの実装は必要です。Derivedで定義しちゃったら、両方無効ですよね?
76 :
デフォルトの名無しさん :2008/12/30(火) 23:08:51
関数名を同じにしていることの意図によるだろ あるいは安直すぎる関数名で事故ったのかは計り知れんが
Derived を Middle1 にキャストしても 仮想関数である以上 Derived の func が呼ばれる。 現状では Derived には func が2つあるので 何を呼んでいいか分からないのでエラーになる。 だから Derived に func を定義する必要がある。 中身は Middle1::func(); Middle2::func(); でいいかどうかは Middle1::func() と Middle2::func() の実装による。
そもそも func は Base で定義すべきものかも考えた方が良い。 istream と ostream でも seek 関数は seekg と seekp に分けている。
Baseから派生クラスのfuncを呼び出し、更にそれぞれのfuncからMiddle〜の仮想関数を呼び出します。 DerivedにはMiddle1,Middle2が持つ仮想関数のオーバーライドがあるという形です。 こうすれば、リスナーの形をとりやすかったんですが・・・
Derived のインスタンス d を Middle1* にアップキャストしようが Middle2* にアップキャストしようが Base* にアップキャストしようが p->func() として呼ばれるのは Derived::func() だ。
割り込む形での質問になり申し訳ありません。 また、ひょっとしたらスレ違いかもしれません。。。 >>> tmp.cpp #include <cstdio> template <typename _T,int _N=2*1024*1024> struct hoge{ _T buf[_N]; }; int main(void){ using namespace std; typedef hoge<char> hage; hage h; h.buf[0] = 'a'; printf("%d\n",(int)sizeof(hage)); return 0; } > g++ tmp.cpp -O3 -Wall > ls -s 12 a.out* 8 tmp.cpp 今までずっと「実行バイナリをメモリにロードするというのは、そのままメモリ上にコピーすること」と思いこんでいたのですが、 どうやら勘違いだったようです。 2Mのバッファは、いつどのタイミングでどこに確保されるのでしょうか。
結局確保せずにおわると思うよw
今試しにバッファサイズを32Mにしたらセグメンテーションフォルトになっちゃいました。
メモリはギガ単位で積んであるマシンなんですが……
>>82 えーそんなー(´・ω・`)
えっと、なぜでしょうか。
それはたぶんスタックオーバーフローという奴かと
そのバッファーはスタック上に取られている。バッファーの確保はnewを使う
>>83 実行サイズが2Mがないことが疑問なんだよな?
2Mの確保は実行時に確保される
スタック足りるかは別として
ulimit -a [~] -t: cpu time (seconds) unlimited -f: file size (blocks) unlimited -d: data seg size (kbytes) unlimited -s: stack size (kbytes) 8192 -c: core file size (blocks) 0 -m: resident set size (kbytes) unlimited -u: processes 16383 -n: file descriptors 1024 -l: locked-in-memory size (kb) 64 -v: address space (kb) unlimited -x: file locks unlimited -i: pending signals 16383 -q: bytes in POSIX msg queues 819200 -e: max nice 0 -r: max rt priority 0 俺のスタックの設定はデフォルトです…。
なるほど、スタックに積む段階で領域が確保される、と。 そして、スタックも32M無いからセグメンテーション違反が起きたと。 なんとなく理解できた気がします。 素直にnewしてコピー禁止してデストラクタでdeleteします。 ありがとうございました。 > ulimit ulimit: command not found (´・ω・`)ごめんなさい
こうすれば、と書こうとしたが、funcはBaseからの仮想関数なのね、ならだめだ。 struct DM1 : public Middle1 { virtual void func() {func_m1();} virtual void func_m1() = 0; }; struct DM2 : public Middle2 { virtual void func() {func_m2();} virtual void func_m2() = 0; }; struct Derived : public DM1, public DM2 { virtual void func_m1() {} virtual void func_m2() {} };
hage自体をnewすればいいじゃん
91 :
デフォルトの名無しさん :2008/12/31(水) 00:29:02
誰か AA 作ってよ
92 :
73 :2008/12/31(水) 00:30:46
>>89 ありがとうございます。
ちょっと長くなりましたが、これでやりたいことできました。
仮想継承はむしろまずかったですね。
struct Base{
virtual ~Base(){}
void run(int i){func(i);}
virtual void func() = 0;
};
struct Hoge:public Base{
virtual ~Hoge(){}
void func(int i){if(i>0&&i<10)hoge();}
virtual void hoge() = 0;
};
struct Fuga:public Base{
virtual ~Fuga(){}
void func(int i){if(i>20)fuga();}
virtual void fuga() = 0;
};
vector<Base*> container;
struct Derived:public Hoge,public Fuga{
Derived(){
container.push_back((Hoge*)this);
container.push_back((Fuga*)this);
container[0].run(5);
container[0].run(15);
container[1].run(25);
}
void hoge(){cout << "hoge()" << endl;}
void fuga(){cout << "fuga()" << endl;}
};
おっと・・・ちょっとミスった・・・。
度々申し訳ないですが、もう少し質問を続けさせて下さい。 メンバ変数をprivateに置き、外部から操作する時はpublicメンバ関数を呼び出すことによって、カプセル化されますよね。 この利点はよく分かるのですが、あとで拡張するときにpublicメンバでできることしかできなくなるのが不便に感じます。 C++には、意味があってつけた制限をあとから明示的に解除する仕組みを持った物がありますよね。 const_castとか、boost::shared_ptrがT*への暗黙の型変換はないけどget()で取得できるところとか。 privateメンバに関しても、基本的には制限したいけど、明示的に制限を解除する仕組みが欲しくなります。 1つ方法としてfriendがありますが、あとで拡張したくなったときにpublicメンバだけじゃ無理!というケースで元のクラスをいじらず拡張することができません。 あとで拡張するときに、privateメンバへのアクセスできないことが問題になった場合、どのように解決すればよいのでしょうか?
get()とset()を両方実装しておけば基本的にはそう言う問題は起きない気がするんだけど。
>>94 あらかじめ共通の操作を行うメンバ関数をprotectedで用意しておく。
クラス作った人が意図してないのに勝手に書き換えられたらprivateの意味が無い
>>95 全てのメンバ変数にget()とset()を定義するぐらいなら、OOPやめて構造体+非メンバ関数で書いた方がいい気がしてきます。
>>96 ,97
当初の予定にないことを、あとで拡張したいと思うこと自体が間違ってるんですかねぇ・・。
privateは駄目だろう private属性の要素を見直したいなら作り直せ、は それはそれで理にかなっていると思うが COMみたいに実装とインターフェイスを分離する方法もあるが。。
>>98 カプセル化ってそういうもんだろ。
内部実装に不用意に馴れ馴れしくすると、
もはやカプセル化の意味がない。
publicでゲッタとセッタがあっても、
裏にprivateなフィールドが存在するとは限らないんだから。
> 1つ方法としてfriendがありますが、あとで拡張したくなったときにpublicメンバだけじゃ無理! > というケースで元のクラスをいじらず拡張することができません。 それが可能になった場合、後で追加する場合には元のクラスをいじる必要はなくなるかもしれないが、 元のクラスの「実装」を変更したくなった場合に、追加したクラスに影響を与えることなく実現することが できなくなる。 C++ としては >96 じゃないかな。 「当初の予定にないことを、あとで拡張したい」時に今のままでできないなら、一旦構成含めて 考え直す必要があるんじゃね?
>「当初の予定にないことを、あとで拡張したい」時に今のままでできないなら、一旦構成含めて >考え直す必要があるんじゃね? これだからC++がダサいって言われるのですよね やはりRubyが最高・最強です
>>99-101 当初の予定にないことをあとで拡張しようとすることに無理があるようですね。
ありがとうございました。
Rubyはブロックをendで閉じるのがどうしようもなくダサい。
>>94 問題の一つとして、経験が足りないんじゃないのかな
何かプログラムを書いてたとして(得にライブラリ、フレームワークとか)、
将来、どこをカスタマイズするか、どこが不変的な部分かって
何度も同じプログラムを設計作り直しして、解ってくるもんだと思う。
rubyはwindowsのこと考えてくれないから嫌だ。
107 :
デフォルトの名無しさん :2009/01/02(金) 11:18:11
Boostなど外部ライブラリを使わず入力された文字列が "2008/01/02 00:00:00"という形式になっているか確かめる方法ありませんか?
APIや外部ライブラリを使わないなら、自分で書くしかないね
std::tr1::regex使えばできるんじゃねぇの?
それも外部ライブラリじゃないのか。
別に外部じゃない 現標準でもないけど
コンパイラがtr1に対応して無ければboostから引っ張ってくることになるのかな ところでtr1って名前空間はずっとstd::tr1なの?stdに将来的には移ったりする?
113 :
デフォルトの名無しさん :2009/01/02(金) 12:57:40
アドバイスありがとございます。 std::tr1:regexは何もインストールしなくても使えるんですね。試してみます。
114 :
デフォルトの名無しさん :2009/01/02(金) 13:19:20
vectorって配列みたいな初期化方法ないんでしょうか? vector<int> vec = {88, 99, 1100}; みたいな。 vector<int> vec; vec.push_back(88); vec.push_back(99); vec.push_back(1100); とするしかないですか?
>>114 次期規格でそんな感じでできるようになるけど、現状では無理。
今のところは
static const int vec_def[] = { 88, 99, 1100 };
vector<int> vec(vec_def, vec_def + (sizeof vec_def / sizeof *vec_def));
みたいにするしかない。
>>112 http://en.wikipedia.org/wiki/C%2B%2B0x >> Various full and partial implementations of TR1 are currently
available using the namespace std::tr1. For C++0x they will be
moved to namespace std. However, as TR1 features are brought
into the C++0x standard library, they are upgraded where
appropriate with C++0x language features that were not available
in the initial TR1 version.
C++0x で std::tr1 は std に移行するが、初めのTR1と同じではないようだ。
アップグレードされると。
tr1 は所詮ドラフトだかんね。
名前空間を分けてるのはそういうことなのか。それを理解して使えばいいってことなのね
120 :
デフォルトの名無しさん :2009/01/02(金) 14:58:26
イテレータを指定して初期化してるだけ。 ポインタはランダムアクセスイテレータ。
> 第二引数は配列の先頭アドレスに要素数を足す??? それであってる。 sizeof <配列名>を関数の仮引数以外で使った場合は配列全体の大きさを返す。 ついでに俺の疑問だがsizeof(vec_def) / sizeof(vec_def[0])って書き方のほうが一般的じゃないの?
なんで[0]なの? for(;;)に対する、while(1)的な気持ち悪さがある。
>>123 これで正しいと思うよ。
配列に対して*vec_defの方がよっぽど気持ち悪い。
[0] はマジックナンバーの出現に気持ち悪さを禁じ得ない。
どちらも結局気持ち悪いことに変わりはない。 どちらも気持ち悪いのなら、マジックナンバーの無い方が良い。
>>124 いや、正しいのはわかってるが、なんで1や2じゃなくて0なの?
0なら確実にあるだろ
sizeof に括弧をつけるのは素人っぽく感じる。 型にはつける必要はあるが。
130 :
デフォルトの名無しさん :2009/01/02(金) 17:59:15
0は先頭だと十分理解できるだろ 数字なら何でもマジックナンバーとかいってんじゃねぇ
サイズ 0 の配列を作れない以上、 1 でも問題ないね(デリミタ用途として仕様で許可されている)。 というか、そもそも sizeof は値を評価しないので、 存在しない要素を指定しても特に問題はない。 先頭だと理解できると言うが、先頭である必然性は特にない。 そもそも C++ ではこのタイプの要素数取得法を使うのは時代遅れで、 テンプレートを利用したタイプの安全な要素数取得法を使った方が良い。
>>128 その理屈はおかしい。
sizeofの渡すときは実際にデリファレンスされないからなんでもいい。
それよか、0よりも-1のほうが先頭じゃね?
134 :
122 :2009/01/02(金) 18:39:51
いろいろ勉強になった。みなさんありがとうございました。
static_cast<int>(1 << (sizeof(int) * 8 - 1))が先頭なんじゃね?
つまんね
配列の添え字はsize_tなのだが
ptrdiff_t じゃね
boost::beginとend使えばいいんですよ。
>140 ptrdiff_t はポインタ間の減算結果の型じゃないの? 配列の添字については明確な記述が見つけられなかった。
143 :
デフォルトの名無しさん :2009/01/03(土) 12:17:48
ローカル関数でオブジェクト作るときは普通newで作って関数の終わりでdeleteしますか?それともMyClass obj;みたいに作ります?
>>142 x[n] は *(x + n) のシンタックスシュガーで、
ポインタ演算用の型は ptrdiff_t だから、
n は ptrdiff_t だな。
>>143 CreateXXXみたいにオブジェクトの作成を目的とした関数ならnewしてポインタで返す。
単に処理の結果を返すだけなら、オブジェクトをそのまま返す。
146 :
145 :2009/01/03(土) 12:31:03
ごめん勘違いしてた。 そのケースでnew/deleteを使うのはサイズが大きすぎてスタックじゃ無理なときとか? 基本的にはnew使う必要ないと思う。
C++はRAIIができるからfinallyがないという話なんですが、どうも納得できません。 後処理が必要なのはリソースの解放だけではないと思います。 たとえば、特定の処理を行うときだけ乱数種を固定したいという場合、 unsigned seed = Random::GetSeed(); try { Random::SetSeed(0); DoSomething(); } finally { Random::SetSeed(seed); } 上のように書くのが自然だと思いますが、C++的には「RandomSeedMemorizer」のような クラスを定義しなければならないということなのでしょうか?
そう。
クラス作っておけば使い回し利くだろ。 finally みたいなその場しのぎよりよっぽど良い。
RandomSeedMemorizerではダメな理由がわからない。 DoSomethingがrandom generatorを引数で受けるようにするというのもあると思うけど。
>>147 seedを固定できる乱数クラスを作る。
finallyのようなその場しのぎだと、記述忘れを起こしたりでバグの巣窟になる。。
確かに乱数なら乱数クラス作るのが一番だな。
まあ、ファイル操作なら
>>147 みたいなのが必要になるね。
え?要らないでしょ・・・
逐次的にファイルを読んでる時に 一時的にファイルの途中を読みたいときに使うでしょ。
>>154 seek位置を保存再生するクラスを作れば?
それFilePointerMemorizerでいいのでは
>>148-150 やっぱりそうなんですね。
ただ、このような単純な処理までもクラスに分割してしまうことで、却って処理の流れが
不透明になるような気もするんですが、そういう議論はないのでしょうか。
>>151 それはRandomSeedMemorizerとは違うんですよね?
固定解除のタイミングが良くわからないんですが、たとえばどういうコードになりますか?
>>155 それがまさに RandomSeedMemorizer と同じような処理だろ・・・。
慣れの問題な気がするナー finallyはクラスつくんなくていいけど 対応を目でイチイチ追わないといかんのがちょっと・・・
>>157 そもそも流れにはあまり固執する必要は無い。
161 :
147 :2009/01/03(土) 13:41:13
>>159-160 なるほど。クラスの粒度に関する考え方の問題に似ているように思います。
ある意味、C++は小クラス主義を強制する言語なのかもしれないですね……。
どちらかと言うと、C++はなにも強制しない言語なんだが。
163 :
147 :2009/01/03(土) 17:54:38
>>162 でも、委員会にはfinallyを標準化する意志はないみたいですよね。
無名関数であるlambdaを入れられるくらいなら、無名デストラクタであるfinallyを
入れられない理由はないと思うんですが、思想的なものが影響してるのかと思ったり。
JavaにもC#にもDにもfinallyがあるのに、C++にだけはないなんて。
他にあるから入れる、というのはあんまりな・・・
つか、ここでボヤいててもしょうがないと思うが。
いやこのスレには割とC++0x標準化委員会のメンバーがいたりする
finally がどうしても必要なのはガベコレがあるからであって、 ガベコレのない C++ はデストラクタに頼ったので良い、という考え方なのだろう。
lambdaがあればDのscope(exit)みたいなものを実装できないか finallyはしらね struct scope_exit_impl { scope_exit_impl(std::reference_closure<void ()> const& f):f(f){} ~scope_exit_impl(){f();} std::reference_closure<void ()> f; }; #define scope_exit(hoge) scope_exit_impl guard([&](){ hoge }) scope_exit( 後始末() );
finally使うと処理がユーザコード側に分散するからなあ
やろうと思えばローカルクラス使ってこんなのはできる めんどくさいけどな void func() { class finally{ ~finally(){ //...後始末 } } finally_; try{ //...なんかする }catch(...){ //...万が一に備えて } }
こんな感じとかか。 まずやらんが。 void func() { { struct local_t { local_t() : a(1) { } ~local_t() { // finally std::cout << a << std::endl; } int a; } local; try { throw std::exception(); local.a = 2; } catch (...) { } // ここには何も書かない } std::cout << "end" << std::endl; }
172 :
147 :2009/01/03(土) 19:16:47
>>167 DにはGCがありますが、C++のようなRAIIとfinallyの両方をサポートしています。
理想論はともかく、現実的にはやはり両方あった方が便利ということかと。
>>170-171 そういう方法があるのは一応知ってますが、推奨される書き方ではないですよね。
ここで質問したのは、C++にfinallyがなくても大丈夫な理由を説明してくれる人が
いるかと思ったからなのですが、やたら小さいクラスは作りたくないしトリッキーな
方法も使いたくない、だけど例外のメカニズムは使いたいという要求に応える回答は
今のところないようです。
まーな。ここの連中レベル低いし。
いや、GC ないから RAII が必ず動く事が保証されるので RAII で大丈夫、ちうのが回答なわけだが。
>>174 GCあっても、RAIIが動かなくなるなんてことはない。
この二つは直行概念だよ。
まあ、C# の using や D の scope みたいなのを使えば動くからね。 でも、こいつらって finally が導入された後に導入されたんじゃね?
GC管理オブジェクトをRAIIすることはできないんだってば ファイナライザは不確かすぎてリソースの確実な開放のような重要な仕事を任せることは出来ない だからfinallyが必要になる 逆にRAIIしたいオブジェクトはGCの管理から外れてないといけない というか後始末はプログラマの仕事になるから任せるわけにはいかない その区別のためにDではscopeなんていう予約語があるし C++/CLIではポインタとハンドルを分けてる
>>176 Dのscopeはクラス(参照型)でRAIIを実現するためのキーワード。
(もちろん、finallyのシンタックスシュガーとも言える)
Dでも構造体(値型)をスタックに確保すれば、C++のクラス(値型)と同様のRAIIを使える。
>>176 C#は1.0の最初からusingを持っている。
一般的にはusingが推奨されているし、実際コーディングしていてもfinallyなんて滅多に使わない。
>>179 そうなのか。
ま、やっぱり finally は GC 使っちゃった場合の
苦肉の策でしかないわな。
>>172 「やたら小さいクラスは作りたくない」
この主観が邪魔してるだけだろ。
小さいクラスを作ってもたいしたデメリットは無いだろうし、あったとしても
同じ後始末処理を使いまわせるメリットに勝ることはないだろう。
auto_ptr は小さいクラスだが、コレ使わずに finally 使えとか言われたら死ねる。
RAII クラスは関数と同じくらいの気軽さで作って良い。
>>177 それがfinallyである必要はない。
DのscopeやC#のusing、C++/CLIの(参照クラスの)デストラクタのように、
GC付き言語でfinallyよりC++のデストラクタに近いものはいくらでもある。
>>183 DやC#やC++/CLIはGC付き言語だけど
そこで挙げてるようなのはGCの管理外だぞ
だからC++のデストラクタに近いものなのは当たり前だし、GCとは別に用意されてるんだ
わかってる?大丈夫?
もっと議論読んでくれよ・・・
>>184 C#やDなどの場合、finallyとusing/scopeはお互い等価に変換できるシンタックスシュガーの関係。
using/scopeも後始末用のメソッドを呼ぶだけで、インスタンス自体のメモリの解放はGC任せ。
「だからfinallyが必要になる」って書いているけど、
本当に必要なのはfinallyそのものではなく「確実に後処理を行える機構」。
finallyはそのための手段の1つでしかない。もちろんusingやscopeもその手段に該当する。
まあ、特に finally とか必要ないと思う。 finally でハードコーディングするよりゃRAII 使え。
もちろん、今時のコンパイラなら実装されている。 でないとstd::operator <<とかstd::operator +とかstd::basic_stringなどが死ねる。 引数が複数ある場合も規格には載っている。 ただ、規格通りに実装されているかというと、怪しいコンパイラがちらほらあったと思う。
俺が使っているオレオレコンパイラは対応してないな
レスありがとうございます。 引数が複数ある時の挙動には注意が必要なんですね。
引数が複数ある場合よりも、テンプレートで予期せぬ名前空間まで探索されることに気を付けろ。
>>192 template <class T>
void Hoge(T t){
F(t);
}
こういう事ですか?
194 :
147 :2009/01/03(土) 23:00:39
>>181 auto_ptrのように標準で用意されているクラスを使えばそれでよしというのなら
まだ納得できるのですが、自分で小さいクラスを書かなければいけないとなると、
やはり小クラス主義の思想を強制されているように感じてしまいます。
RAII方式のデメリットといえば、
(1) 一つの関数内だけでシンプルに記述できない
(2) finallyで書いた場合よりも行数が増える
(3) クラスの名前を考えなければならない
(4) 後処理の実装を再確認するときにも一手間増える
(5) クラスを定義するために別の場所に移動するとき一瞬思考が途切れる
などでしょうか。
これらを差し引いてもメリットが上回ると心の底から納得することができれば、
面倒な思いをしなくても済むのでしょうけれど……。
(2) finallyで書いた場合よりも行数が増える 使い回せばむしろ減る。
196 :
147 :2009/01/03(土) 23:04:08
>>195 使い回せばと言いますけど、1回しか出現しないような処理も結構あるわけですよ。
スコープはずれた時にコンストラクタ引数で渡した関数を呼び出すようなクラスを用意しとけば使い回せるじゃん。 C++0x で lambda が書けるようになれば↑と組み合わせてほとんど解決されるんじゃね? lambda って言っても実質ローカルクラスなんだけどさ。
OOPの理想の最終形態は自分でクラスを作らない、具体的な実装を知る必要もない というところにいくので1-5はデメリットにならない。
小クラス主義って何だ?大クラス主義もあるのか? クラスというのは機能の単位だ 長い関数が悪であるのと同じように、何でもかんでも詰め込んだ巨大クラスも悪だし、 そういうクラスは適切に分割するのがOOPの基本 それを小クラス主義と呼ぶのなら的外れだし、大クラス主義とやらはただのヘタな設計だ
ローカルクラスにはしないけど、 ファイルローカルなクラスにすることはあるね。
>>194-197 >170-171 の方法を知ってれば (1),(4),(5) みたいなのがデメリットは無いだろ。
ついでに (3) もわりとどうでも良くなる。
(2) については 195 の言うとおりで、「1回しか出現しない」のが「結構ある」なんてのは、
似たような処理を関数にまとめられないのと同じで下手なだけでしょ。
今気が付いたんだけどスレのテンプレがpart63を最後になくなってる。 次スレでは復活させたいな。
リソースの構築と後始末の処理という大がかりで複雑で重要な仕事に クラスを1つ割り当てることを「小クラス主義」というのは正直理解しがたい 147にとってクラスとは何なんだ
204 :
147 :2009/01/03(土) 23:59:57
>>197 >>201 今でもマクロなどを使って強引に書けなくもないですし、finallyに非公式対応している
C++コンパイラもあるので、標準など気にせず使ってしまうという選択もありますね。
>>203 個人的な考えでは、RAIIがあるからfinallyは要らないという理屈は、もともとメモリや
ファイル等のわかりやすい例しか考えていなかったのではないかと想像しています。
ですが現実には、リソースに一対一で対応していない、もっと抽象的なものを保存して
おきたい場合もあるわけですよね。乱数種やファイルポインタもそうですし、標準出力の
フォーマットとか、クラス内部の一時的なモード設定等。
そういったものもすべてデストラクタで処理するべしというのが最近の風潮のようですが、
C++の設計者が最初からそういう意図だったのかは結構疑問な部分があります。
思ったんだけど、>147の例がおかしくね? 普通はseedも含めてrandomクラスにするんじゃないの? boost::randomみたいに。 seedだけ入れ替えたりするからこんな格好悪い操作が必要になると思うんだけど。 グローバル的なものを使うのならfinallyみたいなグローバルな仕組みがあると便利そうだけど、 それはかなりC的な使い方だよね。
>204 C++にとって、リソースの所有権をハッキリさせることは非常に重要だよ。 普通はインスタンスが所有するから、RAIIで管理するのは自然なことだよ。 複数のインスタンスで管理するならshared_ptrだし、プログラム全体で管理するならSingleton/Multitonじゃない?
207 :
147 :2009/01/04(日) 00:20:25
>>205 そうですね。C的な設計のライブラリを使う場合などに特に問題になります。
うまく設計することで、後始末処理が必要になるケース自体を減らすことは可能では
あると思います。
>>206 リソース自体をRAIIで管理することには全く反対していないですよ。
>>204 わからんなぁ……
問題はリソースに対応してるかどうかは関係なく、後処理が必要かどうかだろ?
そしてデストラクタは間違いなくリソース後処理のための機能に違いない
何か不満があるのか
「RAIIがあるからfinallyは要らない」というのも順番が違うよなぁ
JavaにC++的なデストラクタがないがためにRAIIが出来ないから
代わりに導入されたのがfinallyという機能じゃないの?
リソース以外に挙げてる例が全部使いまわしの効くものなんで、 >196 が口からでまかせにしか見えない。
C++にfinallyを採用しない理由を禿に聞いたら多分こんな答えが返ってくると思う
・新しい機能を提供しない
必要になれば
>>170-171 の方法で同じ機能のものをいつでも作ることが出来る
・必要とされる機会が少ない
RAIIを適切に行っていれば、finallyが必要になることはほとんど(あるいは全く)ない
・よくないコーディングスタイルを推奨する
「使った後はfinallyで○○を始末してね」のようなクラス設計が行われるようになるおそれがある
言うまでもなく危険だし、RAIIの利点が全く殺されてしまう
RAIIのデストラクタでは出来ない何か大きな利点がないと、禿を説得するのは難しかろう
次々規格でGC導入考えるらしいから遙か未来にはどうなってるかわからんけどね
>207 リソース解放以外にfinallyが必要になるケースはあまり無いような気がするけど…… 「一時的な設定変更」も、そもそもそういうことが必要になること自体が良くない設計じゃない?
つーか、なんでJavaにはデストラクタないんだ コンストラクタだけって、そっちのほうがよくわからん
GC に任せっきりだからさ
破棄処理のタイミングとメモリ解放のタイミングは別々でいいのに、 ごっちゃにしちゃったのがまずいんだろうね。 C++ のデストラクタと Java とかの GC との組み合わせが実現すると良いんだろうなぁ。
218 :
147 :2009/01/04(日) 01:00:25
この疑問を持ったのは、とあるフリーソフトのソースを読んで、一時的な状態を保存して デストラクタで復帰させるだけのクラスが大量にあるのに気づいたからなのです。 で、それらのクラスの多くは1回か2回くらいしか使われていなかったりするわけです。 もしC++の標準機能にfinallyがあれば、このコードはずいぶんシンプルに書き直すことが できるだろうなあと感じました。(ソフトの具体名は差し控えさせてください) 多分「設計が悪い」という意見が一番的を射ているのだろうと思います。かといって 変なトリックを使わない前提でどう直したら良いのかはわかりませんけれど……。 皆さんたくさんのレスありがとう。これにて引っ込みます。
>>170-171 の方法で、と言うが、f1のように使えない限り
とても代わりに使えるレベルとは言い難いが。
また、仮にf1が通っても、可読性は損なわれているように見える。
struct file_t{
void open();
void close();
};
void f0()
{
file_t file;
try{ file.open(); }
catch(...){}
finally{ file.close(); }
}
void f1()
{
file_t file;
struct finally_t{
~finally_t(){ file.close(); } // error C2326
} finally_;
try{ file.open(); }
catch(...){}
}
>>212 Direct3DとかBegin()とEnd()がチラホラあるライブラリでも必要
>218 そういうのだったら関数オブジェクト使った方がスマートだよな。 まあ、一時的に値を変更してまた復帰させなきゃいけないというのはけっこう危険だから、 新しくインスタンス拵えてそっちを使う方が良いと思うけど。
こんなfinalというクラスを作れば #include<functional> class final{ std::function<void()>value; public: template<typename T> final(T value):value(value){} ~final(){value();} private: final(const final&);final&operator=(const final&); }; これだけで出来たぜ!(C++0xです) file_t file; file.open(); final f=[&]{file.close();}; まぁfileのcloseなんて100人いたら100人ともRAIIでやるがな
>>219 そんなときはf1を丸ごとクラスにするという手がある
struct f1{
file_t file;
f1(){
struct finally_t{
~finally_t(){ file.close(); }
} finally_;
try{ file.open(); }
catch(...){}
}
};
ごめんおかしかった
>>222 function のコンストラクタで bad_alloc が投げられると漏れるな。
一応言っておくけどファイルクローズは失敗する可能性があるからRAII厳禁だぞ
>>225 ああ、たしかに考えてなかった。
正しくはこうか。
template<typename T>
final(T value)try :value(value)
{}
catch(...){value();throw;}
>>226 無視していいという状況ではRAIIで任せても問題ない。
使い方として、無視してよい場合と駄目な場合の両方が考えられるなら、
fstreamみたいにcloseとデストラクタの両方を用意すればよい。
ああ、コンストラクタでの例外は、
throwを書かなくても再送されるからthrowを書く必要は無かった。
>>226 ぶっちゃけファイルクローズが失敗するような
末期的な状態になったらどうしようもなくね?
>>226 fstream だと、デストラクタで fclose() させたときの失敗は報告されないことになっている
ものの、いちおう RAII には従ってる。
RAII 禁止じゃなくて、使う側で RAII まかせにしちゃいけない、の間違いじゃない?
ぶっちゃけ close で失敗した所で何をすればいいのん?
末期的でなくても失敗するよ ネットワークドライブ上のファイル扱ってる間に回線切れたとかな ファイルクローズ失敗を無視して良い状況というのはほとんどない RAIIはファイルに使ってはいけない
>>227 T のコピーで例外がスローされるかもしれないから、まだもうちょっと危険な感じ。
ここで引数を reference_closure に限定するといいらしい。
>>231 エラーログに書き込んでから、復旧不能なエラーだったら諦めて無視するかプログラムを落とす
そうでなかったら成功するまでcloseを試みる
どうしてもダメならタイムアウトしてOSに通知する
closeの仕事が本筋の処理が中断するとまずいようならcloseを繰り返すためのスレッドを作る
こんなところか
>>233 むー例外安全とは難しいなぁ。
個人的には、const T&とT&,T&&辺りを気合でゴリゴリ書いて、
関数オブジェクトにも対応させたいなぁ。
でもreference_closureに限定させたほうが楽そうだな。
>>232 了解です。確かにRAIIじゃ不完全ですね
>>234 なるほど・・・。
まあ、そのあたりをデストラクタで(例外を一切発生させずに)行えばいいという気もしなくもない。
スレッド使う場合は、ワーカスレッドを事前に用意しておく必要があるけども。
>>231 デストラクタの外で close() して、普通に例外投げりゃいいんだよ。
ファイルを管理する singleton の大ボスを作っておけばいいんだよ。 デストラクタで close に失敗したら、そいつに管理を委譲する、と。
>>231 それが出力ファイルの close なら失敗した旨をユーザーに通知する必要があるだろ。
std::fstreamでもやっているとおり、 - 処理の最後にcloseを呼ばせるようにドキュメントしておく - デストラクタの実装では、closeされてなかったらcloseして、 もし例外が発生したら呑み込んでしまうことにする とするのが現実的な落としどころだと思われ。 正常系でcloseせずにデストラクタに行って例外が呑み込まれてしまったら それはユーザ側のコードが悪い。 異常系ではcloseが呼ばれずにデストラクタが直接呼ばれることもあるかもしれないが、 その場合closeが失敗するとアクティブな例外が同時に2つ存在することになるので いずれにせよどうにもならない。
想像してみたけどcloseが例外を投げることを考えた場合、 処理が冗談抜きで面倒だなぁ。 try,catch,finallyモデルを採用しても書くのがマジで面倒そう try{ file.open(); file.close(); 例外飛ぶから無理 }finally{ try{ file.close(); }catch{ //どうする? //例外の再送は2重に例外投げるかもしれないから出来ない! } } これでも面倒だけどC++にはfinallyないからRAIIで書くはめになってさらに面倒 俺はこんな面倒なことになるなら、closeは例外投げない! という前提でクラスを設計したくなってくる。 例外を投げれる柔軟性なんかいらんわー。
>>241 closeは例外投げるがデストラクタは投げないとすれば、基本的には問題ない
243 :
デフォルトの名無しさん :2009/01/04(日) 09:44:42
でもどっかにエラーださないと win32のデバイスコンテキストまわりぐれーに開放されてるのかされてないのかわからない状態になるな でも個人的にはスルー(笑)
デストラクタで例外投げたらどんな動きになるん?
別にそれ自体はなんともならん、普通のメンバ関数で投げたときと一緒 でもそのクラスの配列作って delete [] したときとかに複数要素が例外投げてくれると、アウトだろ?
ごめん流れ読めてないね ほんとごめん
配列 delete じゃなくてもアウトだよ。 デストラクタはメモリの開放前に呼ばれるわけだから、 デストラクタで例外投げられたらメモリリークする。
それは違うだろー、自身のこといってるならそれは解放されるし、メンバのことだったらそれは単に書き方の問題だろう まぁアウトなのが配列のときだけではないのはそりゃそうだが
俺はデストラクタで例外が発生する場合は 自前で処理できる分を処理して再送してるな。
デストラクタで例外を投げたら、基本クラスのデストラクタはどうなるのとか、例外の巻き戻し中だったらどうなるのとか悩む
例外がスローされ、ローカル変数がデストラクトされる過程でまた例外が起きたら terminateが呼ばれてあぼーんだべ
デストラクタで例外投げないようにすればRAIIでもOKだよ、って
その持っていき方がそもそもおかしい。
>closeは例外投げるがデストラクタは投げないとすれば、基本的には問題ない
それが出来るんなら、closeでも例外なんて投げないよ
>>228 ,230
だから結局、ファイルクローズはRAIIでやんの禁止なんだろ。
例外巻き戻し中のfinallyで例外投げたらどうなるの
ああ、catch でさらに throw された状態で さらに finally で throw された時のことか。 誤解してた。 どうなんだろ。俺は知らん。
>>255 Javaの話なら、catchで投げた例外は消滅する
>257 それじゃ例外安全にはならないね。RAIIとあんまり変わらないな。 こういうのはGC組んだ方が良さそうだね。 close()が成功する or 失敗したときの後処理が終了するまでdeleteされないようにするとか。 後でアクセスできるように>238みたいな仕組みも必要か……
C++ だとスタック巻き戻し中に デストラクタで例外投げられたら std::terminate が呼ばれてシボンヌ
>>252 >>closeは例外投げるがデストラクタは投げないとすれば、基本的には問題ない
> それが出来るんなら、closeでも例外なんて投げないよ
なんで出来ないと思うの?
こういう実装でいいと思うんだ。 int close_file(file_t); //失敗時は非0を返す。 class file { public: close() { int error = close_file(f) f = 0; if (error) throw file_exception(error); } ~file() { if (!f) close_file(f); } private: file_t f; }; 閉じるときの例外を無視してはならないという主張は全面的に同意だけど、 それ以外の操作で例外が投げられたときは、とりあえずファイルを閉じてリークを防ぐべきだと思う。 あと、読み取りだけの場合は、書き込んだときほどcloseに慎重になる必要はないのでは?
たとえばpod64<int>::typeと書けば64bit int型になるようなテンプレートを書こうと思い、以下のようなテストプログラムを組みました。 #include <iostream> template <typename _Pod,bool _Is64=(sizeof(_Pod)>=8) > struct pod64{ typedef _Pod type; }; template <typename _Pod> struct pod64<_Pod,false>{ typedef long _Pod type; // ※ }; int main(void){ pod64<unsigned int>::type l = 10; std::cout << l << std::endl; std::cout << sizeof(l) << std::endl; return 0; } ネーミングが正しくないのは承知で、charとかvoidとかshortとか入れると発狂されるのも承知の上で、 pod型を入れると64bitより小さければlongで修飾するように書いたつもりだったのですが、コンパイルが通りませぬ。 ※の行でtypeが型として認識されないようです。 なんとなくそれは当たり前だなあとはわかるのですが、かわりにどのように記述すればいいのかよくわかりません。 どのように書くのが正しいのでしょうか。
>>262 template<typename T> struct add_long;
template struct add_long<int> { typedef long int type; };
template struct add_long<long int> { typedef long long int type; };
って感じで、特殊化を全部並べとけばいいんじゃね?
typedef typename long _Pod type; テンプレート中で型名を使う時はtypenameが必要
266 :
262 :2009/01/04(日) 23:02:45
>>263 うえーん(´・ω・`)
>>264 やっぱりそうするしかないんでしょうか。。。
>>265 そういう問題ではないようです。
というのも、longをconstにしたらtypename無しで問題なくコンパイルされ、
というかむしろtypenameを付けるとコンパイルが通らなくなり、
longのままだとtypenameがあっても無くてもコンパイルが通らないので。
純粋にlongがconstのような修飾子とは判断されないということだと思います。
>>263 の方法が一番現実的かつ正確な気がしてきました。
long long long long とかつないで行ったときに92bitとか128bitになる環境だったら名前が正しくないのも気持ち悪かったので、
>>263 の方法でいってみます。ありがとうございました。
267 :
デフォルトの名無しさん :2009/01/04(日) 23:18:28
>>266 typename は本来必要な箇所になくても通るコンパイラがあるから、
あんまり通った通らないはあてにしない方がいい
long int でひとつの型なんだろ longはconstのような修飾子じゃないんでしょ そういうのやりたきゃプリプロセッサでやるこった
long は型指定子(type-specifier)で const は cv-修飾子(cv-qualifier)だな。 specifier と qualifier のニュアンスの違いはよく分からんが。
とりあえず dependent name じゃないから typename は付けられない。 型に対する演算がしたいなら基本は >264。 boost::mpl 使えば多少は省力化できるかも。 template<typename Pod> class pod64 { typedef boost::mpl::map< boost::mpl::pair<int,long int>, boost::mpl::pair<long int,long long int>, boost::mpl::pair<long long int,long long int> /* 必要なだけ追加 */ > TypeMap; public: typedef typename boost::mpl::at<TypeMap, Pod, void>::type type; }
すみません、ちょっと質問です。 テンプレートコンストラクタでテンプレート引数を指定してコンストラクトするにはどうしたらいいんでしょうか? struct A { template<typename T> A() {}; template<typename T> A(T t) {}; } A a0(1); //OK A a1; //error わざわざ使わない実引数を指定しなきゃいけないのかな……
struct A { //template<typename T> A() {}; template<typename T> A(T t) {}; };
>>271 template <typename T> struct Type { };
struct A {
template <typename T> A(Type<T>) { ... }
};
A a(Type<int>());
最適化で Type オブジェクトの引き渡しは消えるはず。
274 :
271 :2009/01/06(火) 00:17:30
サンクスです。 >272 class A { public: template<class T> A() : a_(a<T>()) {}; private: unsigned int& a_; template<class base_t> static unsigned int& a() { static unsigned int r(0); return r; }; }; というのをやりたいので、それだとNGですね。 >273 やっぱりType2Type使うのが妥当ですかね。
276 :
271 :2009/01/06(火) 01:00:17
>275 つまりは型の種類ごとに挙動を変えたい(rの値を変更する)ということですね。 class B {}; class C {}; A ab0(B()); A ac0(C()); A ab1(B()); みたいにしたときに、ab0とab1の挙動を共通にしたいということです。 ……まあ、MC++D参考にマルチディスパッチをこしらえているだけですけどね。
派生クラスによって、 色々な型の返却値、引数のメンバ関数を持たせることの出来る 基本クラス、派生クラスを作成したいのですが、 よい手を教えてください。 具体的には派生クラスによって、メンバ関数funcが、 o intの引数を2つ取り、引数の足し算の結果を返却する o doubleの引数を2つ取り、大きい方の値を返却する o doubleの引数を1つ取り、cos(引数)の結果を返却する というようなバリエーションがとれるような派生クラスに したいのです。 お願いします
それメンバ関数である必要ないじゃん グローバル関数にして関数ポインタ使い回すか 関数オブジェクトにして使い回すかでいいんじゃね
>>277 やりたいように書けばそれで問題ないように見えるんだけど、
ためしに書いてみたコードでも晒してみてくれまいか。
struct T { enum { value = 1, } static T *create(); typedef T *iterator; }; void f() { T *p = p->create(); // OK int n = p->value; // OK - std::string::nposとか長いんだよ p->iterator it = p; // NG - autoだけ先行導入しろよ }
281 :
277 :2009/01/06(火) 13:25:47
すいません。説明不足なのでつけたします。
やりたいことは、派生クラスを基本クラスにアップキャストして
vectorなどに保存しておいて、
vectorの先頭から、派生クラスとしてメンバ関数を実行する
というようなことをやりたいのです。
実行側からすると、どのような関数かはvector内を見るまで
わからないけど関数に合せて実行したいということになります。
>>278 メンバ関数にこだわる理由は特にないのですが、
任意の返却型、引数型を表わせる関数ポインタというのがあるなら、
それを使えそうな気がします。
>>279 今は時間がとれないので夜晒します
>>281 boost::function の出番だな。
あとは、 vector を操作しながらそれぞれの関数を呼び出すところで
引数をどう渡すつもりなのかによる。
283 :
277 :2009/01/07(水) 00:22:33
#include <iostream> #include <vector> using namespace std; int op_plus(int x, int y) { return x + y; } double op_cos(double x) { return x; } template <class TRet, class TArg> class Op { protected: int arg_num; vector<TArg> args; TRet result; public: Op(int n) : arg_num(n) { } virtual void exec(); void add_arg(TArg arg) { args.push_back(arg); } };
284 :
277 :2009/01/07(水) 00:22:49
class Plus : public Op<int, int> { public: void exec() { result = op_plus(args[0], args[1]); } }; class Cos : public Op<double, double> { public: void exec() { result = op_cos(args[0]); } }; int main(int ac, char *av[]) { vector<Op<int, int> > vec; return 0; }
285 :
277 :2009/01/07(水) 00:29:07
関数ポインタは難しかったので、
virtual void exec();の関数内で、
派生クラス毎に任意の関数を呼ぶようにして、
テンプレート使ってみたのですが、
main()内のvectorを作る時点で、Opの型を決める
必要があるようで、
>>281 の意図していたものにはなりませんでした。
main()からは、1種類のクラスとしてvectorで扱いたいのですが、
アイデアがないというところです。
286 :
277 :2009/01/07(水) 01:39:52
>>282 引数の渡し方は、vector内の隣りで
実行完了したクラスの返却値をもらうとか、
クラスのメンバに登録してから、実行するのでもいいです。
boostについても調べてみたのですが、std::mem_funすら
わかっていないのでかなり敷居が高そうです。
性能も必要なので最悪、色々な種類の関数ポインタを
unionした構造体にしてしまうのがいさぎよい気もしてきました。
結局何がやりたいかよくわかんないんだけど funcのシグニチャは派生クラスごとにてんでバラバラなんだろ? そして引数はクラスの外から飛んでくるんだろ? だったら統一的に扱えるわけないじゃん vector<X> vec;//お目当てのvector for(vector<X>::iterator it = vec.begin(); it != vec.end(); ++it) { (*it).func( /* ここに何か書けるか? */); } 同じvectorに詰め込むのをやめて種類ごとのvectorを作った方がいいよ それが嫌ならenum値返すメンバ関数作るなりRTTI使うなりして 派生クラスごとにif文書いてそれぞれの処理を書くことだ どっちにしるfuncの名前は派生クラスごとに変えた方がいい
効率無視してanyとfunctionでやってみた。2個の引数はpairでまとめた。3個以上必要ならtuple使えばいい。 あと、execからoperator ()にした。Cosはただの関数でも可能という例。 この例では、関数オブジェクトの戻り値型を実際の物にしたが、anyでも可。 #include <iostream> #include <vector> #include <utility> #include <functional> #include <cmath> #include <boost/function.hpp> #include <boost/any.hpp> using boost::any; using boost::any_cast; int op_plus(int x, int y) {return x + y;} double op_cos(double x) {return std::cos(x);} struct Plus : std::unary_function<any const&, int> { int operator ()(any const& arg) const { std::pair<int, int> arg_pair = any_cast<std::pair<int, int> >(arg); return op_plus(arg_pair.first, arg_pair.second); } }; double Cos(any const& arg) { return op_cos(any_cast<double>(arg)); }; int main() { std::vector<boost::function<any (any const&)> > vec; vec.push_back(Plus()); vec.push_back(Cos); std::cout << "1 + 2 = " << any_cast<int>(vec[0](std::pair<int, int>(1, 2))) << '\n'; double ret = any_cast<double>(vec[1](0.0)); std::cout << "cos(0) = " << ret << std::endl; return 0; }
>>286 「〜とか〜でもいいです」なんて言われたら考えるのがあほらしい。
どうせ後出しの条件付けで「そうじゃないんです」って言われるに決まってる。
やっぱboostきめぇな
>>286 >vector内の隣りで実行完了したクラスの返却値をもらう
なんだ、隣のCosが返したdouble値を、Plusの自分の引数に渡してもいいんだ
じゃint維持にこだわる意味ないから、引数と戻り値の型を全部doubleにして
execを普通の仮想関数として書けば完全解決だな
よかったよかった
後からダメとか言うなよ
お前がよいですって言ってるんだからよいんだよな
よくよく考えて隣から返り値もらってもいいって書いたんだから間違いはないよな?
292 :
277 :2009/01/08(木) 00:00:44
>>288 ありがとうございます。
参考にして考えてみます。
>>287 1次元配列中でランダムに選ばれたセルでその近傍のセルの
情報を元に計算しなくてはいけないので、
vectorは分けれないのです。
>>289 ,291
自分でも要件がまとまっていない部分があって
変な質問になり、混乱させてしまい申しわけないです。
BCC5.5でテンプレートを使った参照除去をやりたいんですが、通りません。あきらめるしかないのか? template<typename T> struct remove_refference{ typedef T type; }; template<typename T> struct remove_refference<T&>{ typedef T type; };
ほかのコンパイラを使えばいいじゃない。
BCC5.5みたいなウンコンパイラを未だに使っている時点でアウト
>>293 BCC6.1.0なら通る
コンパイラが古い
g++でいいのに Windowsで開発してる時点で負け組
g++も古いバージョンはテンプレート悲惨だっただろ
>>299 いやlinux
マカーの椰子はオブCマンセーなんかな
>>298 暗黒時代については文献も記憶もない
g++はC++0x対応が遅そうなのが気がかり
VC++切り捨てVC#のみサポートとかいう時代がきて大差なくなったり
ネイティブを切り捨てるわけが無い
文字列(std::string)の内容が数字だけ([0-9]+)であることを判別したい。 最も短く書ける方法は何でしょうか? BoostでもOK。
つ[strspn()]
strtolで返り値捨てて末尾の中身が'\0'かを見る程度で充分じゃないの。
数字だけであることを判定するのと、longに変換してみるのは結果が違うと思う。 >306がどっちを要求しているか、だな。
311 :
306 :2009/01/09(金) 13:53:46
>>307 std::strspn(s.c_str(), "0123456789") == s.size()
こうですか。なるほど。
strtolだと符号の判別等を無視してもこれより長いっぽいです。
std::tr1::regex r("[0-9]+"); std::cout << (std::tr1::regex_match(str, r) ? "数字だけ" : "数字以外") << std::endl;
だったら、一時バッファ1個使うだけの sscanf(str.c_str, "%20[^0-9]", buf) == 0 とかでも充分じゃないかな。 ↑は正しく動くか知らんけど。
ていうかやっぱstrcspnの方が短くて楽だよな。 速度を求めるならisdigitでループだろうが。
>>311 size == 0 の時も考慮に入れようぜ
別の場所で class hoge{〜〜} って感じで定義されてるとして class hoge* x と hoge* x って同じだよね?
同じ ついでにstruct hoge* x;でもunion hoge* x;でも同じ
fgetsは処理ごとにメモリが動くので、一様な使い方ができません。 どのように切り抜けるか知っていますか。下記例。 #include<stdio.h> int main(){ FILE *fp; char a[256]; char *b[4]; char *c,*d; int i; if((fp=fopen("address.dat","r"))==NULL)exit(1); c=fgets(a,256,fp); printf("%s",c); d=fgets(a,256,fp); printf("%s",d); fclose(fp); } これを c=fgets(a,256,fp); d=fgets(a,256,fp); printf("%s",d); printf("%s",c); のような順序にすると同じ値が出てしまいます。(1行目が消えて、ファイルの2行目の出力になる)
いったい何を切り抜けたいのかわからない・・・・
そもそもaに格納してんじゃねーのかよ c=fgets(a,256,fp); d=fgets(a,256,fp); printf("%s",d); printf("%s",c); ってやったら2回目のfgetsでaに入った値になるんじゃね? 格納場所はaなんだぜ
アドレスはa==c==dだからな そりゃあaが変わればcもdも一緒に変わりますよと。
323 :
デフォルトの名無しさん :2009/01/11(日) 02:20:02
質問します。 クラスAのインスタンスを配列で1000個生成するのですが、 クラスAに、メンバ変数だけが含まれるのなら、 メモリ上には、メンバ変数×1000個のサイズの領域がほぼ確保されると思うのですが、 クラスAに、メンバ変数とメンバ関数が含まれる場合、 メモリ上には、メンバ変数×1000個+メンバ関数×1000個のサイズの領域が確保されてしまうのでしょうか? それとも、メンバ関数は共通だから、メンバ変数×1000個+メンバ関数×1個のサイズの領域の確保で済むのですか? 教えてください。
メンバ関数はインスタンスが保持するものではない。 メンバ関数はインスタンスを作らずとも存在し、常に1個だけ存在する。 ただし、仮想関数を作った場合、 各インスタンスは仮想関数テーブルと呼ばれるものへのポインタを持つ場合が多く、 その場合はポインタの分だけサイズが増える。
325 :
323 :2009/01/11(日) 02:34:01
>>324 ありがとうございました。迷ってしまいまして。すっきりしました。
326 :
うどん :2009/01/11(日) 08:49:54
こんにちは、最近C言語と言うものに興味をもって始めようと考えていたのですが 「苦しんで覚えるC言語」というサイトを参照したところ始めるにあたって 「Borland C++ Compiler」という物が必要らしく 使うには登録も 必要だったので登録しました。しかしDL画面から何度試みてもDLできなくて 始める前からいきなりの壁にぶつかっていますorz どなたか解決方法が分かる方がいましたら 教えて頂けないでしょうか? スレのお題からは離れている気もしますが宜しくお願いしますm(_ _)m
>>327 お早お返事ありがとうございます!
このページには教えていただく前に何度かたどり着いたのですが
このページのどのあたりからDLするかわからずに困っていました
厚かましいお願いなのですがそのあたりも教えていただけると
感謝の極みです。
>>328 分かったからもうこっちにはもどってこなくていいよ
333 :
271 :2009/01/11(日) 17:07:20
初心者にBC++勧めるのはどうなのかね。 とりあえずVC++の無料版使って、本腰入れてアプリとか作るようになったら有料版にするのが 一番お手軽かね。興味あったらググッて調べなさい >326 個人的にはKNOPPIXでgcc使うのが勉強になりそうな気もするけど。
Cだったろ?
VCから入るとほかで使えない人になっちゃうのがそれなりにいるからあんまり勧めたくない。
336 :
デフォルトの名無しさん :2009/01/11(日) 17:46:33
vcのIDEが使えない人もどうかと
makefileの書式とか忘れてるわ。 修正はたまにするけど新規で書けないな。
それ俺だ >335 自分でmakefileとか拵える気にならない…… boost jamとかどうなのかな?
俺はmakefileの方が楽だな IDEはうまくいってるときはいいけど、トラブルがあった場合何もできない
IDEだって独自形式のmakefileみたいなもんだ。 例えば、VC++のはvcbuildコマンドでビルドできるという具合。
>>333 BCもBCB最新版を公開すれば、初心者に勧められるんだけどね。そうすればそのまま製品に移行する人も出てくるんだと思うんだよね。
おまいら、g++忘れてるぞ
おまいら、dmcも忘れてるぞ
goto DMC;
キモ
346 :
デフォルトの名無しさん :2009/01/12(月) 20:57:51
申し訳ありません教えていただきたいです。環境はXPSP3 VC++2008です giveio.cを使わせていただいてgiveio.sysをインストールしたいのですが 0x7c812aeb で初回の例外が発生しました: 0x000006F4: NULL 参照ポインタがスタブに渡されました。 Run-Time Check Failure #2 - Stack around the variable 'fullpath' was corrupted. と言うエラーが出ます /* #define MAX_PATH 256 */ static DWORD DriverInstall(LPCTSTR lpFname,LPCTSTR lpDriver) { BOOL dwStatus = 0; SC_HANDLE hService = NULL; char *address; char fullpath[MAX_PATH]; /* connect to local service control manager */ if(OpenServiceControlManager()) return 1; /* get full path of driver file in current directry */ GetFullPathName(lpFname,MAX_PATH,fullpath,&address); ←ここのfullpathのようです /* add to service control manager's database */ if ((hService = CreateService(hSCMan, lpDriver, lpDriver, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, fullpath, NULL, NULL, NULL, NULL, NULL)) == NULL) dwStatus = GetLastError(); else CloseServiceHandle(hService); return dwStatus; } コメントアウトにてMAX_PATH 256とありますが私の環境では260のようです
C++かどうかは知らないが、
NULLポインタのデリファレンスみたいだからポインタ変数を疑ったらいいと思う。
lpFname, lpDriver, hService, addressなど。
>>GetFullPathName(lpFname,MAX_PATH,fullpath,&address);
この関数の性質上、怪しいのは、lpFname, fullpath, addressであって、
assert(lpFname != NULL);でもいれとくといいかも。
TCHAR * address; TCHAR fullpath[MAX_PATH * sizeof(THCAR)];
GetFullPathName(lpFname, sizeof(fullpath), fullpath, &address)
とかなのか、Windowsは知らねぇよ、と最後にいってみる。
ここではなくて、Windows専用のところで聞いてみたらいい。
Win32API質問箱 Build75
http://pc11.2ch.net/test/read.cgi/tech/1231423602/ こんなところだっけ。
348 :
デフォルトの名無しさん :2009/01/12(月) 21:48:32
>>347 ありがとうございます
lpFnameが不適切なptrなのとsizeof(fullmath)と置くことでデバッグできましたがやはり動作としておかしいようです
手動でインストールすることにします
349 :
デフォルトの名無しさん :2009/01/13(火) 17:29:12
この度C++を勉強しようとしている者です。 レベルとしてはC#中級レベルくらいで、OOPは大体理解できています。 マのバイブルとされるEffectiveC++と、C++勉強用に独習C++を購入しようと思っていますが、 Effective C++ 【改訂第2版】 Effective C++ 原著第3版 この2種類があるみたいなんですが、どちらを買うべきなのでしょうか? それとも両方買うべきなのでしょうか?
Effective C++ はほんと目から鱗の内容だな すべてのC++プログラマは読んで身につけて欲しい
>>352 立ち読みでもして、欲しけりゃ買え。
3版の後ろの方に、2版との違いが載ってるから。
355 :
デフォルトの名無しさん :2009/01/13(火) 22:42:38
>>349 禿本は却下?
/⌒\
川 ´∀`||
|||| 川 |||
std::tr1::bind 使おうとしたら _1 が定義されてないとエラーが出てしまいました boost ライブラリ入れてない状態だと、tr1::bind の _1 とかって使えないのですか?
>>356 std::tr1::placeholders名前空間に入っている。
なんで66立ったんだ?
前にもどっかのスレでそういうことがあった気がする。
>>361 gccは(整数)+(ポインタ)の式をポインタ→整数の順に評価するから
>>362 なるほど!361じゃないけどありがとうございました。
364 :
361 :2009/01/14(水) 22:36:04
361はまだわからない・・・
A + B は、GCC では最適化が効かなければ、 A と B が数値の場合は A → B の順に、 A か B のどちらかがポインタの場合はポインタが先に評価される、 ということだろう。 実際には最適化が効くと結果が変わるかもしれないし、 処理系によって結果も違うだろうし、 あまり覚えても意味は無い事だな。 処理系作るなら必要な知識かもしれないが。
cygwinのgcc3.4.4でも確かにそうなるね (int) puts("foo") + (int *)puts("bar"); で bar foo と出る 面白いけど、規格上は不定だろうし、とりたて役にはたたないな
副作用完了点でないところで何らかの結果を出そうとしている時点で鼻から精液が出てもおかしくないね。
評価順なんぞに依存した処理を書いても大体ロクなことにならないからな
barfooと出てもfoobarと出てもfboaorと出てもおかしくないわけだ。
フボアオー
fboaorと出ることはないだろ puts("foo")とputs("bar")の処理が混ざらないことは保証されるはず
372 :
361 :2009/01/15(木) 00:09:32
373 :
デフォルトの名無しさん :2009/01/15(木) 19:05:09
アドバイスお願いします。 今ゲームを作ろうとしていて、町のデータに int int int double double の数値を予定しています。 こういった場合、 町のデータっていうものは クラスまたは構造体にした方がいいんでしょうか? 現在、クラスが良く判っていない為、配列であてているのですが、町(データ)の数が増えた場合、クラス化してあると管理は楽になりますか? スレ違いだったらごめんなさい
>>373 やりようによるとしか・・・・・
クラス使ってもアホがやると、やっぱりゲログチョに・・・・・・
376 :
デフォルトの名無しさん :2009/01/15(木) 19:54:20
std::istreamのようなインターフェースから一文字ずつget()出来る場合、 配列strに含まれない文字からなる配列retを返す賢い方法はありますか? 言い方を変えると、strに含まれる文字が来るまでget()し続けるということです。 algorithmヘッダは使えます。
unget とstrchr でいいんじゃねーの 賢いかは知らん
378 :
デフォルトの名無しさん :2009/01/15(木) 20:09:11
unget()は、一文字だけ常に返せることが保証されていると考えていいんですか? putback()が一文字以上はエラーになる場合とならない場合があって、 実際のクラスとストリームオブジェクトの状態に依存するようで どうにも困ってます。 ストリームがエラー状態になった場合の回復方法もよくわからない。 難しすぐる。
379 :
デフォルトの名無しさん :2009/01/15(木) 20:09:16
>>374 ,375
回答ありがとうございます。
紹介してもらったスレ読んで見てきます
380 :
デフォルトの名無しさん :2009/01/15(木) 21:23:40
>>375 現行スレをざっと見てきたのですが、今の私では・・ って感じでした。
クラスの中に構造体を所持すればいい? というのはどういう感じなのでしょうか?
データクラス (町) {構造体 <町データ> } なのかなぁ
クラス = 構造体+関数 って認識なんですが、 根本間違えてる?
>>380 構造体にしろクラスにしろPOD型(intとか)に限らずクラスや構造体をメンバにできる。
町データをどうするべきかは
>>375 に貼られてるスレで訊くべし。
>>376 get() の繰り返しを行う Iterator をでっち上げて remove_copy_if() 。
>>382 そんなイテレータを作らなくてもistreambuf_iteratorで十分という気がする。
>>383 「std::istream から」と書いてあればそうなんだけど、「のようなインターフェースから」と
書いてあるからたぶん実際は違うんだろうなと思った。
int8_t num = 10; cout << num; 上記でint8_tを表示できないのですがなぜでしょうか? intにキャストすると表示できます。
通常はint8_tはcharのtypedefで 通常はcoutにcharを出力すると文字として表示されるようになっているから
signed char じゃね。 まあ同じ事だけど。
388 :
385 :2009/01/16(金) 07:33:16
>>386 ,387
なるほど。どうもありがとうございました。
>>389 BC++とそれ以外の動作の違いをifで吸収して説明しているだけだよ。
srandを呼んだときに、乱数を1回分捨てるかどうかの違い。
アルゴリズムの本質的な部分ではないから、まとめている。
テンプレートでグローバルなキャスト演算子って書けましたっけ?書き方が分からんのですが・・・
#ifndef GLOBAL_CAST_HPP #define GLOBAL_CAST_HPP namespace mycast{ template <typename _ResultType,typename _T> _ResultType global_cast(const _T& in){ return _ResultType(in); // 処理は適当に }; } #endif ていうか、結局何がしたいの?
は?
関数でなくて演算子オーバーロードが良いんですが・・・ やりたいのはbad_castを捕まえて自前のエラーを投げることと、一部の型について特殊化を行うためです。
cast演算子は確かオーバーロード出来ないので、適当に関数組んで中で処理させるしかない。 c++0xではオーバーロード出来るようにしたいねとか話題があったような気もするけど、結局どうなったのかは知らない。
>>390 さんくす、最初の一回を捨てるということかな
srandは種を入れる関数だったね srandで呼び出すのかと間違ってました・
ここで言っているキャスト演算子って何? static_cast とか?それとも (Type) みたいなキャスト表記? bad_cast を捕まえてっていうからには dynamic_cast に被せるんだろうけど だったら >392 で十分な気がするんだ。
>>398 そうですね。どうやら無理っぽいのでキャスト関数に落ち着きます。ありがとうございました。
static_cast にこだわんなくても hogehoge_cast でええやん。
TCHAR *pBuf = new TCHAR[iLength+1]; edit.GetLine(i,pBuf); pBuf[iLength+1] = 0; str.Format(_T("%s\r\n"),pBuf); //ファイルへ書き込み ar.WriteString(str); delete[] pBuf; というコードを実行させるとdelete[]でエラーをはいてしまうんですがなぜでしょうか?
>>pBuf[iLength+1] = 0; ぶっ壊してるじゃないか
>>401 iLength + 1しか確保していないのにiLength + 1番目に書いちゃダメ。
それが原因かはしらね。
pBuf[iLength] = 0; にしたらdelete[]でエラーをはかなくなった代わりに、文字が全て不定値になりました。。。
iLength + 2 確保するという発想はないのだろうか
そもそもMFCならCStringに直接入れられるんじゃないだろうか。 つーか、EditControlなら複数行まとめて取り出せるんじゃないだろうか。 いずれにしても、スレ違いになるが。
+2しても全て不貞値になりましたとさ・・・もう疲れたよ派とラッシュ・・・ ありがとうございました
実際にはバイト数じゃなくて文字数だった気がするよ。
>>407 GetLineの戻り値は何になってる?
>>401 iがiLengthよりうんと大きい値になっているということはない?
412 :
デフォルトの名無しさん :2009/01/18(日) 15:56:21
>>404 「不定値」とは具体的にどのようなものですか?
コンパイラあるいはデバッガに「文字列は不定値です」と言われたのですか?
413 :
デフォルトの名無しさん :2009/01/18(日) 23:03:10
質問させていただきます vecter<ObjectA> vec; vec.push_back(new ObjectA); としてvecterに複数個オブジェクトを入れた場合、 最後にdeleteするのは一般的にどうやるのが普通なのでしょう? vec.clear()ではオブジェクトのデストラクタも呼ばれないので・・・
boost が使えるなら boost::ptr_vector<ObjectA> を使うなり std::vector< boost::shared_ptr<ObjectA> > を使うなりする。 boost が使えないなら、 vec を、必ず vec を制御する関数を通して扱うか、 カプセル化してしまう。
Boostがだめでもstd::tr1::shared_ptrという希望がある。
一般的かは知らないけど、下のような関数作っておくというのも一つ。 コンテナでも配列でも使えて便利。 template<class Itr> void purge(Itr begin, Itr end) { while(begin != end) { delete *begin; *begin = 0; ++begin; } }
for_each + checked_deleterでいいじゃない。 っていうか例外投げられたらリークする。
deleteが例外投げちゃいかんでしょ
>>418 そうではなくて、purgeを呼ぶ前に例外投げられたら駄目だろという一般的な話。
>>415 今までさわってきた限りだと、boostもtr1も入ってないか、boostしか入ってない処理系にしか出会わなかった。
tr1ってまだ普及してないんだなって思った。
ためしに416 をしてみたらなぜか無限ループから抜け出せなくなったw
>>416 イテレーターの参照を直接deleteしたらまずくないか?
ポインタのコンテナなんだろ
vectorの削除って for(int i=0;i<vector.size();i++) { delete vector[i]; } じゃぁだめなんでしょうか?
いいけど、他のコンテナに変更した時に書き直さなきゃならなくなるよ。
VC++で作成したライブラリを gccでコンパイルしたいんだけど できるものですか? マングリングとかの関係で云々という記述は見たりするのだけど・・・
フルコンパイルする分には問題ないよ。 ただ、VC++ に依存するコードがあると移植作業が必要だけど。
コンパイルだけなら、環境依存なコードじゃなければ問題ない VCでビルドしたスタティックライブラリをgccでリンクとなると無理 理由は名前マングリングなどバイナリの互換性が無いから
>>427 ,428
レスありがとうございます.
そうですかー,ソースは自分のじゃないので手元にない
というわけで,無理ってことですね
reimpとかdlltoolとかで変換できればいいんですけどねー,残念です
VC++ライブラリを呼び出すextern "C"のラッパーを(VC++で)作って それをgccで呼び出すようにすれば行けるんじゃないかな やったことないけど
そうそう、__cdeclリンケージのライブラリであれば問題なし C++のスレで質問するってことは違うんだろうけど
あるいはWindowsなら、純粋仮想関数のみの抽象クラス(仮想デストラクタなし)でも相互に行けるはず。 ようするにCOM一歩手前。 当然COMインタフェース化してもいい。
>>430 マングリング以外の部分でマズいこと起きそうな気がする。
>>430-433 一応reimpにはかけていて
ライブラリ中のclassで記述されている部分が軒並み変換されなくて
どうにかならないかと思って 調べている最中なのです
非純粋仮想関数のclassを使っている時点でNGという認識であってますか?
VC++ だとメンバ関数ポインタは多重継承や仮想継承をしてるかによって 4、8、12バイトと可変だが、g++ だと8バイト固定だったりする。 this ポインタの渡し方も VC++ だと ecx 渡しだけど g++ だと eax 渡し。 本当に色んな部分で決定的に違うから、C++ は簡単に変換できないと思われ。
VC++ で C の dll を作って、 それを g++ で使えるようにするといいんじゃない?
クラスを直接受け渡すのは無理だろうな 面倒だがPOD構造体に直してから渡して受け取った方で再構築するしかない
呼び出される関数が予めオーバーライドされた物かどうか判断する合法なやりかたってありますか? struct Hoge{ virtual ~Hoge(){} void virtual X(){} void fuga(){/*ここでどちらが呼ばれるか判定*/} }; struct Piyo:public Hoge{ void X(){} };
>>440 できてもあんまりうれしくないから、無いと思うよ。
そんな判別ができたとして何がしたいのかわからん。
子クラスの面倒を見たいんです・・・
>>440 if(Hoge::X == this->X)
とかやったらわかるだろうか。試してないし保証しないが。
なんにせよそんな判断がしたい、ってのが変な話なような。
>>443 Hoge::X の時点でコンパイルできないね。メンバ関数へのポインタなら &Hoge::X だけど、
&this->X もコンパイルできない。
&this->X に対する gcc 3.4 のエラー。
> error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say `&Hoge::X'
>>440 RTTI有効にしてインスタンスが何なのか調べればいいんじゃね?
typeid(*this) != typeid(Hoge)ですか?コストはどうなんでしょう・・・
親クラスの中で派生クラスでの挙動を考えるというのは 何と言うか構造的に問題がありそう気がするけども
449 :
438 :2009/01/21(水) 22:12:45
昨日今日で色々試したけど,駄目でした extern"C"でのラッパを作って一見いけてそうに見えたんだけど 実行すると何も吐かずにエラーっぽく落ちる
なんかそれは別の理由っぽいが
>440 型によって処理を切り替えたいのならその部分から仮想関数にすればいいじゃないか。
>>451 その更に前後に処理挟みたいんですよね。用はBeginPaintとEndPaintで挟みたいってことなんですが・・・
NVIの出番だな ぐぐれ
454 :
438 :2009/01/21(水) 23:59:58
>>450 printfの間にラッパ関数を呼び出したら何も表示されなくて
関数外したら表示されるから,ラッパの所為かと思ってたけど
違うとなると....なんだろうか...
なんだろうかとかいわれても・・・・・・・
456 :
438 :2009/01/22(木) 00:23:47
ラッパの作り方が悪いとかで, 関数コール時に不正な処理をしているのかと想像していたんだけど もう少し仕込みを入れて調べてみます
XをprivateにしてXを呼び出すメンバ関数を作ってそこの前後にbeginとend呼べば。 継承したクラスで呼びたくないならその関数もラップしる。
458 :
デフォルトの名無しさん :2009/01/22(木) 10:51:24
type erasure について詳しく載ってるサイトまたは書籍教えてください。 できれば日本語で..
少しは検索しろよ。紹介する気にもならん
結局サンプルコードを自分で作って試したら やり方はあってて,実行時にdllがありなかっただけでした すんません ってことで,無事解決できました.ありがとうございました.
461 :
438 :2009/01/23(金) 00:02:12
あっ,名前忘れた 460は自分です
463 :
デフォルトの名無しさん :2009/01/23(金) 17:10:46
すれ違いな気もするけど、C言語使っての上でと言うことで… 実験とかで得たデータを保存するとき、 独自フォーマットよりは、汎用のが良いと思っています。 XML,YAML,CSV…変わったところでXとか、まぁいろいろありますけど、 Cで"繰り返しの中に繰り返しが入るような"データを保存するとき、 どのような形式が向いていますか? (たとえば、SGML系は配列等には向かないと思うのです)
Cかどうかはさておき ネストの深さが不定ならxml, yamlかなあ ネストが親要素で固定されるならなんでもいいんじゃね?
あとJSONとか? CSVで扱える構造なようならCSVが扱いやすいと思うけど
467 :
デフォルトの名無しさん :2009/01/24(土) 12:37:36
そこで独自フォーマットを作ってこそのプロなんだと思うが。
何のプロ? 車輪の再発明なんてド素人中のド素人だろ。
独自フォーマット作るぐらいなら、S式使った方がよっぽどマシだよ。 話の流れをぶった切って(ry こんなの作っているんだけど、M0がvoid式だとコンパイルエラーになります。 何か上手い回避方法ありませんか? SFINAEやろうとしても戻り値がvoidかどうかは判別できないし…… template<typename H, typename M0, typename A1> static bool entry() { struct Local { static H trampoline(M0& method, A1& arg1) { return H(method(arg1)); }; }; };
>>470 うまい方法って具体的に何?
M0がvoid関数だった場合、entryは何を返したいの?
void式の時はH()を返そうかと思います。
VC++ってどうしてliteralが青く光るのはなんでなのは何故に?
>>470 これが最適だとは思えないが、
M0をvoidでテンプレートの部分特殊化すれば
出来ることは出来る。
>>473 目が悪いんじゃないか? 青く光ってなんかいないぞ。
>>473 C++/CLIでキーワードになっているから。
>470 関数テンプレートなんで、部分特殊化はムリ…… とりあえずテンプレート引数を一つ増やして何とかしました。格好悪いけど。 template<typename H, bool return_value, typename M0, typename A1> struct filter1 { static H trampoline(H& method, H& arg1) { return method(arg1); }; }; template<typename H, typename M0, typename A1> struct filter1<H, false, M0, A1> { static H trampoline(H& method, H& arg1) { method(arg1); return H(); }; }; public: template<typename H, bool return_value, typename M0, typename A1> static bool entry() { struct Local { static H trampoline(M0& method, A1& arg1) { return filter1<H, return_value, M0, A1>::trampoline(method, arg1); }; }; };
まあ、なんだ。 あんまり無理はするなよ。
479 :
デフォルトの名無しさん :2009/01/24(土) 20:36:18
480 :
デフォルトの名無しさん :2009/01/24(土) 20:36:41
仁義なきキンタマ ウイルス情報 Part80
http://changi.2ch.net/test/read.cgi/download/1229742858/546 546 :[名無し]さん(bin+cue).rar :sage :2009/01/04(日) 00:24:59
報告する時は、詳しく的確に、一部だけ報告しないでお願いね
[殺人] Administrator(20081230-101522)のキンタマ.zip 2,263,376,860 09ed98f10653c3fc2555621ceeed6bc33e8f6228
[殺人] Administrator(20081230-101522)のメール.zip 59,426,579 4da9459b30eec31f58b86530dbb48d1cf86ef4be
[写真集][IV] Administrator(20081230-101522)のアルバム.zip 2,205,946,474 9d87cc0e08dc0e3afd959fcead6c48d569787cee
膨大な量のファイル数キンタマ ファイル数 13508 フォルダ数2381
以前勤めてた会社の資料など多数 独立行政法人情報処理推進機構などの資料など無いと思うが
有るかも知れない、あまりにも数が有り過ぎる、メールなどは、古いものばかりメルマガなど膨大な量
個人情報などは、披露宴主席者などの住所、名前、電話、メール 数十人分しかしエロばっかり落としてるな
ちなみに ハメ撮りscr 踏んだみたいね
早稲田実業学校中等部卒業
早稲田実業学校高等部卒業
早稲田大学政治経済学部政治学科卒業
卒論「知的財産権とインターネット技術」
当時の同大学理工学大学院の大川功 賞佳作を受賞
コンピュータ関連会社に入社ソフトウェア開発の仕事を経て
2005年に独立行政法人情報処理推進機構に入社
ソフトウェア・エンジニアリング・センター企画グループに配属
同グループ主任 岡田賢治さん33歳
481 :
デフォルトの名無しさん :2009/01/24(土) 20:37:03
482 :
デフォルトの名無しさん :2009/01/24(土) 20:37:24
483 :
デフォルトの名無しさん :2009/01/24(土) 20:37:47
484 :
464 :2009/01/24(土) 22:34:58
>>465 探してみたんですが、yamlのC用パーサって少ないですね…
>>466 JSONをCで使うのってどうなんでしょう…?
>>467 よく考えたら、テキストとして読めた方が良いかも。
>>470 ちょっと見てみたんですが、頭が回らない…
そもそも、C言語使っていること自体が間違っているような気がしてきた…
こういうの向きじゃないのね
何に食わせて再利用したいかってのが決まってないと何とも言えないと思う XMLとかにした所で、どのタグが何の意味なのかってのはどっかで別に解釈しなきゃならんわけで 形式だけ汎用方式にしたからってすぐ再利用出来るとは限らないし
std::tr1::unordered_map<const char*, int> MAP; MAP.insert(make_pair("abcd", 1)); char *name = (char*)malloc(5*sizeof(char)); strcpy(name, "abcd"), name[4] = 0; printf("1,%d\n",MAP.count("abcd")); printf("2,%d\n",MAP.count(name)); gccで↑の様にした時、二番目に表示されるポインタの所で参照出来ませんでした。 std::map の時は↓の様にすれば参照出来たのですが、unordered_mapで同様な事を出来ませんでしょうか。 namespace std { template <> struct less<const char*> : binary_function<const char*,const char*,bool> { bool operator()(const char* x, const char* y) const { return strcmp(x, y) < 0; } };
>>486 std::tr1::unordered_map<std::string, int>
>>487 const char* でやりたいのです。
>>486 よくわかんないけどうちの環境でコンパイルしたら
>g++ temp.cpp -Wall
>ls
a.out temp.cpp
>./a.out
1,1
2,0
>gcc --version
gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Copyright (C) 2006 Free Software Foundation, Inc.
以下略……
って出たよ。
hashとpredを自分で定義するだけでいけるだろ
>>489 それを↓のようにしたいのです。
1,1
2,1
>>486 本題とは関係ないけど
> namespace std {
> template <> struct less<const char*> : binary_function<const char*,const char*,bool> {
これって std::less の特殊化だけど、ユーザー定義型じゃないから未定義動作になるよ。
std の外で別の型名で作って std::map のテンプレート引数に渡すとか、別の方法にしないとダメだよ。
>>490 >>492 取り合えずこんな感じで指定してみましたが結果は変わらず…。
何かやり方が悪いのでしょうか?
struct MyLess : binary_function<const char*,const char*,bool> {
bool operator()(const char* x, const char* y) const {return strcmp(x, y) == 0;}
};
std::tr1::unordered_map<const char*, int, std::tr1::hash<const char*>, MyLess> MAP;
>>493 なんでハッシュがそのままなんだよ。
なんで等値比較関数の名前が MyLess なんだよ。
ハッシュマップの構造が理解できるまではおとなしく std::map のままにしとけよ。
>>494 すみません、適当すぎました。こんな感じでしょうか?まだ上手くいかないのではありますが…。
struct MyHash {
size_t operator()(const char* s) const { return std::tr1::hash<const char*>()(s); }
};
struct MyEqual_To : binary_function<const char*,const char*,bool> {
bool operator()(const char* x, const char* y) const { return strcmp(x, y) == 0; }
};
std::tr1::unordered_map<const char*, int, MyHash, MyEqual_To> MAP;
>>495 > struct MyHash {
> size_t operator()(const char* s) const { return std::tr1::hash<const char*>()(s); }
これで何が変わると思ってんの?
そういう所をお教え願えませんでしょうか・・・?
ワロタ。ポインタ渡しても意味ないよ。 size_t operator()(const char* s) const { size_t h = 0; while(*s++ != '\0') boost::hash_combine(h, *s); return h; } boost::hash_combine使えないなら h += *s;とかでもとりあえずはいける。衝突が多くなって遅くなりそうだけど。
ミスったこうだな for(; *s != '\0'; ++s)
これでもいいけどな。 struct MyHash { size_t operator()(const char* s) const { return std::tr1::hash<std::string>()(s); } };
>>498 なるほど、ハッシュってそういう使い方をするのですね。
その方法で出来ました。ありがとうございます。
>>502 それを書くくらいならhash_combineの実装をコピペしたほうがいいと思ったんだよね。一行だけだし。
まあ実験用ってことで
>>500 それって中でstd::stringが作られないの?
>>504 もちろん。
const char*からstd::stringへの暗黙の変換を行った上で呼び出している。
506 :
デフォルトの名無しさん :2009/01/26(月) 17:13:57
マイコン開発ツールの「KEIL」って何て読むの? カイル?ケイル?キール?
ケーイーアイエル
508 :
デフォルトの名無しさん :2009/01/26(月) 18:36:13
C++だけでなく、Cも関係あるのですが、 stack overrun を検出するツールなどはありますでしょうか? 現在のテスト環境はlinux(kernel 2.6系), gcc(g++)です。 デバッグは主に、valgrindを使ってますが、coreをバックトレースすると、 スタックが壊れてるような感じになっています。
>>509 そういう環境依存なことは該当環境スレへどうぞ。
509です。環境依存の方に質問し直しました。
512 :
デフォルトの名無しさん :2009/01/29(木) 11:26:42
アセンブラからC++仮想関数を呼ぶにはどうしたらいいでしょうか? (関数名とVtableの対応は、どうしたら分かるでしょうか?)条件は単一継承のみです。 環境はVCです。
513 :
デフォルトの名無しさん :2009/01/29(木) 12:19:44
家のパソコンを使い、 C言語で小遣い帳を作ることは可能ですか?
>>512 コンパイラの生成したコードを真似るといいよ。
別のコンパイラやバージョンの違うコンパイラと組み合わせたら動かなくなるかもしれないけどね。
>>512 組み込み系のコンパイラなんかはリファレンスに呼び出し規約が書いてある
>>513 Microsoft Excelを起動すればおk
>>512 素直に普通のCの関数でラップするのが楽。
class Hoge {virtual void Foo();};
extern "C" void call_hoge_foo(hoge* p) {p->Foo();}
どうしても最高速でアクセスしたいなら 各環境でいちいち仮想関数内のインデックスを調べるしかないのかね
再高速でアクセスしなければいけないものを関数で書くなよ
多態ならある程度しゃーない
ライブラリなのでは?
メンバ関数ポインタとればいいじゃん。
525 :
512 :2009/01/30(金) 06:52:59
>>514 ,517,519-524
簡単なのは、519ですね。高速性を要求されるときは、各環境で仮想関数内のインデックスが必要になるのですが、
そんなときは、524方式で、vtable内で合致するINDEXを調べてアセンブラに教えてあげることにしました。
コンパイラを書いていて、VCで書いたC++クラスを利用したくなったのでお聞きしました。
皆様、どうもありがとうございました。
アセンブラから呼ぶときって例外とかどうなるん?
C++ワールドの外に出た例外は何を起こすかわからない
528 :
デフォルトの名無しさん :2009/01/30(金) 20:36:14
struct T { struct poddata pods; T() : pods() {} }; て書いたとき、podsの中身は0クリアしてくれるんだっけ? 要は、コンストラクタの初期化リスト内で : pods() と書いたときの挙動なんだけど 初期化リストに何も書かないときは、pods(内のPODデータ)は何もされないけど podsを0初期化したい場合は、初期化リストに pods() を加えれば良いのか、ってこと。 もちろん、podsは(手書きの)コンストラクタ等を持っていない場合に。
>>524 ちなみに、メンバ関数へのポインタがアドレス(普通のポインタの表現)だと思っていたなら、
それは違うと言っておく。そうでもしないと、メンバへのポインタを介した仮想関数の呼出時に、
多態的にthisに合う関数を選び出す実装が不可能だと思う。
#include <cstdio>
struct Hoge {virtual void Foo() {std::puts("Hoge");}};
struct Piyo : Hoge {virtual void Foo() {std::puts("Piyo");}};
int main()
{
void (Hoge::*pf)() = &Hoge::Foo;
Piyo piyo;
(piyo.*pf)(); //Piyo::Fooが呼ばれる
}
質問者は理解していたようだけど。
td::dequeってclearが走るとメモリも開放される(アロケータのdeallocが走る)って規定されてる?それとも未定義?
未定義はさすがにないだろwwww
実装依存だろう
未規定?
>>530 アドレスでも不可能じゃないよ。
「this を受け取って仮想関数テーブルを引いてジャンプする処理」のアドレスで実装できる。
537 :
470 :2009/01/31(土) 17:32:30
例外をoffにした場合って、newが失敗した場合はNULLが返ってくるんでしょうか?仕様として。
>>538 「例外をoff」の時点で標準から外れるので、この場合の仕様はコンパイラしだい。
マニュアル嫁
>>539 ありがとうございます。マニュアルみます。
仕様として、std:nothrow指定すればnewを失敗したときにNULLを返す。
>>541 それ、コンストラクタからの例外に効かないからあんまり意味無いよ。
3年ぶりにc++の仕事に戻ってきたんだけど お勧めのログ出力のライブラリってありますか log4cppとかboostにも一応あるみたいだけど。
>>544 それ、boost::refでも全く同じ結果になるよ。問題ない。
>544 template はどんな型でも受けるんだから T = refwrap<U> の場合もある。 そして変換関数の呼び出しが必要ない分、F<>(refwrap<T>) が F<>(int&) よりもオーバーロードの解決で優先される。
>>544 boost::refってそうやって実装してるのか勉強になったよ
>>546 2版目のFは明示的にT&を返すメンバ関数呼んでるんだけど、なんでF<>(int&)に解決されないの?
printf()
>548 すっとぼけたこと言ってすまんかった。 > 14882:2003 5 Expressions/6 > If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to “T” prior to any > further analysis, the expression designates the object or function denoted by the reference, and the expression > is an lvalue. により参照はずした後で解析が行われるため型導出(type deduction)の結果は F<int&>(int&) ではなくて F<int>(int) になる。
templateの型がどれに決定されたのかをコンパイル時に見たいんだけど(エラーメッセージでいい) どう書けば確実に見れます?Borlandで
普通は見れないし強引に見る方法もほとんどない あらゆる特殊化にprintf仕込んでおくしかない
>>551 typedef typename T::undefined_t UNDEFINED_T;
で発生させたエラーメッセージで見れた。VCだけど。
typeid(T).name() を出力すれば?
ああ、コンパイル時か・・・ すまんかった
もっかい聞きます。お勧めのログ出力のライブラリってありますか log4cppとかboostにも一応あるみたいだけど。 環境はg++、linuxです
>>557 挙げてる奴でダメな理由を出さないと別のは挙げようがないんじゃね?
printf()
>>557 C++におけるオープンソースライブラリの隆盛がわからんのです
boostがデファクトというのは理解出したんだけど
ログは日本語のboostサイトには紹介されてなかったので何か他にいいのがあるのかな、と
log4cppはjavaで慣れてるんだけど引数にストリーム使わないっぽいし
かと思えば一般的にストリームもあまり利用されてないとか
よくわからんのです
>>560 使ってみて自分の必要とする機能さえついてれば、隆盛とか関係ないだろ?
boost より開発がアクティブなやつを挙げろと言われても無理だろうしな。
>>550 thx.
よくわからんかったけど・・・w
>562 「T への参照型」となる式は、いかなる解析よりも前に T 型へと調整され、参照先のオブジェクトあるいは関数を指し示す左辺値となる。 つまり関数テンプレートの型導出の前に、int& 型を持つ r.getref() は int 型と見なされてしまい、結果 T が int として導出される。
F<int&>(i)
(i)←まんこ?
struct X{ virtual ~X(){} virtual void p(){} virtual void p(int){} }; struct Y:public X{ void p(){} }; このように継承先で親クラスのオーバーロード関数の一つをオーバーライドするとX::p(int)がY::p()に隠蔽されると出ます。 これを鎮めることはできますか?BCC5.5のクソパイラです。
Y::p(int)もオーバーライドすればいいよ
クラスが同じだと異なるオブジェクトでもプライベートメンバーにアクセスできるのだが C++の言語設計者って馬鹿なの? class A { int n; A(int m){n = m;} int func(const A& a){ return a.n; } } A a1(1), a2(2); cout << a1.func(a2); << endl;
>566 >このように継承先で親クラスのオーバーロード関数の一つをオーバーライドするとX::p(int)がY::p()に隠蔽されると出ます。 その挙動自体は規格準拠。 struct Y:public X { using X::p; void p() {} }; と書けばいいはずなんだけど、BCC5.5 で通るかは分からない。
>>568 自クラスのことすら把握できないって馬鹿なの?
>>568 operator ==とかこうでないと実装できないだろって例ならいくらでも挙げられる。
あと、逆にこうなっていない言語って何がある?
いくらでも挙げられるつーなら、一つくらい挙げてみろよ
コピーコンストラクタ
operator ==だろ あとoperator !=とか operator <とかoperator <=とか operator >やoperator =>もそうだな operator +だってそうだしoperator -にoperator *にoperator / operator %もそうだ それからoperator &とかoperator |とか operator ^も 変わった所ではoperator ->*なんてのもあるな ちなみにoperator &&もそうだけどやっちゃダメだぞ operator ||とoperator ,もね あ、忘れてた。operator =
同じクラスのものなのにプライベートメンバにアクセスできない方が異常
class A { int n; char c; public: A(int m, char d):n(m),c(d){} A(const A& a):n(a.get_n()),c(a.get_c()){} bool operator==(const A& a) const { return n == a.get_n() && c == a.get_c(); } A operator+(const A& b) const { return A(n+b.get_n(),b.get_c()); } int get_n() const { return n; } char get_c() const { return c; } } A a1(1,'a'), a2(2,'b'); cout << a1 == a2 << endl; できないこともない privateの意味がないけどな!
A::operator==(const A& a){private_member = a.private_member;} ができるのに、じゃあなんで A::operator==(const B& b){private_member = b.private_member;} ができないんだよ。 C++の言語設計者は明らかにアホ。
別クラスの private メンバ見れたらカプセル化壊れるだろwww
別オブジェクトのpriveteメンバが見られても同じことだろ
確かに問題だな。 C++0xで修正されるんじゃないの?
>>581 比較のために公開したくもないメンバを public メンバ関数で公開しなきゃいけない方が問題だろ
自分のクラスの面倒くらい private で面倒みさせてくれよw
自オブジェクトからしかアクセスできないアクセス指定子が必要だな 名前は何がいい?
secret
private
masturbate
なんで0*HUGE_VALって落ちるの? あと、doubleで0除算ってINF返してくれるんじゃないの?何で落ちるの?
C系言語は伝統的に浮動小数点の扱いが超適当だから その辺ちゃんとやりたいならFortran使いなさい
それはない
C89は「NaN?INF?-0?何それおいしいの」って感じだった そんなだからC++の方でもほったらかしだった C99で対応したけどやっつけだったからクッチャクチャになった C++0xは真面目に対応する気はないらしい C/C++の浮動小数点に期待するな
C#でいいじゃん
>自オブジェクトからしかアクセスできないアクセス指定子 静的にきめられねぇだろJK
Objective-C<呼んだ?
むしろオブジェクトが1個しか作れないようにすればいいんじゃないか?
this->つけて使わないとコンパイルエラーになるのはちょっとほしいと思った。
>568 パフォーマンスを高めるための妥協案。D&Eになんか書いてあったような気がする。 インスタンスごとにアクセス権を設定しても利点が少ない割にコストがデカくなる。 まあ、インスタンスとクラスの概念をごっちゃにしていると>568みたいに思うこともあるよな。 俺も昔はそうだったし。
>>593 Dでいいじゃん。
!<>=(順序づけ可能でない)とか、!<>(順序づけ可能でないか等しい)とか組み込み演算子であるよ!
>>600 >まあ、インスタンスとクラスの概念をごっちゃにしていると>568みたいに思うこともあるよな。
どうしてそう思ったの?
>>568 ではクラスとオブジェクト(インスタンス)を厳密に使い分けているが?
>>603 600 じゃないけど、いちおう言葉は使い分けているものの、クラスの整合性を保つ責任が
どこにあるかという点でごっちゃにしていると思う。
>>600 まぁ疑問に思うことはあるかもしれないけど、そこですぐ「○○は馬鹿」とはならんよね、普通。
頭の悪い奴ほど、不足だらけのデタラメな知識体系で
「わかってる俺と、わかってない他者」って関係を見出したがるけど。
606 :
デフォルトの名無しさん :2009/02/03(火) 14:01:08
>>605 だからと言って、「頭の悪い奴」にはならないよね。
まさに、「デタラメな知識」ですね。わかります。
>「わかってる俺と、わかってない他者」って関係を見出したがるけど。
お前が「わかってる俺」で、
>>600 は「わかってない他者」ですね。わかります。
人に説明して分かって貰えない時は、説明の仕方が悪いと思え。
アホ=cool
611 :
602 :2009/02/03(火) 22:15:52
612 :
600 :2009/02/03(火) 22:16:55
>605 おいおいおい、誰も馬鹿なんて言ってないぜ。噛み付くなよ。 理由は>604の通りですな。どうせプログラマはクラス単位でプログラムするから、 わざわざインスタンスでアクセス制御するメリットがあんまりないんだよね。 もしインスタンス単位でアクセス制御したいんだったら、そういう風にクラスを作ればよろし。
>>604 それでは、「クラスの整合性を保つ責任」と言う言葉を使って、
>>568 がインスタンスとクラスの概念をごっちゃにしている、
ということを君なりに説明してくれないか?
>>606 >だからと言って、「頭の悪い奴」にはならないよね。
ん?拙い知識で言語仕様にケチをつける
>>568 は
俺からみても、とても頭の悪い人にしかみえないけど。
>>612 >>605 は
>>568 を揶揄しているようにしか読めないわけだが。
行間()読めないやつはかき込むなよ
行間を期待するプログラマはバグを埋め込む三流の派遣 コンパイラは行間など読んでくれない
617 :
600 :2009/02/03(火) 23:18:07
>614 スマン、素で勘違いした。 >613 ・インスタンスとクラスは別物 ・プログラマが設計するのはクラス(インスタンスじゃない) というあたりがちゃんと判っていれば、>568のような全否定の言葉は出て来ないんじゃない? まあ、言語設計を馬鹿にするんだったら、せめてD&Eとガウディ本ぐらいの知識は持って欲しいなぁ。 馬鹿相手にすると疲れるし。
「クラスの整合性を保つ責任」は何処行っちゃったの?
>>617 その本のどの部分の知識が反論に当たるのか示せなければ
お前は単なるD&Eとガウディ本の威を借る狐だ。
620 :
600 :2009/02/04(水) 00:11:53
ああ、ああ、判った判った。ウザいな。 突っ込み入れるだけじゃなくて少しは有益な情報を追加してくれよ。相手するのも疲れるわ。 D&Eは「2.10 保護の方式」にコメントが載ってますな。 インスタンス単位で制御できるようにすることで何か新しいことができるようになると感じるのは錯覚だと断言してるね。 ガウディ本だと「7.3.3 カプセル化制御」のあたりかね。色々な言語のアクセス制御について整理されている。 しかし、2chとはいえもう少しは有意義な話をしようぜ。
>>616 人間に対するときとコンパイラに対するときと、同じようにしか接することが出来ないプログラマは
コミュニケーションが取れない三流の派遣
>>620 ようやく有意義な書き込みを書けたね^^
623 :
600 :2009/02/04(水) 00:21:54
あと、>619 「プログラマが整合性を保つ責任を持つのはクラス」ということかね。 インスタンスの整合性は、あくまでクラス設計から導き出される間接的なものでしかないよね。 インスタンスの視点では設計の整合性を保てない場合もあるし。例えばSingleton/Multitonとか。 あるいは プログラマが設計できるのはクラスで、インスタンスは間接的にしか設計できない。 なのでクラス視点のアクセス制御があっても何ら不思議ではないし、インスタンス毎の アクセス制御ができなくても何ら不思議ではない だから>568は短絡的すぎ とでも言っとくかね。
>>623 クラスを「メーラーのソース」、インスタンスを「メーラー」と読み替えると、
僕のメーラーから君のメーラーへのアクセス制御ができなくても何ら不思議じゃないことになるね。
プログラマが設計できるかどうかという観点で区別するのは正しいのかな?
読み替えてる時点で違うものになってるから。 会話で勝った気になりたいだけのウザイやつは死ねよ。
死ねとか言い出したら負けだろ
628 :
600 :2009/02/04(水) 01:06:28
>625 C++の場合、そういうのは「同じユーザーが2つのメーラーを立ち上げている」ようなケースじゃない? あくまでプログラマがクラスを使用するんだから、同一プロセスで同一クラス同士のインスタンスが 通信してもそんなに問題にはならないと思うけど、どうよ。 「僕のメーラーから君のメーラー」というのはプロセス間通信みたいなモンだと思う。
>>627 肝心の言語の話がまるで理解できず、「死ね」の部分にしか反応できないと
そういう考えになるかもな。
>>628 「同じユーザーが」と言う仮定はどこからきたの?
マルチユーザー環境なら世の中に山ほどあるよ。Windowsしか使ってないと分からないかもしれないけど。
>>622 お前もちったあ見習えよ。
>>626 内容が理解できないときは例え話です。
誤謬なんか気にしちゃ駄目なんです。
>>624 打たれ弱いけど速いよ!
632 :
デフォルトの名無しさん :2009/02/04(水) 17:56:10
ここで聞いていいのか分からないけれど、他に適切なスレがあれば教えて下さい。 DLL内の関数でメモリを確保して、それを呼んだ側でスマートポインタに入れる、 というのはメモリの管理上問題ないですか? dll_func(vector<T*>& v) { v.push_back(new T()); } main_func(void) { vector<T*> v; dll_func(v); vector<shared_ptr<T> > u(v.size()); for (size_t i=0; i<v.size(); ++i) { u[i].reset(v[i]); } }
問題ないけど危ない設計
ちゃんとデアロケータ呼ばれるか心配だな
635 :
632 :2009/02/04(水) 18:16:02
>>633-634 どうもありがとう。「危ない」というのは人間側の問題でしょうか?
例えばDLL側にファクトリ関数のようなものを実装する場合は他に何か一般的な方法がありますか?
>>632 バージョン含め同じコンパイラで同じランタイムライブラリに動的リンクするようにすれば上手くいく可能性が高い。
そうでないなら、dll_func側のnew/deleteとmain_func側のnew/deleteが別物になるので大いに問題あり。
Tについてはdll_funcの引数をvector<shared_ptr<T> >にすればいい。
そして、vector<shared_ptr<T> >を両者共通で使えるメモリ確保ルーチンを使ったアロケータを使うようにする。
ただ、前者でもdll_funcの引数でvector<shared_ptr<T> >にしたほうがいい。しない理由がない。
637 :
632 :2009/02/04(水) 18:22:54
>>636 ふむぅ、なるほど。確かにしない理由がないですね。
とりあえず問題点はわかりました。
ありがとうございました。
638 :
600 :2009/02/04(水) 21:26:45
>630 最初のメタファが狂ってんだよ。 腐ったメタファなんか使わずに、どういうことで問題になるのか具体的にきっちり言えよ。 もともとの例え話がダメダメなんだから、『「同じユーザーが」と言う仮定はどこからきたの? 』 なんて突っ込まれてもこっちが困るんだがねぇ。 C++のプログラムだと「僕」が誰で「君」が誰で「僕のメーラー」と「君のメーラー」を実行するということが どういうことか、きっちり説明してもらおうかね。 “僕のメーラーから君のメーラーにアクセスされると困る”というのなら、素直にメーラー捨てろよ。 同じように、プログラムするときに困るならクラスも捨てろ。 そんなもんメーラー/クラスの設計次第だろ。(あるいはOSとかの下位層の仕事) 『クラスの設計者がバックドアを仕込んで別プロセスにデータを流すかも知れないから 言語でprivateアクセスはインスタンス単位で制御しないと危険だ』 とでも言いたいのかね?だとしたらムダも良いところだな。 同一クラスのインスタンスで情報をやり取りする方法はいくらでもあるし、インスタンス単位で アクセス制御するコストは馬鹿みたいにデカくなりそうだしな。
いつまでも煽り合ってるなよ。
>>600 にあるとおりパフォーマンスが理由でFAでしょ。
はい、次の相談者どうぞ。
640 :
デフォルトの名無しさん :2009/02/04(水) 21:57:14
> パフォーマンスが理由でFAでしょ。 アホ
「D&E読め」で終わる話をいつまで続けるつもり?
相手を黙らせるまでだろ?
君が!n(ry
ヒープからメモリ取るのにmalloc使って引数にsizeofどうたらと書くのが面倒だったので こんなの作ったんですが問題はないでしょうか 一応エラーとかはなく動いてるみたいです template <int Size> class Buffer{ char buf[Size]; public: Buffer(){this->~Buffer();}; }; int main() { void *p = new Buffer<100>; //pをただのメモリの塊として利用 delete p; }
例外安全性がないし、void * にキャストした後に delete した動作は未定義なので失格 素直に std::vector 使え
>>644 厳密に言うと、それを解放するには、operator delete(p)としないといけないと思う。
ところで、それだとmallocやnew char[]を使わない利点が見えてこないけど。
operator delete するなら new 側も operator new を直接使わないと
class Buffer { public: Buffer(size_t size) : m_buf(size) { } void *data() { return &m_buf[0]; } const void *data() const { return &m_buf[0]; } operator void *() { return data(); } operator const void *() const { return data(); } private: std::vector<char> m_buf; }; てか、バイト単位で指定させるだけなら、結局 sizeof 必要なんじゃね?
>>647 作る側はnew演算子(operator new関数→コンストラクタ)の後、
デストラクタを呼んでいるから、operator delete関数呼出で釣り合う。
>>645 void*のdeleteは未定義なの?
operator deleteの定義をみると
特に問題なさそうだが
this->~Buffer() ってことは、このメモリ領域、その後なんかでnewした時に割り当てられるってことないの?
すいません、あと、delete p; って既に開放済みなのにdeleteできるの?
C++ってscanf()に相当することをしようと思ったらscanf()使うしかないわけ?
>>653 scanf相当って「型を指定して得る」って事をいってるのか何のことなのか意味が分からん
std::cinでは足りないと?
656 :
651 :2009/02/05(木) 00:26:56
>>654 すみません、色々間違えてました
this->~Buffer() でデストラクトしてるのに
deleteで再度デストラクトしていいの?
2重デストラクトって問題ないの?
>>655 std::cinって書式付き入力変換できるの?
できないなら、全然足りない。
だったらstdinの中にはいってるからfgetして必要なデータ型に直せば?
つまり、iostreamは使えないライブラリだってことね。
またそのパターンかよw
>>661 (お前にとって)使えないライブラリだ、ってことなら正しい。
scanfは危なすぎてC++でまでわざわざ使う気にはなれんなぁ 入力には少々面倒でもcin使うわ ostreamは本物の糞だから絶対使わないけど
どう糞なのか教えていただけないでしょうか
今宵も大暴れの予感 age
>>665 printf("%08.3f %+04.1f\n", x, y);
std::cout << std::setw(8) << std::setprecision(8) << std::setfill('0') << (int)(x*1000)/1000.0 << " "
<< std::setw(4) << std::setprecision(4) << std::setfill('0') << std::setpos << (int)(y*10)/10.0 << std::endl;
Cスタイルキャスト(笑)
>>667 setprecisionの引数はそれぞれ3と1では?
setprecisionの意味調べ直せカス
std::setpos? std::showpos のことか?
boost::formatの支援がない環境ではoperator <<(ostream &, T)なんて使わんな
>>650 operator delete () 関数の呼び出しは問題ないが
delete 演算子の適用は未定義動作。
%fなんだからfixedがいるはず。
g++で、あるヘッダーファイルを定義するとき、 クラス定義とか関数のプロトタイプ宣言とかを インクルードガードする分には問題ないのですが、 クラスのメンバ関数の実装とかを書くと インクルードガードしているはずなのに multiple definition って言われてしまう気がするのですが。 しかも必ず再現するわけではないようで… …これは俺が悪いのですかね?
2カ所以上に定義書いてないだろうな…
これをいろいろなファイル(他のヘッダーファイルA.hやB.h)からインクルードしてみています。 ↓↓↓ #ifndef PREVENTION_OF_OVERLAPPING_INCLUSION #define PREVENTION_OF_OVERLAPPING_INCLUSION 1 class test_for_overlapping_inclusion { int m_hoge; public: test_for_overlapping_inclusion(); int foo(int num);//このメンバ関数を有効にします。 }; test_for_overlapping_inclusion::test_for_overlapping_inclusion() {m_hoge=97;} int test_for_overlapping_inclusion::foo(int num) {return num+m_hoge;} #endif
>>677 定義をヘッダファイルに書いちゃダメ
それだと多分毎回フルコンパイルしないといけなくなる
ポインタってNULL状態でもメモリを消費しますか? 例えば int *pn = 0; って書いて if(pn) っていう風に処理できるのだからひょっとして4byteぐらいは固定で 消費してしまうなんて事はないですか?
>>679 ポインタ変数も普通の変数とその辺りは大差ない。
メモリを消費するかもしれないし、レジスタしか消費しないかもしれない。
もっと極端に、最適化で消えてなくなるかもしれない。
>>679 そのとおり。つーかC言語レベルで重症だから変数について学びなおしてこい。
>>676 >>678 メンバ関数に対してinline指定したらなんか通るようになった。
Why??????
>>682 インライン化されたからだよ
リンカがシンボルを参照する必要がなくなったから
>>684 なるほど。ありがとうございます。
まあまさかGCCのせいなわけは無いでしょうから俺のせいなんですよね?
皆さんはこんなこと無いですよね?
>>685 a.cppとb.cppからそのヘッダを参照していたとすると、
それぞれ独立にビルドしてa.oとb.oの両方にfooの実体が含まれることになる。
すると、a.oとb.oをリンクするときに同じ名前の関数が複数あるからおかしなことになる。
>>686 >>687 読ませていただきました。
「それぞれ独立にビルドして」
という状態がポイント、ということでしょうか?
そのためにインクルードガードしたつもりでもなっていないということでしょうか?
グローバル変数を宣言するとき static つけたときとつけなかったときの違いは分かるか?
boostのthreadの昨日を使いたいのですがbjamでビルドしてもエラー麦価で手津空けませ印 解決策plz
コンパイル環境とエラー内容を詳しく聞かせてもらおうか。 それとエラーと思っていたけど実は警告でしたーだったら(^ω^ #)ビキビキ
windows、VC6.0、boost_1_37_0、boost-jam-3.1.17-1-ntx86つ買ってます Let's Boostというサイトのディレクトり公正、びるどテジュんをま違いなく倣っているのですが ここいコピペしきれないほどのエラーはいてあます ...found 4880 targets... ...updating 988 targets... compile-c-c++ bin.v2\libs\math\build\msvc-6.0\release\link-static\threading-mult i\acosh.obj acosh.cpp .\boost/math/tr1.hpp(179) : error C2632: 'long' と 'long' の 2 つの型指定子のあ いだにコードがありません。 .\boost/math/tr1.hpp(180) : error C2632: 'long' と 'long' の 2 つの型指定子のあ いだにコードがありません。 .\boost/math/tr1.hpp(181) : error C2632: 'long' と 'long' の 2 つの型指定子のあ いだにコードがありません。 .\boost/mpl/aux_/integral_wrapper.hpp(88) : fatal error C1506: ブロックが大きすぎて 、コンパイルできません。 こんあ漢字にえねんと・・・
>>689 >>グローバル変数を宣言するときstatic つけたときとつけなかったときの違い
static変数は開始時に0で初期化されることが保証されている
…という話ではないですよね。
そういえばstaticつけるとそのファイル内でしかスコープが有効でないんでしたっけ??
>>692 1.37がVC6.0に対応しているかどうか調べた?
なるほお VCのヴァージョンをあげるか簿尾sとのヴぁー所のwさげるかです根 とりあえず古いBoostでたえmしてみることにします どうもありがとうございましいた
std::string str; と std::basic_string<char> str; は等価だよな?typedefなんだし。 それなのに std::string::iterator it; がおkで std::basic_string<char>::iterator it; はコンパイルエラーになるのは、なんで?
>>697 std::basic_string<char> str;
が通るのは確認したのか?
お前の処理系が古すぎて、basic_string自体無いとか?
>>698 遅レスすまそ
とおらねかった。
組み込みうぜー
そして確認不足でスマソ
いつもの感覚でやってたorz
>>699 std::basic_string<char, std::char_traits<char>, std::allocator<char> > str;
ここまで書けばコンパイル通る
>>696 さすがに、そろそろ新しいの買った方がいいんじゃないか?w
VS2008ならStdで6.0のPro相当だから安いよ。
MSのイベントでタダで配ってたりするらしい。
開発環境がVC6ってカキコよく見かけるが 新しいのに移行しないで6を使い続けるってなんか理由あるのか? 古いの保守のため?
ISO C++(VS2003以降含む)とVC++6は全く別の言語だから
Visual C++ 2005 でOCCI環境10.2gでDBと接続してやっているんですが、 DBから内容を取り出すときにヒープが壊れていますとエラーが出ます。 C++プロパティ(文字:Unicode) std::string name = ""; name = rs->getString(1); ←getStringの時点でヒープが壊れてしまい(全角文字8文字以上の場合) エラーを吐き出してしまいます。 C++環境でgetString以外、またはgetStringをこう改良したら、壊れないっていうのってないでしょうか? google先生に助けを求めて二週間以上立っても俺には見つけれませんでした… 最終的な形は、取り出した値をString^ に変換するかんじです・・・ よろしくお願いします
705 :
704 :2009/02/05(木) 21:57:28
失礼しました、DBはVARCHAR2で作っています
rsがどこからでてきたんですか><;;;
オープンソース開発とかだと、VC6のプロジェクトファイルであれば それ以降のバージョンすべてで使えるという利点があるが、 普通の人には関係ないな。
結局VCでしか使えないうえに、 言われてるように仕様が変わりすぎて、vc6とvs200x使ってる人たちが協力するとかありえないだろw
VCって何であんなにクソなの?
710 :
704 :2009/02/05(木) 22:12:28
>>706 失礼しました、流れはこんな感じです(部分抜粋)
private:
Statement *stmt;
ResultSet *rs;
をしておき、オラクルにログイン
this->stmt = conn->createStatement();
rs = stmt->executeQuery("SELECT文");
std::string name = "";
String^ Name = "";
while(rs->next()){
name = rs->getString(1);
}
Name = gcnew String(name.c_str());
nameに入る時点ではなく、getStringの時点でエラーが出てるみたいです(ブレークポイントの位置的に)
一応MSの擁護もしておくと、VC6の頃はC++の標準規格自体がなくて ベンダが好き勝手にオレオレ実装するのが当たり前だった頃だから仕方なかった
あー。 そうだったんか。 俺はまたてっきりIEの時に標準規格を無視してJavaScriptやHTMLタグの独自実装をした時と同じような現象かと思った。
size_t って std::size_t が正しいんだよね? これって何のtypedefなの?unsigned long?
>>713 <cstdlib>をインクルードしたならstd::size_t。
元の具体的な型は決めようがないからこそtypedef。
まあ、std::size_tは符号無し整数型だという決まりはあるけど。
>>714 サンクス
あと、wchar_tはstd名前空間じゃないよね?
これは
intとかdoubleとかと同じ組み込み型そのものだから」
という理解で良い?
class A{ int m_a; public: int* operator&(){return &m_a;} }; このようなクラスのオブジェクトのアドレスを取得するにはどうしたらよいの? 具体的には CComBSTR 型変数のアドレスが取得したい。
>>716 なんかあったねそういう状況。
確かキャストとかを変に重ねて解決するんじゃなかったっけ?
Boostにそういう状況でもアドレスを取得するためのライブラリがあった。
>>716 boost::addressofの実装はこんなんなってた
reinterpret_cast<T*>(&const_cast<char&>(reinterpret_cast<const volatile char &>(obj)));
size_tはグローバル名前空間にも無いとだめじゃなかったか?
戻り値が参照の関数でエラーが起きたらどうやって呼び出し元に伝えるの? 例外しかないって、マヌケじゃない?
意味がわからん。 ポインタだったらnullがあるのにってこと?
>>722 どういうこと?
君はどういう実装だったらうれしいの?
例外と参照の意味を考えればそんな変な仕様じゃないと思うがね。
例外使う奴って素人だろ
あんまり参照のリターン値ってつかわんよね。 return *this; くらい?
素人は例外を使えないと思うんだが。 玄人は例外安全を徹底するだろうが。 …じゃあ例外は誰が使うんだ!?!?
>>728 クロウトはせっかく例外安全を徹底してるのに、例外をつかわんの?
>>727 ostream&と自作クラスを受け取るように
operator <<をオーバーロードし、
ostream&を返す
っていう例があるじゃん。
使うかどうかは怪しいが。
return os;
>>729 使うだろうが、使いたくはないんじゃね?
俺は決して玄人じゃないから分からんがね。
みんななんだかんだ言っても、 結局C++の事が大好きなんだろ!? 正直に言えよ。好きだって。 このツンデレめ。
>>722 俺はNULLオブジェクトを作って、エラーがあったら戻り値でそれを返してる。
クラステンプレートとテンプレートクラス ってどちらが正しい用語?
>>734 class template
function template
じゃね?
…絶対かと問われると不安になってきた
>>688 インクルードガードの考え方が大幅に間違ってるがもう解決したんだろうか。
実際にコードがどうなるか自分で展開してみるといいんだが。
クラステンプレートはクラスのテンプレート テンプレートクラスはテンプレートから作ったクラス 要するにtemplate<typename T> class Hoge{/*...*/}; がクラステンプレート Hoge<int>がそのテンプレートクラス std::vectorはクラステンプレート std::string(==basic_string<うんたらかんたら>)はテンプレートクラス
ひとまず解決したのですが。。。
>>736 インクルードガード…複数インクルードしたヘッダファイルをたどったときに同じヘッダファイルが重複するのを防ぐためのもの
ってことでしょうか?
a.cppでインクルードしてビルドすることとb.cppでインクルードしてビルドすることは全く別にコンパイラは並行作業するってことですか?
>>739 インクルードはプリプロセッサ指令に従ってファイル結合してるだけなんだよ。
だからヘッダは宣言のみで実体を書いてはならない。
ヘッダにCという実体を定義してしまったら、
a.cppとb.cppのオブジェクト内にそれぞれCという実体が入ってしまう。
そうするとリンクするときにCはa.cppとb.cppのどちらを使えばいいのかリンカが分からなくなる。
インクルードガードはそれでいい。
コンパイラはコンパイルごとに終了してるのでソースファイルごとに独立して作業。
(Makeツールが何度もコンパイラを起動している)
ビルドとコンパイルは意味違うからな。
>>740 >>コンパイラはコンパイルごとに終了してるので
>>Makeツールが何度もコンパイラを起動している
なるほどそうだったんですね。
合点がいきました。
その辺ブラックボックスでした。勉強しなきゃ。
#undef ってあんま使えなくね? bccにて #define HOGE 1 std::cout << HOGE <<std::endl; ってやったら1が出力され、そのうしろに #define HOGE 2 std::cout << HOGE <<std::endl; ってやったらマクロの多重定義の警告が出たが2が出力された。 ここまではいいんだがその後に #undef HOGE std::cout << HOGE <<std::endl; ってやったら未定義って言われた。 俺は前に定義されているマクロと自分のマクロの重複の影響を除くためにあるのかと思ったらそういう動作はしてくれないみたいだ。 …じゃあ何のために#undefがあるんだろう?
#define HOGE 1 std::cout << HOGE <<std::endl; #undef HOGE #define HOGE 2 std::cout << HOGE <<std::endl;
>>743 それが正しいんだろうけど、俺的には
誰かの作ったヘッダのインクルードとかで
知らず知らずに定義されていたHOGEを
俺が新たに#define HOGE 2ってしちゃった場合、
#undef HOGE
をしとけばHOGEの定義がヘッダの物に戻るのかと思ってた。
まあそんなの役立つ機会無いだろうけど。
つーかマクロが重複したらなぜコンパイルエラーにしないのだろう?
745 :
デフォルトの名無しさん :2009/02/06(金) 02:40:45
いいID出たので記念パピコ
コンパイラによっては前処理シンボルの push, pop が出来るぽ(VCとか)。 でも前処理の話はCスレとかの方が妥当かもね。
747 :
632 :2009/02/06(金) 03:46:08
クロスDLL問題(?)で再度質問させて下さい。以下でうまくいきません。 void dll_func(vector<shared_ptr<X>, DllAllocator<shared_ptr<X> > >& v) { v.push_back(shared_ptr<X>(X::create())); } void main_func(void) { vector<shared_ptr<X>, DllAllocator<shared_ptr<X> > >& u; dll_func(u); } template <typename T> struct DLLAllocator : std::allocator<T> { ... pointer allocate(size_type sz, const void*) { return HeapAlloc(GetProcessHeap(), 0, sz*sizeof(T)); } void deallocate(pointer p, size_type) { HeapFree(GetProcessHeap(), 0, p); } }; struct X { ... static void* operator new(size_t sz) { return HeapAlloc(GetProcessHeap(), 0, sz); } static void operator delete(void* p) { HeapFree(GetProcessHeap(), 0, p); } }; クラスXのnewとdelete、それからDLLに渡すvectorのアロケータをHeapAllocとHeapFreeに変更したのですが駄目で、 もうどこをどうすればいいのか…。
748 :
632 :2009/02/06(金) 03:47:25
書きこんでみてから気付いたけど<X>って<><>に見間違う…
>>747 もし、双方のvectorの実装が別物だったら、うまくいかないけど、それは大丈夫?
あと、Xにはnew/delete関数の定義は不要。shared_ptrがうまいことやってくれる。
750 :
632 :2009/02/06(金) 04:28:53
>>749 main+dllともにVCの同じソリューション内で同じ構成でビルドしてます。
したがって(というのも変ですが)vectorの実装は両方とも同じです。
両者ともstd::vectorです。
> あと、Xにはnew/delete関数の定義は不要。shared_ptrがうまいことやってくれる。
ΩΩΩ<な、なんだってー
みなさん、プログラム関係の仕事に就いてる方も多いのでしょうが、 数学や物理の知識も豊富なのでしょうか? 自分ははっきり言って高校生レベルにも満たないレベルだと思います。 もし必要なら今からでも高校生向けのテキストを買って勉強しようと思うのですが、、
752 :
デフォルトの名無しさん :2009/02/06(金) 05:26:42
ほとんどの場合、いらない。
何言ってんだお前 誰でも簡単に開発が出来るように作られたソフト、言語は、誰でも出来て当たり前なんだよ 数学なんか出来て当たり前だろ。 資料もほとんど日本語版はスルーだから英語中国語も必須だし、ググって解決できるのは最初だけだ 各専門分野が必要だと、自分を磨いて初めて社会の一員になれるんだと信じてがんばっても 結局、開発期限に間に合わなくて損害賠償で首吊るんだよ。社長がだけど 今の時代一番IT人口が多いというか出来て当たり前の時代すらとっくに過ぎてて、人件費の安い国からのITドカタに勝てる自身あんのか? 知ってるとは思うが、あいつら九九も桁違いだぞ。 技術ごっこが趣味で、ゲームソフト買う代わりに開発ソフト買うとかいうレベルなら何もいらない
スレ違い過ぎてフイタ
俺は中学校から始めたけど、幼稚園からやってるやつには勝てる気がしない あいつらの基本思考回路は母国語じゃなくて機械語だ
>>722-733 例外を使うか使わないかがスタイルで選べるように思ってるのがもうおかしい。
例外使わないというなら new もできないし標準コンテナも使えないし、
コンストラクタの失敗を扱うのが相当めんどくさい。
「俺は例外使わない」って言ってる奴でも new や標準コンテナは平気で、
コンストラクタの中でも余裕で使ってたりする不思議。っていうかただの無知だろ。
>>714 違う。
<stdlib.h> をインクルードしたら size_t のみ。
<cstdlib> をインクルードしたら size_t と std::size_t の両方。
>>756 new(std::nothrow) を知らないのは無知
そして例外を完全に使わないスタイルの人は
STL は使わず独自のものを作るだろう。
>>722 参照は初期化されているのが前提だから、エラーは例外で返すのが当然。間違ってもnullを返すのは止めて欲しい。迷惑だから。
エラーを返す関数で参照を返すのがそもそも誤り。どうしてもエラーを返したい場合は、boost:::optionalを使えばいい。
761 :
632 :2009/02/06(金) 13:51:26
>>747-750 の続きです
1. スレッドAがスレッドB(main_func)を起動、このときAからBへvector<shared_ptr<T>, DllAlloc<T> > vをポインタ渡し
2. スレッドBはvをDLLに渡す:main_func内でdll_func(vector<shared_ptr<T>, DllAlloc<T> >& v)を呼ぶ
3. dll_func内でvに要素追加:v.push_back(shared_ptr<T>(T::create()))
4. dll_funcから処理が返った後、main_func内でvは問題なく使える
5. スレッドB終了時、例外で落ちる。
main_funcでvの要素を作成した場合には、dll_func内でその要素の値を読み書きしても落ちませんでした。
些細なことでも結構ですので、心当たりか手がかりがあればお願いします。
762 :
632 :2009/02/06(金) 13:52:23
↑ DllAlloc<T>はDllAlloc<shared_ptr<T> >の誤植です。
>>761 固定手順で問題が再現できるなら、あとはさっさとデバッガつないでトレースなりなんなりしろよ。
スレ違いだし。続けたいんなら VC++ スレ行ってくれ。
・・・あれ? VC++ の専用スレは無いのか? Visual Studio ならあるみたいだけど。
dllが解放されるときにshared_ptrが解放されてるだけじゃね?
766 :
632 :2009/02/06(金) 21:37:52
いろいろ試行錯誤してたら遅くなりました。だいぶ切り分けられました。
vectorは関係ないみたいです。
thread A:
shared_ptr<Test> test; // これをDLL側で構築したい
ThreadB(test); // スレッドを作成してThreadB::runをコール
---
struct ThreadB {
shared_ptr<Test> test_;
ThreadB(shared_ptr<Test>& test) : test_(test) {} // testを受け取る
void run(void) { dll_func(test_); } // スレッドが走るとDLLを呼ぶ
};
---
void dll_func(shared_ptr<Test>& test) {
test.reset(new Test); // これがアウト
}
ThreadBから抜けるときに例外が発生します。
shared_ptrの使い方間違ってるでしょうか。
>>765 > Avoid using unnamed shared_ptr temporaries to save typing; ...
引数の評価の途中で例外が発生するとメモリリークが発生するという話は
Effective C++にもあって、ちょうどそこを昨晩読んだところでした。
>>763 DLL間のオブジェクトのやり取りに便利というのがshared_ptrのもう一つの有効な使い道みたいなので(昨晩知りました)
ここで勘弁して下さい。
template<typename T> struct test{ struct type{}; }; template<typename T> void f(){ //VC++ではコンパイルできない。typenameを除くとコンパイルできるが今度はgccではコンパイルできなくなる。 struct fn{ static void g(){ typename test<T>::type i; } }; } int main(){ f<int>(); return 0; } コンパイラの挙動としてはどちらが正しいのでしょうか?
g++
根拠は?
規格読め
それがコンパイルできないのは古いVCまでだよ
C++でJavaでいうユーティリティ(静的メンバだけのクラス)を 作りたいんだけど、C++だとやり方が ・クラスの静的メンバ関数として定義 ・名前空間内で関数定義 の2つ思いつくが設計上どういう違いがあるのかわからん オープンソースだと後者をよく見かけるんだが、これがC++風なの?
普通の関数をわざわざメンバ関数にする必要は無いかと。 まあ、using を禁止する意味で、敢えてメンバ関数にするというのなら分かるけど。
もちろん、完全にユーティリティの場合の話だからね。 静的メンバ関数自体は有用なものだ。
>>774 なるほど。
C++だとJavaのようになんでもクラス化は間違い?
プログラミング言語C++、effective C++は読んだのだけど
これは設計に関しては今でも通じる?
最近のC++のプログラミングスタイルを学びたいんだけど
地道にオープンソース読んでいくしかないのかな
最近のプログラミングスタイルならboostだろ JK
>772 クラス ・アクセス制御ができる ・継承ができる ・テンプレートの引数とかtypedefで使える --> Traitsなんかを参照。 名前空間 ・開いているので別の所で関数などを追加できる。 といった特徴があるので適材適所で。
>>775 そもそも Java は普通の関数を作れないから仕方が無い
779 :
777 :2009/02/07(土) 02:18:20
Traitsの所はなんか変だな。ちょっと修正&追加 ・テンプレートの引数とかtypedefで使える --> Mix-in(Policy)とかに使える。 ・クラステンプレートにできる --> テンプレートの特殊化で色々なことができる。Traitsなんかを参照。
>>766 スレッドまで絡んでるのか。こんどはスレッド使わずにやってみればいいんじゃね?
boost::shared_ptr の話なら Boost スレに行ってもらったほうがいいような気がする。
っていうか、なんで一番的確と思われる >763 のアドバイスを無視してるの?
delete/delete[]についての疑問なのですが 「配列へのポインタ」を「配列でないポインタ」へキャストした場合、"delete"と"delete[]"のどちらを使えばよいのでしょう? char *p0 = new char[4]; int *p1 = (int *)p0; delete[] p1; なのか delete p1; なのか
delete[] (char*)p1;
>>781 その p1 はその型のままでは何にも使えない。
delete[] (char *) p1;
>「配列へのポインタ」を「配列でないポインタ」へキャストした場合 それらの違いは何を想定している? その以下の例とは異なるようだが。
>>782 dクス
つまりnewの際の型にしてやる必要があるということでしょうか
delete[] p1; も delete p1; もNG?
>>786 そもそもそのキャスト自体が異常。どうしてもやりたいならreinterpret_castを使え。
>>785 例は簡略化してますが、バイト列を構造体にキャストして利用する場合などです。
ダメだこりゃ。
>>783 たしかにそうですね(^^;
p1にアドレス入れないといけませんが64bit幅だと4バイトどこかを破壊する事に
freeはvoid*だったけどdeleteは型が意味もつんかな new/deleteのアルゴリズムどっかに書いてないか?
>>790 いちおう言っておくが、 int としてもアクセスできる保証は無いよ。
じゃあ、お前は何を保証するんだよ
俺じゃなくて、規格が char* にキャストで戻せば元通りに使えることを保証するよ。
>>791 new[]で確保したメモリは、こうなってるみたいよ。ポインタは先頭オブジェクトを指してる。
| 数 | obj | obj | obj | obj |
実装依存
格納の仕方は違うだろうけど、795からわかることは「delete呼ぶにはオブジェクトサイズが必要」ってことだな。要素数はいらないということも。
gcc 3.4.5を使っています。 以下のコードはどうしてVC++では通るのにgcc 3.4.5では通らないのでしょうか? テンプレートクラス内のテンプレートクラスの特殊化は駄目なんでしょうか? template<typename Expr> struct testyhand{ template<unsigned int i> struct test; template<> struct test<0>{ enum{ value = 0 }; }; template<> struct test<1>{ enum{ value = 1 }; }; };
800 :
デフォルトの名無しさん :2009/02/08(日) 14:16:39
>>800 error: explicit specialization in non-namespace scope `struct testyhand<Expr>'
error: enclosing class templates are not explicitly specialized
error: template parameters not used in partial specialization:
error: `Expr'
error: explicit specialization in non-namespace scope `struct testyhand<Expr>'
error: enclosing class templates are not explicitly specialized
error: template parameters not used in partial specialization:
error: `Expr'
>>802 ぁーそれ俺も最近悩んだわ。
特殊化はクラススコープの外で書いてあげないと怒られる。
規格でいえば 14.5.2 あたりからかな
VC++2008です。ソース分割された静的変数を任意位置で初期化したいんですがどうすればいいですか? ソースは以下のようになっています。 //main.cpp #include "src.h" int main(){ init(); loop(); } //src.h class Test{ static int num; //private } int Test::num = otherclass::getnum(); //これをinit();の直後に実行したい
静的メンバ変数の初期化は、 各翻訳単位内では実体定義の順番通りに実行される。 翻訳単位間での実行順は未規定。 これらの初期化の実行は、main 関数より前に行われる。 要約すると、init(); の後に初期化処理を記述するしか無い。
こういう場合は Singleton パターンが有効。 Singleton パターンでググれ。
>>806-807 迅速な回答ありがとうございます。
早速Singleton パターンで調べてみます。
811 :
632 :2009/02/09(月) 11:24:54
>>780 マルチスレッドとdllとshared_ptrの問題みたいなので他スレで聞いてみます。
>>763 というのはデバッガ使えという話ですか?
追ってはいるんですが、shared_ptrの参照カウントを減らすところで
すでにdeleteされているものをdeleteしようとしていることくらいしか分からないです。
とりあえず、スレッドBが呼んだdllで確保したメモリをスレッドAで解放しなければ
正常に動作するところまでは確認しました。
812 :
632 :2009/02/09(月) 12:53:22
>>811 は少し不正確でした。無視して下さい。
「すでにdeleteされているものをdeleteしようとしている」わけではなくて
「deleteするところで例外が発生する(delete先はこの時点で生きてるっぽい)」でした。
デストラクタで例外でも投げてるとか
814 :
632 :2009/02/09(月) 13:14:07
>>813 正確には <memory> 内で
~shared_ptr ⇒ _Ptr_base::_Decref ⇒ _Ref_count_base::_Decref
で、_Ref_count_base::_Destroyが_Ref_count_base::_Getptrの返り値を
deleteしようとするところで例外が起きます。
参照カウントはこの直前で1から0に減らされてます。
_Getptrの返り値は0ではないです。
スレッドを使ってもDLLを使わなければOK、DLLを使ってもスレッドを使わなければOKでした。
マルチスレッドスレで聞いてみます。
ランタイムエラー R6025 pure virtual function call の再現方法(エラーの発生手順)をご存じありませんか? 調査してみたところ、 無効なポインタを使用して関数が呼び出された場合に発生する という情報があったので試してみたのですがR6025は発生しませんでした。
>>815 pure virtual function を call するんだ。
>>815 サンプルコード
class A;
void fcn( A* );
class A {
public:
virtual void f() = 0;
A() { fcn( this ); }
};
class B : A {
void f() { }
};
void fcn( A* p ){ p->f();}
B b;
void main(){}
>>809 なるほど、すっきりと書く事ができました。ありがとうございました
クラスで動的な部分が値を保持するいくつかの変数だけだとしたら 他のメンバは、特に関数は全て静的にするのが常識なんでしょうか? やっとこの辺が理解できてstaticを付けまくりたくてたまりません
そんな常識はありません。 メンバ変数にアクセスしない関数を静的にするのは一つの見識ですが。 尤も、そんな関数ばかりならnamespaceにすることも検討すべきかと。
普通はメンバ関数は大抵メンバ変数にアクセスする処理ばかりになるはず。 メンバ変数にアクセスしないものもたまーに存在するが、そう多くないはず。
メンバ変数を参照しない関数は高確率でstaticにしてるな
メンバ変数を参照してても関数内で動的クラスの動的変数を参照する記述なら問題なくないですか?
まず正しく用語を使え。 いらぬ誤解を招く。 そしてコンパイルとおらねえだろ。
おそらくインスタンスと言いたいのだろうな
これコンパイル通らないのか 納得 staticはメンバ変数にアクセスしない関数だけだね
例えばstd::stringのような有名なクラスを継承した自作クラスを作って ライブラリにしようとした場合、そのstd::stringは 仮想継承させておくべきなの? それとも仮想継承にはしないでおいた方が良いの? なんか、既存の文化とか慣習とかあります?
ない。仮想継承は動的に継承を解決する。 ライブラリ内で自作stringが仮想継承を必要とするならばそうするべきだが、 別にそれ以外のケースで文化とか慣習はない。
>>827 慣習っていうならそもそもSTLを継承はしない
参照透過性のある関数を動的に生成したいのですが(現時点ではインタプリタっぽい実装になっているので高速化したい)、使うのにベターなライブラリやインラインアセンブリの命令などはありますか?
BaseクラスがテンプレートクラスBase<type_T>だとします。 template <typename type_T> class Base {〜} このときBaseを継承したDerivedクラスを考え、これもテンプレートクラスにします。 template <typename type_T> class Derived : public Base {〜} …ここでDerived<type_T>のメンバ関数の中からBase<type_T>のメンバ関数foo()を呼ぼうとしたらコンパイルエラーになりました。 そこでいちいちBase<type_T>::foo()の様に指定したらうまくいったのですが、 これ(Base<type_T>::)って省略できないものなのですか? テンプレートじゃなきゃできますよね?
833 :
832 :2009/02/10(火) 00:52:22
テンプレートクラス →→クラステンプレートです
typedef Base<type_T> base; base::foo();
2番目の宣言がおかしくね。 template<typename type_T> class Derived : public Base<type_T> じゃね? 省略したらどうなるんだろう。
836 :
832 :2009/02/10(火) 00:59:55
趣旨がわかりにくくて済みません。 Derived<type_T>のメンバ関数の中bar()からBase<type_T>のメンバ関数foo()を呼ぼうとしている状況です。 つまり template <typename type_T> void Derived<type_T>::bar() { foo(); } としたらコンパイルエラーになりました。 そこでいちいち template <typename type_T> void Derived<type_T>::bar() { Base<type_T>::foo(); } の様に指定したらうまくいったのですが、 これ(Base<type_T>::)って省略できないものなのですか? テンプレートじゃなければ継承しているんですから要らないですよね?
通る template <typename T> struct Base { void foo() {} }; template <typename T> struct Derived : public Base<T> { void bar() { foo(); } };
838 :
832 :2009/02/10(火) 01:01:51
>>835 すみませんそれ付けていました。
書き間違いです。
(試しに省略したらさすがにコンパイルエラーでした。)
839 :
832 :2009/02/10(火) 01:02:33
>>837 あれれ??
ちょっと待っててください。
BaseがTを使用してなければ通るんじゃね。 Base<T>じゃなくてBaseとして宣言されたstructを呼び出してるだけなんだし。 省略はできないし、すると意味が違うだろう。 Base<void>とBase<T>とBase<A>は全部別コードになるよ。
841 :
832 :2009/02/10(火) 01:19:56
再現性を確認しました。 template <typename type_T> class Base { public: void foo(); }; template <typename type_T> class Derived : public Base<type_T> { public: void bar(); }; template <typename type_T> void Derived<type_T>::bar() { //foo(); //Base<type_T>::foo(); } です。本文中で Derived<int> hoge; Derived<double> piyo; の様にインスタンス化させています。この条件の下で、 foo(); でも Base<type_T>::foo(); でも両方ともBCCではコンパイルOKですが、g++では前者がエラーで後者がOKです。 error: there are no arguments to `foo' that depend on a template parameter, so a declaration of `foo' must be available error: (if you use `-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
規格14.6.1 の paragraph 3 だな。 大域名前空間にfooを定義すれば、そちらが呼ばれる。
.hppってなんですか?
ファイル名の一部。拡張子。 C++言語的には何の関係も無い。
>>845 の「C++言語的」 というのが「言語仕様」のつもりなら
確かにファイル名がどうとかまったく関係ない。
/*
でも、拡張子がファイル名の一部かどうかは環境次第なので
>>845 は誤り
*/
一般的な解釈では
>>846 の通り。
定義も含むのがhppで宣言だけならhだと思ってた
難しいですねテンプレート。 このあたり直感的でないのはまだテンプレートが新しめの機能だからですかね? 私方式の Change the call from f() to B<T>::f(). だと注意書きがありまして Note however that this might not give you what you want if f() is virtual, since it inhibits the virtual dispatch mechanism. だそうですが、これってどういう事ですか? f()が仮想関数としてB<T>でもD<T>でも定義されているときに、 B<T> *p=new D<T>; p->f(); とすると、本来なら仮想関数なので期待通りにD<T>::f()が呼ばれて欲しいが、記述上残念ながらB<T>::f()が呼ばれてしまいますよ ってことですか?
そ
ありがとうございます。 連続で聞いて申し訳ないですが Change the call from f() to this->f(). の Since this is always implicitly dependent in a template, this->f is dependent and the lookup is therefore deferred until the template is actually instantiated, at which point all base classes are considered. って言うのは、 this->が解決されるのがD<T>が具体的にインスタンス化された時だから、そのときにはもう親クラスのfoo()が継承されているから大丈夫なんですよ ってことですか?
>>853 そんなてめぇが疑問に思ってるような
コードを人様に見せる場面で使うんじゃねぇウンコ
>853 ちょっと違う。 template 中の名前解決は 2 回に分けて行われる(これは two phase lookup と言われている)。 具体的には宣言された時と、インスタンス化された時の 2 回。 テンプレート型パラメータに依存している名前はインスタンス化された時に、それ以外は宣言時に解決される。 f() はテンプレート型パラメータに依存していないため宣言時に名前が解決され、結果として、テンプレート型パラメータ依存の 基本クラス B<T> まで見に行かない(見に行くのはインスタンス化された時だから)。 this->f() にすると、this がテンプレート型パラメータ依存であるため、this->f() もテンプレート型パラメータ依存となる。 結果、f の名前解決がインスタンス化時点となり、テンプレート型パラメータ依存の B<T> の中まで探しに行くことになる。
>>854 別に「各自の自慢のコーディングを人様に教え合うスレ」ってわけじゃないから良いじゃないですか。
むしろ自分しか見ないコードの中で自分が疑問に思っているコーディングをしたらひんしゅくすら買えない謎のバグを仕込みかねませんし。
>>855 ありがとうございます。
本気で分かりやすかったです!
>>856 すみません投稿中で見てませんでした。
今から見てみます。
ありがとうございます。
861 :
埋め :2009/02/10(火) 22:56:11
埋め
862 :
埋め :2009/02/10(火) 22:56:33
埋め
863 :
埋め :2009/02/10(火) 22:56:54
埋め
864 :
埋め :2009/02/10(火) 22:57:16
埋め
865 :
埋め :2009/02/10(火) 22:57:37
埋め
866 :
埋め :2009/02/10(火) 22:58:20
埋め
867 :
埋め :2009/02/10(火) 22:58:28
埋め
868 :
埋め :2009/02/10(火) 22:58:50
埋め
相談スレで相談するなとかどんだけ。
自分が理解できないものを見なかったことにしたかったのでしょう。その証拠にほら、埋め嵐。
おもしろいな
もういっぺんいってやろう
>>853 そんなてめぇが疑問に思ってるような
コードを人様に見せる場面で使うんじゃねぇウンコ
872 :
埋め :2009/02/11(水) 11:06:00
埋め
873 :
埋め :2009/02/11(水) 11:06:24
埋め
874 :
埋め :2009/02/11(水) 11:06:44
埋め
875 :
埋め :2009/02/11(水) 11:07:12
埋め
876 :
埋め :2009/02/11(水) 11:07:34
埋め
877 :
埋め :2009/02/11(水) 11:08:19
埋め
878 :
埋め :2009/02/11(水) 11:08:37
埋め
879 :
埋め :2009/02/11(水) 11:08:58
埋め
880 :
埋め :2009/02/11(水) 11:09:20
埋め
881 :
デフォルトの名無しさん :2009/02/11(水) 11:12:03
埋めるな
埋めてんじゃねーよ
埋めるぞ
ずいぶん可哀想な奴がいるな。
885 :
埋め :2009/02/11(水) 14:54:40
埋め
標準またはboostに数学の順列の数、組み合わせの数を求める関数はないですか?
>>886 ないと思う
next_permutationで生成しながら数えれば
while (std::next_permutation(rng.begin(), rng.end())) count++;
自分で計算する関数作ったほうがいいな。 公式あるし、オーバーフローに気をつければあとは楽。
そんな難しいロジックじゃなさげだな 自分で作った方がパフォーマンス調整しやすいし作ってみれば?
n 個のものから m 個を取り出す順列の数 n!/(n-m)!
>>887-890 レスthx
boostには数学に関して結構マニアックな物まであるのに、ないとは意外でした。
簡単に実装できるものなので自分で書くことにします。
すぐオーバーフローして使いどころが限られるから、 あるいは使い方がケースによってまちまちだからなのかねえ
893 :
デフォルトの名無しさん :2009/02/11(水) 23:03:10
クラス設計で質問 1 メンバにオブジェクト持たせるとき、ポインタで持つのが当たり前? STLのコンテナとかそのクラスのデフォルトコンストラクタが空とかなら直で持ってもいいんでしょうか 別に実装隠したいわけでもない場面でもpimplイディオムでやらなきゃいけないのかな Javaと同じようにやろうとすると面倒くさすぎる 逆にクラスを使う人間にこういう事を考えさなくてよいよう、デフォルトコンストラクタは全クラスで定義すべき? 2 vectorメンバのsetterを下のやり方でやってるんだけど もっと効率良いやり方あったらダメ出し下さい void Foo::set_vec(const std::vector<int>& val){ vec_(val); }
>>893 速度で言うなら、中身がPOD型だから
resizeしてmemcpyする方法が使用可能ではある
>>893 ポインタで持たないと何が面倒なんだ?
vec_ = val じゃないの?
>>891 >>892 もし作るならnCrは再帰を利用し、漸化式から作るようにした方がいいよ。
n!/(r!(n-r)!)でやると、あっという間に途中式(階乗の部分)がオーバーフローするけど漸化式を利用した方法ならそれなりに持ちこたえられるらしいです。
boostにない理由は分からないけど、まあたぶん、nCrにおいてどうせ作るならnやrが整数でない場合についても計算できるようなライブラリにしないとなんか不満な気がしてるとか?
んで難しくて実装できてないとか?
C++(含0x)の標準ライブラリに多倍長演算って無いの?
無いよ。
そういうライブラリを作るのも面白いな マルチコアを意識して作ったら、地味に早くなるものだろうか
だめだなー
>>898 マジで銀行とかどうしてんだよって思うな
俺が関わったときはなんかライブラリ使ってたけど
>>896 ファクトリが定義されてないクラスをメンバにするとき
newとdelete書かなきゃいけないのが嫌なのです
単体テストクラスが書きずらくなりませんか?
コンテナみたいな汎用的なオブジェクトでいちいちそれを書くのも面倒くさいかな、と
あと vec_ = valだとvalの参照先が変わったらvec_も変わるんじゃないかな
>>900 基本はテンプレートでお願い。勝手にスレッドとか作ったら死刑。
redoとundo実装しろって言われたときにクラスを心底恨んだ メンバはなるべく構造体で定義してからクラスにもたせる
ホントに多倍長演算が無いのは謎。 あってもおかしくないだろうに。
>>903 とりあえず delete 書くぐらいなら auto_ptr ぐらい使っとけ。
具体的なクラスを new するのが嫌なら引数でもらうようにしとけばいい。
コンテナを new するつもりならやめておけ。
vec_ = val はコピーだ。参照先とか関知しない。
ReDo/UnDoの仕組みを構築するのは本当に疲れるよな 奇麗な差分を作らないと、メモリを圧迫するし
要素型にデフォルトコンストラクタが無くてもコンテナは使えなかったっけ?
>>907 STLコンテナ相手なんだからshared_ptrくらい挙げようよ。
今使うには微妙かもしれないだけどさ。
boost::ptr_vector
質問なのですがvectorの特定の要素の削除ってどうやるんでしょうか vector<int>::iterator it = find(v.begin(),v.end(),v[1]);v.erase(it,it); じゃ動かないし removeやremove_ifを使うと、重複値がある場合はそれも取り除かれてしまい 望んだ動作とは違うんです
今まで参照カウントのshared_ptrが標準に無かったことも大きな間違いだな。
>vec_ = val はコピーだ。参照先とか関知しない。 これはマジ?VC7,1だとこういうのは駄目だった気が。。 vector<vector<int> >
思って良いくらいであって、間違いとは言ってない
あ、erase(it)で動いた・・913は忘れてください。失礼・・
>>897 パスカルの三角形を利用した再帰による実装は
オーバーフローの危険性は最も少ないけど、
バッファを用意して再計算を減らさないと遅いし、
nCr が必ず整数になることを利用して、こう実装した方が速い。
オーバーフローの危険性は多少増えるが、
n - r がそれなりに大きくないとそういう状況にはならないと思うし、
なんなら一時変数のサイズを増やせば良い。
r = 0 の時、
nCr = 1
r > 0 の時、
nCr = n!/(r!(n-r)!) = n!/((r-1)!(n-r+1)! * r/(n-r+1)) = nC(r-1) * (n-r+1)/r
unsigned int combi(unsigned int n, unsigned r)
{
if (n < r) { return 0; }
if (r > n / 2) { return combi(n, n - r); }
unsigned int nCr = 1;
for (int s = 1; s <= r; ++s) {
nCr = nCr * (n - s + 1) / s;
}
return nCr;
}
919 :
897 :2009/02/11(水) 23:54:07
>>918 完成版サンクス。
問題はもう891さんがご覧になっていないかもしれぬと言うところだな。
分岐は増えるが、
>>918 のオーバーフロー安全性を
パスカルの三角形と同レベルにすることもできるぜ。
for (int s = 1; s <= r; ++s) {
if (nCr % s == 0) {
nCr /= s;
nCr *= (n - s + 1);
} else {
nCr *= (n - s + 1) / s;
}
}
(n - s + 1) / s って常に整数なの?
922 :
897 :2009/02/12(木) 00:07:37
>>920 俺が軽い気持ちで書き込んだオーバーフローの話題にみんな何でこんなに付いてきてくれるんだ?
なんかスマン
>>921 常に整数じゃないから分岐してるんじゃん。
じゃあ、nCr % s != 0 のとき、 (n - s + 1) / s って常に整数なの?
パスカルの三角形っていってるのはこれのこと? int com(int n,int k){ if(n<k)return 0; else if(n==k||k==0)return 1; return com(n-1,k)+com(n-1,k-1); } 俺はコンテナの並び替えとかのがほしいから こんなのを自作して使ってる。効率とかはあんま考えたことがないので よくわからんが string s="abcde"; string c=""; void com(int p,int k){ if(k==0){cout << c << endl;return;} if(p>=s.size())return; c+=s[p]; com(p+1,k-1); c.erase(c.end()-1); com(p+1,k); }
>>924 常に整数だよ。
整数じゃなかったら、nCs が整数にならないじゃん。
>>926 >整数じゃなかったら、nCs が整数にならないじゃん。
いや、だからおかしいだろ、って言外に言ってるのだが。
ついでpermutation next_permutationは重複値がある時少しめんどうだから こっち使ってる void perm(string&a,int n){ if(n==a.size()-1){cout << a << endl;return;} for(int i=n;i<a.size();++i){ swap(a[i],a[n]); perm(a,n+1); swap(a[i],a[n]); } }
>>926 そんな証明の循環みたいなこと言われても
下降階乗冪で考えるとわかりやすいよ
void niwatori() { tamago(); } void tamago() { niwatori(); }
>>927 nCr と (n - s + 1) のどちらも s の倍数でない場合もあるかもしれないもんな。
>>932 確かに・・・。
なら、nCr と s の最大公約数を求める処理を挟む必要があるか。
ええぃアルゴリズムスレでやれ。
これでいいね。はい、終了。 for (int s = 1; s <= r; ++s) { unsigned int d = gcd(nCr, s); nCr /= d; nCr *= (n - s + 1) / (s / d); }
n=3, r=3 nCr=1, s=1 → nCr=1/1 → nCr=1*(3-1+1)=3 nCr=3, s=2 → nCr=3*((3-2+1)/3)=3*(2/3) ここで (n - s + 1) / sは整数ではない。
if (r > n / 2) { return combi(n, n - r); } これが見えんのか
>>935 (n - s + 1) / (s / d) って常に整数なの?
それに nCr % s == 0 のケースじゃん
>>938 常に整数だよ。
整数じゃなかったら、nCs がどうやっても整数にならないじゃん。
>>940 >整数じゃなかったら、nCs がどうやっても整数にならないじゃん。
いや、だからおかしいだろ、って言外に言ってるのだが。
>>897 ,918
数学的には簡単なのに、実装するとなると色々考えないといけないんですね。
とても勉強になりました。
正しいと主張するなら、証明しろよ
まず前提として、nCr * (n - s + 1) / s は必ず整数になると保証されている。 この式の結果は nCs に相当するからだ。これは整数だ。 つまり、nCr * (n - s + 1) は必ず s で割り切れる。 ここで、s = de, d = gcd(nCr, s) と分解する。 nCr (n - s + 1) / s = nCr (n - s + 1) / de = (nCr / d) (n - s + 1) / e d は nCr と s の最大公約数なのだから、 e でも e の素因数でも nCr / d を割り切る事は出来ない。 従って、この式の結果が整数になるためには、 (n - s + 1) が e = s /d で割り切れる必要がある。
>>945 の nCr ってのはあくまで一時変数名だから
そこんとこ誤解すんなよ
947 :
886 :2009/02/12(木) 00:45:35
リロードしないで
>>943 書いたらレスが大量に・・。
じっくり考えて読まないと理解できそうもないので、また明日読むことにします。
ありがとうございました。
>>945 >まず前提として、nCr * (n - s + 1) / s は必ず整数になると保証されている。
>この式の結果は nCs に相当するからだ。
この証明して
952 :
930 :2009/02/12(木) 01:35:11
>>920 のコードが間違ってるんだよね。
nCr *= (n - s + 1) / s;が間違いで
nCr = nCr * (n - s + 1) / s;が正しい
nCr * (n-s+1)/s;は整数になるが
(n-s+1)/s;は割り切れない時もある
結局正しいコードは
>>918 もしくは
>>920 を修正してこうなる。
unsigned combi(unsigned n, unsigned r)
{
if (n<r) return 0;
if (r>n/2) return comb(n, n-r);
unsigned ncr = 1;
const unsigned m = n-r;
for (int s=1; s<=r; ++s) {
if (ncr%s == 0) {
ncr /= s;
ncr *= (m+s);
} else {
ncr = ncr * (m+s) / s;
}
}
return ncr;
}
それでいいよ
下降階乗冪で考えると5C3は(5*4*3)/(3*2*1)で表すことが出来る。これを以下のように表記する。
543
321
でこれを計算するには上段の数字を右から掛けていき、その都度下段の数字で割ればよいこれをコードに起こすと
const unsigned m = n-r;
unsigned ncr = 1;
for (int s=1; s<=r; ++s)
ncr = ncr * (m+s) / s;
ここで問題になるのが ncr * (m+s) / sは整数になるのかどうかということだが先ほどの
543
321
を思い出す。右側から計算していくので
3
1
を計算することになるがこれは(3)/(1)つまり3C1の組み合わせの表記に等しく、組み合わせの数は整数である。次に
43
21
となるがこれも(4*3)/(2*1)となり4C2の組み合わせに等しい。
右側から見ていくとすべてが何らかの組み合わせの数に等しくなるため ncr * (m+s) / sは整数になる。
ちなみにncr * (m+s) / sと
>>918 のコードのnCr * (n - s + 1) / sとの違いは今までのものを
345
321
に並べ替えただけであり右から見ていけば(5)/(1)で5C1,(5*4)/(2*1)で5C2,(5*4*3)/(3*2*1)で5C3と全て組み合わせになるため
nCr * (n - s + 1) / sは同じく整数であるといえる。
>>951 呆れてものも言えなかったんだよ。
>>918 に書いてある事をなんでもう一度言う必要があるんだ。
>>956 そんなこと考えなくても、組み合わせ数は定義から整数になって当然。
冪で表現すると整数になると一見分かり辛いかもしれないが、
パスカルの三角形を思い出せば、
全ての組み合わせ数は 0C0 = 1 の和に展開できるのだから、
整数になると簡単に証明できる。
パスカルの三角形は
nC0 = 1 = (n-1)C0
nCn = 1 = (n-1)C(n-1)
nCr = (n-1)Cr + (n-1)C(r-1) (0 < r < n)
の関係を表にしただけのもの。
n が 0 になるまで展開すれば最終的に 0C0 の和になることはすぐ分かる。
959 :
930 :2009/02/12(木) 09:45:13
>>953 だとオバーフローのしやすさに変わりないからncr%sの分岐は意味ないくて
>>933 が言うようにgcd使わないとダメなのかー。結局自分がよくレスを読めてなかったのか。
ステップ数を正確に数える方法は? 改修ステップ数を正確に数える方法は?
>>958 組み合わせの数を別の整数で割ったものが整数かという話だろ
あ〜ぁ、また重複させちゃって。 どうする? 俺としては早漏スレより、新しいスレの方が好きだけど、 みんな似合わせるよ。
part63が二つあったから、もし新しいスレを建てるんだったらpart67かな。
part XX いらなくね?
965 :
埋め :2009/02/12(木) 21:17:22
埋め
966 :
埋め :2009/02/12(木) 21:17:44
埋め
967 :
埋め :2009/02/12(木) 21:18:09
埋め
968 :
埋め :2009/02/12(木) 21:18:39
埋め
969 :
埋め :2009/02/12(木) 21:19:09
埋め
970 :
埋め :2009/02/12(木) 21:19:27
埋め
971 :
埋め :2009/02/12(木) 21:19:48
埋め
972 :
埋め :2009/02/12(木) 21:20:10
埋め
973 :
埋め :2009/02/12(木) 21:20:32
埋め
974 :
埋め :2009/02/12(木) 21:21:04
埋め
975 :
埋め :2009/02/12(木) 21:21:36
埋め
976 :
埋め :2009/02/12(木) 21:22:32
埋め
977 :
埋め :2009/02/12(木) 21:22:53
埋め
978 :
埋め :2009/02/12(木) 21:25:41
埋め
979 :
埋め :2009/02/12(木) 21:26:03
埋め
980 :
埋め :2009/02/12(木) 21:26:25
埋め
981 :
埋め :2009/02/12(木) 21:26:46
埋め
982 :
埋め :2009/02/12(木) 21:27:08
埋め
983 :
埋め :2009/02/12(木) 21:27:41
埋め
984 :
埋め :2009/02/12(木) 21:28:02
埋め
985 :
埋め :2009/02/12(木) 21:28:09
埋め
986 :
埋め :2009/02/12(木) 21:28:31
埋め
987 :
埋め :2009/02/12(木) 21:28:52
埋め
988 :
埋め :2009/02/12(木) 21:29:14
埋め
989 :
埋め :2009/02/12(木) 21:29:28
埋め
990 :
埋め :2009/02/12(木) 21:30:07
埋め
991 :
埋め :2009/02/12(木) 21:31:03
埋め
うm
993 :
埋め :2009/02/12(木) 21:35:34
埋め
994 :
埋め :2009/02/12(木) 21:35:56
埋め
995 :
埋め :2009/02/12(木) 21:36:20
埋め
996 :
埋め :2009/02/12(木) 21:36:42
埋め
997 :
埋め :2009/02/12(木) 21:37:06
埋め
998 :
埋め :2009/02/12(木) 21:37:30
埋め
999 :
デフォルトの名無しさん :2009/02/12(木) 21:37:52
999
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。