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


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

C++相談室 part31
251 名前:デフォルトの名無しさん :04/06/09 23:50
>>250
C++ が苦手というか、operator overload で「数式っぽい見た目」でプログラミング
するのと相性悪いんだと思うよ。

これが 4x4 行列と 4 次ベクトル限定で、ベクトル演算用のレジスタ積んでる
プロセッサだと話が変わってくるけど。演算子オーバーロードを使う場合でも、

o 演算子に対応する関数をインライン展開
o 行列やベクトルの要素がコンパイラ最適化によってうまくレジスタに乗る

と、陽に関数呼び出しを行う C スタイルの書き方より早くなることもある。

252 名前:デフォルトの名無しさん :04/06/09 23:51
>>250
C++でもCのような書き方をするなら別に苦手ではない。
それでも効率より見やすさや安全性を考えてクラス化してるんだと思う。

253 名前:デフォルトの名無しさん :04/06/10 00:00
Adobeのソフトや、Windowsなんかは全部C++使ってるんでしょうか?
速度重視のコアの部分はCで書いてて、外側の部分はC++のような気がするんですが…。
どうなんでしょう?

254 名前:デフォルトの名無しさん :04/06/10 00:02
最近C++を始めたばかりです。
・ある物の状態を監視
・その状態を表示
といった単純な事がやりたいのですが、その状態を表すクラスを↓のように定義して
class Status{
public:
Status() : dat(0){};
virtual ~Status(){};
void set(int i) { dat=i; }
int is() { return(dat); }
private:
int dat;
};
メイン関数では↓のように作りました。
Status st;
// 監視側
if(ある物の状態==true){
st.set(1);
}
// 表示側
if(st.is()==1){
表示;
}
が、これだと表示側からもdat.set()が呼べてしまうので危険です。
現状ではfriendを使ってやってるのすが、すっきりしません。
こういう場合、普通は(オブジェクト指向的に?)どのように作るものなのでしょうか?

255 名前:デフォルトの名無しさん :04/06/10 00:06
4X4ぐらいの小さい配列だとだとpure C に比べてETのオーバーヘッドが目立つだけだよ。
もちろん何も考えず作業領域をoperator毎に作るようなコードに対しては
アドバンテージがあるかもしれないけど。
大きな配列を持ってこないとETは逆効果

256 名前:デフォルトの名無しさん :04/06/10 00:07
>>254
コメントを日本語で書くのはやめることだな

257 名前:254じゃないよ :04/06/10 00:11
>>256
言わんとしているのは
 「監視」を英語に直して+パターン
ということかな

258 名前:257 :04/06/10 00:12
s/監視/監視側/

259 名前:デフォルトの名無しさん :04/06/10 00:13
説明用のコメントだろ。アフォだね。

260 名前:デフォルトの名無しさん :04/06/10 00:16
Observer Pattern?

261 名前:デフォルトの名無しさん :04/06/10 00:17
>>259
じゃあ、おまえは「ひまわり」でも使ってろ(プ

262 名前:デフォルトの名無しさん :04/06/10 00:18
さぁ盛り上がってまいりますか

263 名前:デフォルトの名無しさん :04/06/10 00:22
>>254
インターフェースと実装を分離する。

264 名前:237, 238 :04/06/10 00:40
>>246
237は行列同士の*=で1行分しか一時領域が要らないのではないか,
という疑問を単に投げただけのもので,議論の本筋からそれたものでした.すいません.
>でもそうじゃない場合は困るよね。
はい困ります.ただ,困るのはCでもC++でも同じことだと思います.
>op=で一時オブジェクトが必要なときはC式のスタイルよりパフォーマンスが悪くなる
というのは,上の議論において未だ論拠が指摘されていないように見えます.
自分としても,Cスタイルにおけるmultiply_assign(Matrix &a, Matrix const &b)という記述と
operator+=の記述との間にパフォーマンスの差を生じさせるものがあるとは思えないです.

>>248
いえ,私が指摘したいのは,
「ETを実装{しない/できない} -> 数値演算で逆行列を使うのはおかしい」
ではないです.
数値演算で逆行列を使うことは悪いとするスタンスは適切ではないか,ということだけです.
ただ,これは数値計算の一般論の指摘でこのスレで書くべきことではなかったです.すいません.

>>249
>式テンプレートを使わず逆行列のメソッドを提供すればいいのになんでblitz++はやらないのかね?
以下は私の中途半端な知識による考えです.適当に流してください.
通常,行列の逆行列が真に必要となる場面は非常に限られ,ほとんどの場合,
逆行列を陽に計算するよりも適切なアルゴリズムを選択する方が
計算量・精度双方の観点から圧倒的に有利になります.
例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,
通常はLU分解法で行列を三角化してから計算します.
なので,あえて逆行列を陽に求めるメソッドを提供せず,逆行列を表す式オブジェクトとの演算を
適切なアルゴリズムにdispatchしているのではないかと愚考します.あくまで私見です.


265 名前:デフォルトの名無しさん :04/06/10 00:49
みなさんはbad_alloc例外ってどう扱ってますか?

最近VC6.0から7.1に移行してとまどってる厨房です。
いままでは、

char* buf = new char [256];
if (buf) {
 delete [ ] buf;
}

みたいにしてたのを、
(auto_ptr, shared_ptrを使わないとすると)

try {
 char* buf = new char [256];
 delete [ ] buf;
}
catch (bad_alloc&) {
 delete [ ] buf; ← 例外の場合も開放しなきゃだめ?
}

にすればいいんでしょうか。

nothrowを指定するっていう方法もあるけど、
なんかDEBUG_NEWがあるとコンパイルエラーになるし...




266 名前:デフォルトの名無しさん :04/06/10 00:51
>>264
>例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,
>通常はLU分解法で行列を三角化してから計算します.

LU分解は大規模疎行列には使わない。逆行列を陽に求めないというのは同意。

267 名前:デフォルトの名無しさん :04/06/10 00:54
>>266
LU分解は密行列にしか使いませんね.舌足らずでした.すいません.

268 名前:デフォルトの名無しさん :04/06/10 00:57
>>265
> みなさんはbad_alloc例外ってどう扱ってますか?
即興プログラムなら放置してabort()逝き。
まともなプログラムなら適切にcatchを配備。

> delete [ ] buf; ← 例外の場合も開放しなきゃだめ?
まずは、コンパイル通してから出直せ。

269 名前:デフォルトの名無しさん :04/06/10 01:28
>>264
>はい困ります.ただ,困るのはCでもC++でも同じことだと思います.
>というのは,上の議論において未だ論拠が指摘されていないように見えます.
>自分としても,Cスタイルにおけるmultiply_assign(Matrix &a, Matrix const &b)という記述と
>operator+=の記述との間にパフォーマンスの差を生じさせるものがあるとは思えないです.

過去ログちゃんと読めよ。昨日さんざん話したっていうのに。
A *= B の場合、一行分の作業領域もしくは行列1個分の作業領域とコンストラクタ、swapの呼び出しが必要。
C = A * B の場合、行列一個分の作業領域とコンストラクタ、コピーコンストラクタの呼び出しが必要(RVOが使えなければそれ以上)。
multiply(Matrix& C, const Matrix& A, const Matrix& B) を使った場合、
&C == &A の場合、A *= Bと一緒、
&C == &B の場合、一列分の作業領域もしくは行列1個分の作業領域とコンストラクタ、swapの呼び出しが必要。
&C != &A && &C != &B の場合、領域もコンストラクタもswapもいらない。
三番目のパターンはoperatorでは実現できない。受ける変数のために行列一個分の作業領域とコンストラクタが必要でも、
コピーコンストラクタ分は得する。あと変数を使い回せるという利点もある。

Matrix A = ...;
Matrix B = ...;
Matrix C = ...;
Matrix D = ...;
Matrix E;
//E = A * B * C * D;
multiply(E, A, B);
multiply(A, E, C);
multiply(E, A, D);

270 名前:デフォルトの名無しさん :04/06/10 01:30
>>265
VCに限定していいなら__try〜__finallyを使う。
ちょっとしたものを書くときにクラス化しなくていいのは便利なんだけどな。
標準にして欲しい。

271 名前:269 :04/06/10 01:31
>>264
議論を理解してないようだけど、
multiply_assign(Matrix &a, Matrix const &b)とoperator+=を比較してるんじゃないよ。
>>187 参照。

272 名前:270 :04/06/10 01:35
スマン。265の回答にはなってない。

273 名前:264 :04/06/10 02:31
>>271
自分の理解が浅く,議論を蒸し返しただけでした.申し訳ないです.

274 名前:デフォルトの名無しさん :04/06/10 03:32
finally使うんじゃもうC#つかった方がいいんじゃないの?

275 名前:デフォルトの名無しさん :04/06/10 04:27
>>264
>例えば,行列の逆行列と{ベクトル/行列}との乗算では直接逆行列を計算することは論外で,

論外かどうかは用途とか行列サイズによる。理論式上では多用する分野もある。現実問題にアプローチ
する前に理論検証したい場合だってある。
あるいは自分が作った疑似逆行列アルゴリズムと理論式どおりの逆行列アルゴリズム間で精度や速度がどれだけ違うか
比較したい場合もある。
うまくいかなかった場合、元の理論がわるいのか、誤差が利いてきてるのか切り分けたい場合だってある。
そんなもんはケースバイケース。論外とするのはサイズの大きいマトリックスで実行時間もかかるし、求めたところで
誤差が大きくなって使い物にならないって言う場合。
事実、数値計算電卓のMATLAB/Octaveでは用意はしてる。

除算は理論的にワンショット(最小システムクロック)で算出できないから用意しませんでした。というプロセッサより
用意したがそれなりに実行コストはかかります。というのがユーザとしてはありがたいと思う。
ただ、逆行列のET実際はほとんど不可能だ。

276 名前:デフォルトの名無しさん :04/06/10 05:19
>>274
C#なんていうクソ遅い言語は問題外。ベンチマーク取ってもVC7.1の1/2以下
の速度しか出ない。

277 名前:デフォルトの名無しさん :04/06/10 05:50
>>276
それをいうなら
見やすいC++のコードを書いたら同機能のCの1/4の速度になったことあるよ。
もっというと、Cだと遅すぎるのでasmでチューンしたら3倍速くなったことがあるよ。
全部Verilogで書き直して組み合わせロジックだけで実現できたので1クロックで
処理できるようになったことがあるよ。

必要に応じて開発手段を選択するのが設計。

278 名前:254 :04/06/10 06:45
>>257
Observer Patternを調べてみて、だいたいどのようなものかは
分かったのですが、実際に監視側と表示側のソースをちょっと
書いていただけないでしょうか?
初心者なもんでそういう設計自体の方法がよく分からなくって・・・

>>263
こちらもできればお願いします。


279 名前:デフォルトの名無しさん :04/06/10 07:21
>>265
bad_allocはnew演算子内から投げられる
bufには値は代入されていない
解放する必要がある/ないの前に
どこを解放するつもり?

280 名前:デフォルトの名無しさん :04/06/10 08:21
>>279
イラク

281 名前:デフォルトの名無しさん :04/06/10 08:30
>>280
イラクって解放できるの?

282 名前:デフォルトの名無しさん :04/06/10 08:39
解放はできるけれど、解放した段階で未定義動作になります。

283 名前:デフォルトの名無しさん :04/06/10 08:42
s/解放は/解放しようとすることは/

284 名前:デフォルトの名無しさん :04/06/10 10:26
>>277
どうもよくわかんないんだけど、このレスで "C++" っていうとテンプレートや
オペレータの再定義等の C にない機能を使ったコードに限定されるの?

漏れはクラス一切無しのコードでも C++ で書くけど。
ネームスペースとか C99 風のいつでも出来る変数宣言とかありがたいし。
それで別に C より遅くなってる気もしないけど・・・

285 名前:デフォルトの名無しさん :04/06/10 10:38
>>284
遅くなくて当たり前だ。

286 名前:デフォルトの名無しさん :04/06/10 11:04
C 相当のコードで速度差がないのは自明なので議論の対象にならないだけ。


287 名前:デフォルトの名無しさん :04/06/10 11:58
例えばg++, gccでC相当のコードのアセンブラが同一になるのは自明なの?
この部分のコンパイラは同一のコード同一の人間が書いてる?

288 名前:デフォルトの名無しさん :04/06/10 13:34
このケースで「当然同じような速度になるはず」と思えないようだった
ら、コンピュータのプログラミングに対するセンスが欠如してると認識
したほうがいいよ。

ちなみに gcc と g++ だと、ソースコードがプログラミング言語非依存
の形式になった後は、まったく同じルーチンで最適化されてアセンブリ
出力される。VC++ の cl.exe の中身なんて知らんが、C と C++ でわざ
わざ別の最適化なんてするとは思えないでしょ。



289 名前:デフォルトの名無しさん :04/06/10 14:03
全く同じプログラミング言語非依存の形式になるかどうか。

290 名前:デフォルトの名無しさん :04/06/10 16:26
227で質問した者ですけど、
cin >> data;
した後、バッファに「\n」が残ったりしますけど
クリアするには、「cin.get()」とか「cin.ignore()」しかないんですかね?

291 名前:デフォルトの名無しさん :04/06/10 17:04
>>290
俺は getline()派だ。

292 名前:290 :04/06/10 17:28
>>291
でも、象徴的に書ける「>>」が好きなんですよ。
「getline()」だと、Cと変わらないですし…

293 名前:デフォルトの名無しさん :04/06/10 17:46
>>292
string使うから、それだけでも大きく違う。と、思う。
少なくとも、Cと変わらない、は偏見じゃないか?

294 名前:290 :04/06/10 17:53
>>293
Cと変わらないはちょっと言い過ぎでしたが…
それと、stringつかうというのはどういう事ですか?

295 名前:デフォルトの名無しさん :04/06/10 19:18
本を持ってる人にしか分からない質問で申し訳ないのですが
Exeptional C++ の34ページの
>T::operator=()は、例外を投げた際に代入しようとしていたTオブジェクト
>の値が変更されてないことを保証しなければならない。
の意味が分かりません。そんな必要は無いと思うんですけど。

296 名前:デフォルトの名無しさん :04/06/10 19:18
>>294
char[]じゃなくstd::stringが使えるからって事でしょ。

改行残るのは、なんかflushとかしたらよかった気がする。
環境依存かもしれんしうろ覚えだから違うかもしれんけど。


297 名前:デフォルトの名無しさん :04/06/10 19:39
120 名前:番組の途中ですが名無しです[] 投稿日:04/06/10 02:39 ID:DlgC++i0
>>116
「かわいい彼女」といっても三日で飽きるわけだが。

121 名前:番組の途中ですが名無しです[sage] 投稿日:04/06/10 02:40 ID:Qn1mrozU
>>120
3日で飽きても
なにもないより全然マシじゃないのこのC++野郎


298 名前:295 :04/06/10 20:07
あともう一つ。swapが例外を投げないことを強調していますが、
アトミックでありさえすれば例外は投げてもよいように思えます。
なんで例外投げちゃいけないんですか?

299 名前:デフォルトの名無しさん :04/06/10 20:17
>>298
標準化委員会でそう決定したからです。理由は標準化委員会に問い合わせて下さい。

300 名前:規格制定委員会議長 :04/06/10 20:31
>>299
こちらに聞かれてもこまります。
禿げに聞いてください。

301 名前:295 :04/06/10 20:31
>>299
どういうことですか?
コンテナとかの swapも throw()宣言されてませんが。

302 名前:デフォルトの名無しさん :04/06/10 21:05
>>295
ん〜、科学的には説明できないけど、感覚として。

Cでも関数がエラーを返したのにポインタ経由で渡した引数を
ぐちゃぐちゃにされたらムカつくしな〜。

sturct Nanka iremono;

iremono.sono1 = saisyokarahaitteitamono;

if(ERROR == NannkaChoudai(&iremono)) {
 assert(iremono.sono1 == saisyokarahaitteitamono);
}

これでassert()に失敗したらムカつく。

それと同じようなものを感じる。

もしoperator=( )が例外を投げたのに中途半端にオブジェクトが
変わっていたらきっとムカつくな。

303 名前:デフォルトの名無しさん :04/06/10 21:22
>>287
$gcc -dr hoge.c
$g++ -dr hoge.cc
とした時の出力はちょっと違うんだよねえ。
しかし最終的なアセンブラコードはほぼ同じ。どうしてでしょう。


304 名前:デフォルトの名無しさん :04/06/10 22:00
わざわざCとC++で分けないでしょってのは概ね同意だけど、
CとC++は仕様量が格段に違うんだから
それによって最適化しやすくなったり、
逆に不確定要素が増えて最適化しにくくなったり
ってのはあると思うんだけど、なんで誰も指摘しないのかな。

305 名前:デフォルトの名無しさん :04/06/10 22:44
>>304
例外に対処するためのコードが埋め込まれたりして?

306 名前:デフォルトの名無しさん :04/06/10 22:44
スレの流れを折ってしまって申し訳ないですが、
vectorのN番目の要素を削除したいときって、
erase()を使うしかなくて、erase()の引数はイテレータしかないですよね。

そこでこんな↓関数を作ってN番目の要素を指すイテレータを取得しようとしたんですが・・・
template <class Cont> Cont::iterator GetNItr(Cont c, int n){
Cont::iterator it = c.begin();
for(int i = 0; i < c.size(); ++i, ++it)
if(i == n) break;
return it;
}
帰ってくるのは不定値ばかり。一体なぜなんでしょうか?(試した環境はVC6です。)

それ以前に「N番目の要素のイテレータの取得」なんて
かなり使いそうな気がするんですがBoostとかにもないですよね。
やっぱり「イテレータ=反復子」という名前に反した使い方だからですかね??

307 名前:デフォルトの名無しさん :04/06/10 22:49
不定値とだけ言われても困るけど
つーか std::advance じゃだめなん?(戻り値として iterator を返してくれないから使いにくいけど)


308 名前:デフォルトの名無しさん :04/06/10 22:57
erase(vec.begin() + n) ってやれば?

309 名前:デフォルトの名無しさん :04/06/10 22:58
つーかvectorならbegin() + NでN番目を指すiteratorが帰ってくるはずだが

310 名前:規格制定委員会議長 :04/06/10 23:37
>>304
>なんで誰も指摘しないのかな。
ヴァカなお前に付き合うの嫌だから。

311 名前:デフォルトの名無しさん :04/06/11 00:19
>>306
とりあえず、その関数は

引数で Cont c ってやってるから、コンテナがコピーされ、コピーされた方の要素を指すイテレータが返るからダメになる。

Cont &cなら思ったとおりにいくんじゃね?まc.begin()+Nの方が断然いいが

312 名前:デフォルトの名無しさん :04/06/11 01:51
ファンクタ書く時に、
operator() 内で、
static std::vector< double > tmp;
ってインスタンス作るのと、
private 内に、std::vector< double > tmp
のインスタンス作ってoperator() 内で使うのと
どっちがいいんですか?

313 名前:デフォルトの名無しさん :04/06/11 02:03
>>312
privateインスタンスのほうがstaticよりマシ。

314 名前:デフォルトの名無しさん :04/06/11 02:24
>>295
http://www.boost.org/more/generic_exception_safety.html

315 名前:290 :04/06/11 07:32
>>296
それは分かるんですが…
「cin.getline()」使用時に「std::string」をどの様に利用するのですか?

316 名前:デフォルトの名無しさん :04/06/11 07:57
たぶん、そっちじゃなくてstd::getline()のことを言ってるんだと思うよ。

317 名前:290 :04/06/11 08:09
>>316
なるほど。「std::getline()」だったのですね。
良く分かりました。

318 名前:デフォルトの名無しさん :04/06/11 09:29
>>301
throw() 宣言すると、コンパイラが例外処理のためのコードを追加するから、
パフォーマンスを考えれたら、throw() は入れない。

あと、operator= が例外安全でなければいけない理由は、

simpleDBTable.Current["NAME"] = "MONA";

のような簡易データベース中の項目を置き換えるコードがあったとして、
この中で例外が発生したとき、すでにある項目が消されたら困るでしょ?

319 名前:デフォルトの名無しさん :04/06/11 09:41
>>318
>パフォーマンスを考えれたら、throw() は入れない。
なるほどパフォーマンスの問題ですか。

>この中で例外が発生したとき、すでにある項目が消されたら困るでしょ?
そんなことは分かっているのですが(基本的に全ての関数はアトミックにすべき)、
この文脈でその必要はないのではと。例外投げられたら deleteされるので。

320 名前:デフォルトの名無しさん :04/06/11 09:58
>>319
> 例外投げられたら deleteされるので。
そうは言えない。

T x = initial_value;
try
{
 x = new_value;
}
catch( ... )
{
}
// x はまだ生きている。
// ここで x の値は initial_value か new_value か、どちらかであると言えなければ、
// 以降、 x へアクセスしたときの動作が把握できない。

321 名前:デフォルトの名無しさん :04/06/11 10:13
>>318
> 例外投げられたら delete される
誰が delete するのさ?
君はデータベースの更新に失敗したら即座にテーブルを破棄するのか?



322 名前:デフォルトの名無しさん :04/06/11 10:31

何らかの例外が発生したときに、
1. その例外を呼び出し元に正しく通知する。(例外中立)
2. 例外が発生しても、オブジェクトの状態は変化しない。
  もしくは例外を出さない。(例外安全)

というのが、例外安全の基本。これを >>295 は理解しているのだろうか?
コンストラクタで例外が発生した場合、そもそもオブジェクトそのものが作成されないが、
代入処理の場合、例外が発生しても依然としてオブジェクトは存在している。
例外から回復して、オブジェクトを再度いじろうとしたときに内容が不定では話にならない。


323 名前:295 :04/06/11 11:31
>>320 >>321 >>322
おんなじこと何度も何度も書きやがって。んなこたー分かってる。
Exceptional C++ 33,34ページの話だYO!
catch してから deleteしてるだろ。
だからクラスTにアトミックな代入演算子は要求しないと思うんだよ。

あと swapについて。
確かに例外を投げないほうがいいときもある。
例えば73ページの第二の試み。最後に代入演算子使ってるけど、例外を投げない swapがあればそれで解決する。
でも Stackの例だとアトミックであれば例外は投げともよいと思うんだよ。
そこらへんどーよ。

324 名前:デフォルトの名無しさん :04/06/11 11:55
>>295
まあ、おちついて。

"代入しようとしていたTオブジェクト"
とはコピー元をさしてっるて解釈はどお?
コピー元がconstでもmutable変数含んでりゃ
同にでも出来るし。

swapについてだけど、逆にswapが例外を投げる可能性がある場合、
swap(v1,src.v1);
swap(v2,src.v2);
swap(v3,src.v3);
見たいなメンバ関数を例外安全にするのは大変だYO!みたいな事が
言いたかったって解釈はどお?

325 名前:デフォルトの名無しさん :04/06/11 11:55
>>323
> Exceptional C++ 33,34ページの話だYO!
そんなコード片の話をしてたのか、そりゃ気付かなかった。
例外発生したときの対応がdelete一択なら、たしかに、そんな要求はないよ。

でも、>>295で引用された2行が、より一般的なケースでの指針である可能性はないのかい?
本読んでないからわかんないだけかもしれないけど。

326 名前:デフォルトの名無しさん :04/06/11 12:02
>>324
> "代入しようとしていたTオブジェクト"
> とはコピー元をさしてっるて解釈はどお?

明らかに問題外。

327 名前:324 :04/06/11 12:05
>>326
そお?例えばCOWな実装のstringの場合
代入時にコピー元にも影響ありそうだけど

328 名前:295 :04/06/11 12:10
>>324
よく分からんけど自己代入ってこと?
でもコピー先は newしたばっかの領域だし。
swap についてはその通りですね。
でも Stackの例は適切ではないと思います。

>>325
>でも、>>295で引用された2行が、より一般的なケースでの指針である可能性はないのかい?
そう読めなくもありません。訳の問題なのかも。
でも 58ページに
Stack を例外安全にするために、唯一例外安全にしなければならないTのメンバ関数
なんて書いてます。

329 名前:デフォルトの名無しさん :04/06/11 12:13
>>327
そんな話は関係ない。>>295の引用に対する解釈の仕方が問題外だってこと。

330 名前:デフォルトの名無しさん :04/06/11 12:15
>>323
そういうことかよ。まぁ、悪かった。
でも今は会社だから手元に本がないんだよなー。

ただ、すこし言わせてもらえば、
アノ本は 代入処理は以下の形式にしなさいというのがキモで、
途中のイロイロは、すべて以下のコードにもっていくための「布石」だと思う。

this_type & this_type::operator=( this_type const & rhs )
{
  this_type( rhs ).swap( *this );
  return *this;
}

だから、途中のコード云々で話をするのはまったくもって無意味だと思うのだが、どうか?

331 名前:デフォルトの名無しさん :04/06/11 12:19
状態が「不定」なオブジェクトは delete 出来るの?

332 名前:295 :04/06/11 12:22
>>330
その swapは例外を投げない保証をする必要ありますか?

>>331
確かに!!!

333 名前:デフォルトの名無しさん :04/06/11 12:24
>>331
できないかもしれない。
けど、最低限それだけは保証してもらわないと、どうやっても回復できなくなってしまう。
例外に対する対応がプログラムの終了以外ほぼ選択肢がなくなってしまうだろう。
(ほかには、そのオブジェクトに2度と触らないようにするくらい?)

解体すらできなくなってしまうような仕様のクラスは作らないのが常識だろう。

334 名前:デフォルトの名無しさん :04/06/11 12:36
>>332
> その swapは例外を投げない保証をする必要ありますか?

this_type::operator=()への要求として例外安全性が必要なければ、
必要ない。

this_type::operator=()への要求として"no-throw gurantee"が必要ならば、
swapへの要求として引数に対する"no-throw gurantee"が必要。

this_type::operator=()への要求として"strong gurantee"が必要ならば、
swapへの要求として引数に対する"strong gurantee"が必要。

this_type::operator=()への要求として"basic(以下略)

335 名前:334 :04/06/11 12:37
s/引数に対する//

336 名前:デフォルトの名無しさん :04/06/11 12:47
>>334
まあつまり例外を投げない保証をする必要はないですよね。
この本 swapが例外を投げないことをやたら強調してますが、その理由が示されていないように思えます。

337 名前:デフォルトの名無しさん :04/06/11 13:05
>>330
> その swapは例外を投げない保証をする必要ありますか?
ある。

>>330 のコードにおいて、swap が例外を発生させる場合を考えると、
>>322 の 2. を満たすためには、
operator= は以下のように直す必要があるが …

this_type & operator=( this_type const & rhs )
{
 this_type temp( rhs );
 ... // this の状態を保存する。※1
 try { temp.swap( *this ); }
 catch( ... )
 {
  ... // this の状態をもとにもどすコードを入れる ※2
  throw;
 }
 return *this;
}
ここで、※ にどのようなコードを入れればいいかを考えるといい。

さらに、A.swap( B ) において、A のメンバの一部と、Bのメンバの1部だけが
入れ替わった状態で例外が発生すると、>>322 の 2. を満たせなくなる。

面倒なことをイロイロ考えなくてもいいように、swap は例外を出しちゃ駄目ってことになってるの。

338 名前:デフォルトの名無しさん :04/06/11 13:09
>>336
例外が発生したときには、内部状態が変更されていないことを保証するクラス(群)を
構築する際には、例外安全な swap を用意すると便利だよ、STLもそうしてるよ、
っていう話だと思うけど。boost も同じ方針ですよね。

339 名前:デフォルトの名無しさん :04/06/11 14:05
>>313 何故なんでしょうか?
また、マシって事は他にお勧めがあるんですか?

340 名前:デフォルトの名無しさん :04/06/11 15:11
>>337
だーかーらー swapはアトミック性だけ保証してればいいんじゃないですか? アフォ?

>>338
あなたの言う例外安全っていうのは例外を投げないって意味ですか?

例外を投げないことがアトミック性を実現する一番簡単な方法ってなら分かりますが、
Exceptional C++ は swapが例外を投げないってことを強調しておきながら
そのちゃんとした説明がなされていないと思うんですよ。

341 名前:デフォルトの名無しさん :04/06/11 17:17
>>340
swap がけして例外を投げないわけではない。
ポインタのスワッピングだから例外を投げないのだよ。わかるか?


342 名前:デフォルトの名無しさん :04/06/11 17:39
>>341
???
組み込み型のスワッピングは例外を投げませんね。
再帰的に全てのスワッピングは例外を投げませんね。
swapは例外を投げないものだってのは分かります。
例外投げたらなんか無理してるってのも分かります。
でも Exceptional C++ 48ページに
> Swap() はどんな状況下であっても例外を投げない。
> Swap() のこの特徴こそが、Stack自身の例外安全に関する論証の要なのだ。
って書いてます。
Stack 内で StackImpl::Swap()は2回使われていますが、
これらが例外を投げたとしても Stackの例外安全性は損なわれないと思うんです。

343 名前:デフォルトの名無しさん :04/06/11 19:48
そもそもC++の例外処理ってプロの方々は積極的に使っているので
しょうか?あんまりパフォーマンスがよくないとかいう話も聞くし。
どちらかというと、プログラムの連結とかそういうときに持ち出すの
ですか?

344 名前:デフォルトの名無しさん :04/06/11 20:21
>>342
StackImpl::Swap のコードは、3つの std::swap から成り立っていて、
そのすべてが組込型に対するスワッピングである以上、StackImpl::Swap は
決して例外をスローしない。ここまではいいと思う。
そして、Swap が例外を投げない以上、これを積極的に使わない手はない。

で、それをふまえた上で、>>342 は、次のどちらを言いたいのか?

 1. Swap が無くても例外安全に出来るじゃないか。
 2. Swap が決して例外を投げないというその理由がわからない。


どうも、あなたの言いたいことがピンとこない…

345 名前:デフォルトの名無しさん :04/06/11 20:39
>>344
僕が言いたいのは、Exceptional C++ の48ページの主張の真意を教えてくれ(Stackの例、間違ってんじゃねーの?)ってことです。
Stack がアトミックなのは Swapが例外を投げないからじゃなくて Swapがアトミックだからだ。
Swapが例外を投げないのはただの結果であって、この場合必要ではない。
と、僕は思うんです。

あー同じこと何回書いただろう。

346 名前:デフォルトの名無しさん :04/06/11 21:36
C++で、継承についてわからないことがあります。

class A
{
 SetOne();
 SetTwo();
};

class B
{
 SetOne(;);
}

class C
{
 SetTwo();
};

というクラスがあったとします。クラスB、CはクラスAにある関数と同じものを一つずつ持っています。
このとき、同じことを何度も定義すると無駄なので、継承を考えますが、必要ない関数まで継承されて
しまいます。継承先で、必要のない関数を消す方法などはないのでしょうか?
また、何か解決策がありましたら教えてください。

347 名前:デフォルトの名無しさん :04/06/11 21:45
必要な関数だけのクラスを作りましょう。

348 名前:デフォルトの名無しさん :04/06/11 21:46
>>346
class A : public B, public C {};
なんじゃないのか?

349 名前:131 :04/06/11 21:50
>>346
struct afo { virtual SetOne() = 0; };
struct sine { virtual SetTwo() = 0; };
class black { /* ry */ };
class c { /* ry */ };
class A : public afo, public sine { black b; c dakko; /* ry */ };
class B : public afo { black b; /* ry */ };
class C : public sine { c dakko; /* ry */ };

350 名前:デフォルトの名無しさん :04/06/11 21:52
>>345
Swapは絶対に例外を投げない を
Swapは絶対に失敗しない に読み替えれば納得いくんでない?

351 名前:デフォルトの名無しさん :04/06/11 21:57
>>350
もったいぶらないではっきり言えよ。
なにが言いたいのか全くわからねえよ。

352 名前:デフォルトの名無しさん :04/06/11 21:58
それぞれ関数の中で、同じ構造体に値を渡すのですが、この場合多重継承で考えると
かなりややこしい作りになってしまうんですが、もっとすっきりしたものにできないでしょうか?
できれば多重継承はない方向でいきたいと思ってます。

353 名前:352 :04/06/11 21:59
346です。

354 名前:デフォルトの名無しさん :04/06/11 22:06
>>345
本の著作者にメールで真意を聞け

355 名前:デフォルトの名無しさん :04/06/11 22:07
JAVAのStringTokenizerと同じような機能を持つ関数って
CやC++にはないですかね?
地道にクルクル回すしかないのでしょうか。

356 名前:デフォルトの名無しさん :04/06/11 22:09
>>352
ソースさらすの下手っ取り早いかと

357 名前:デフォルトの名無しさん :04/06/11 22:10
>>351
それで理解できないなら、その程度の頭ってことだ。

358 名前:デフォルトの名無しさん :04/06/11 22:19
>>357
考えてみても分からん。まじで分からん。
教えてくれ。たのむ。

359 名前:デフォルトの名無しさん :04/06/11 22:20
ソースはかなり長くなってしまうので無理ぽいです。
なのでかなり端折りますが、以下のような構造体を持つクラスがあります。
これはDirectXで用意されている構造体です。

typedef struct _D3DLIGHT9 {
D3DLIGHTTYPE Type;
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Ambient;
D3DVECTOR Position; // ディレクショナルのとき無視
D3DVECTOR Direction; // ポイントのとき無視
float Range; // ディレクショナルのとき無視
float Falloff; // ポイント、ディレクショナルのとき無視
float Attenuation0; // ディレクショナルのとき無視
float Attenuation1; // ディレクショナルのとき無視
float Attenuation2;// ディレクショナルのとき無視
float Theta; // ポイント、ディレクショナルのとき無視
float Phi; // ポイント、ディレクショナルのとき無視
} D3DLIGHT9;

type には ポイントライト、スポットライト、ディレクショナルライトがあります。
それぞれのライトには適用されず無視される変数というのが存在しています。
パラメータの前に書いてあるメッセージがそれです。
この構造体のすべての値を変更できるように、それぞれに対してセッターを作ると
実際に使用するときに、間違って無効なパラメータを設定してしまう場合があると思います。
これを防ぐために、3つのライトそれぞれをクラス化して、無効なパラメータを設定するような
関数は省きたいと思っています。

360 名前:デフォルトの名無しさん :04/06/11 22:28
よーやくわかったよ。だからこれで最後。


わたしが想像する サッターさんの真意は、
P35 や P37 のガイドラインおよび、P42 の 3 にあると思う。
それをうけての P48 の記述。

彼の譲れない部分(信念)として、「例外を起こす可能性のある処理」をすべて最初に行い、
「例外を投げる可能性のある処理で状態変更をしてはならない」わけ。
例はあくまで例。言いたいことはコレ。

以下駄文。国語のテストみたいなもん。

Swap に求められていることは、「アトミック」だとか「例外安全」とかいうことではないと思う。
本当に求められているのは、きっと「絶対に失敗しない」こと。
「ここまで来れば絶対成功する」という保証。だから、アトミックであることはもちろん、例外を投げるなんて論外。

まぁ、そういう宗教だと思えばいいじゃん。

361 名前:360 :04/06/11 22:30
あ、360 = 342 ね。




362 名前:デフォルトの名無しさん :04/06/11 22:32
>>360
あっはっはー
やーい逃げた逃げた
何が宗教だ ぼけ

363 名前:デフォルトの名無しさん :04/06/11 22:39
例外を投げるくせにアトミックというのがよくわからん。
教えてエロいひと!!

364 名前:デフォルトの名無しさん :04/06/11 22:41
>>359
struct PointLight : D3DLIGHT9 {
  ポイント用セッター
};
としておいて、生の変数には直接触らないと誓う。
もしくは、AbstructLightクラスのメンバにD3DLIGHT9を持たせて、外からは触らないようにするか。
どっちにしろ、あんまりこだわっても大して嬉しくはならないので、適当なところで妥協することを薦める。

365 名前:デフォルトの名無しさん :04/06/11 22:42
そもそも例外安全な代入をやりたいのに、代入とは別の処理であるSwap()が失敗されちゃあ、たまらん。
失敗する可能性が本来の代入処理より増えるのであれば、そんなロジックは採用したくない。

366 名前:デフォルトの名無しさん :04/06/11 22:43
>>360 >>361 >>362
え? 騙られてんの?

>>360
なるほどねえ。そう考えればつじつまは合わなくもない。
例はあくまで例というけれど、そんな破綻した例を持ち出して 48ページのような強い物言いをするかな?
信念があるのはよいけれど全く例が伴ってないよ。
>>323 に書いたように swapが例外を投げちゃいけない例ってのがあって、しかもその信念にぴったりなのにね。

367 名前:デフォルトの名無しさん :04/06/11 22:48
本の内容に納得いかないのなら、著者に文句を言うべきだ。

368 名前:デフォルトの名無しさん :04/06/11 22:49
>>364
>>生の変数には直接触らないと誓う。
誓うというのは、基本的に自分ならば大丈夫ですが、それ以外となると不可能なので。
妥協して無駄に同じ処理を記述するようにします。
ありがとうございました。


369 名前:デフォルトの名無しさん :04/06/11 22:52
>>365
そんなレベルの話をしてるんじゃねえよボケ、と言いたいところだけど
著者の真意は案外そんなとこかもしれない。

>>367
そうですね。これだけ粘っても誰も説明できなかったので、著者は電波ってことで納得します。
スレ汚しスマソ。

370 名前:デフォルトの名無しさん :04/06/11 22:59
295の態度が徐々に変わってゆく姿が笑える。

371 名前:デフォルトの名無しさん :04/06/11 23:06
>>369
>>363 の質問にも答えてやってくれ。
例外を出して、かつアトミックな処理の例とか出してくれると助かる。

372 名前:デフォルトの名無しさん :04/06/11 23:23
>>371
そんなもん try,catch 使えばいくらでも書けると思うけど、好みじゃないので。
例えば >>330
最初のコピーコンストラクタが失敗しても、状態は変化していない。
その後の swapは例外を投げない、もしくはアトミックなので例外が起きても大丈夫。
最後の returnは参照渡しだから例外を投げない。

より一般化すると >>314

template <class Container, class BasicOp>
void MakeOperationStrong( Container& c, const BasicOp& op )
{
Container tmp(c); // Copy c
op(tmp); // Work on the copy
c.swap(tmp); // Cannot fail
}

op() がアトミックじゃなくても swap()がアトミックであれば、副作用が一つの処理なら
どんな処理でもアトミックにできると思う。

副作用が二つあったりすると、例外を投げない swap() が必要になると思う。
まあ swap()は例外を投げないべきだけどね。

373 名前:デフォルトの名無しさん :04/06/11 23:26
文章いじったらおかしくなった。

op() がアトミックじゃなくても swap()がアトミックであれば大丈夫。
アトミックな swap()があれば、副作用が一つの処理ならどんな処理でもアトミックにできると思う。

にして。

374 名前:デフォルトの名無しさん :04/06/11 23:28
あぁ、アトミックってそっちかYO!
てっきりクリティカルセクション的なアトミックを連想したよ。
つまり、

T temp( a ); a = b; b = temp;

ってあったら、そのすべてが必ずひとまとまりに行われるってのを想像した。


375 名前:デフォルトの名無しさん :04/06/11 23:33
>>295は釣り師だったということで、終わりにしようぜ。

376 名前:313 :04/06/12 00:10
>>339
staticインスタンス
×寿命が(おそらく)不必要に長くて、さらにその寿命はほぼ制御不能。
×さらに関数内staticは関数外からのアクセスは不可能。
○毎回作り直さないので、生成、破棄のコストがかからない。
×マルチスレッドに対応不可能。

privateインスタンス
○寿命はファンクタの寿命を超えない範囲で自由に制御できる。
○メンバ関数を通してアクセスが可能。
×毎回作り直すので、生成、破棄のコストがかかる。
○マルチスレッドに対応可能。

お勧めは、ファンクタのコンストラクタでstd::vector<double>への参照を受け取り、
メンバにポインタを保持する方法。
アルゴリズムのファンクタ引数は値渡しで実装されている可能性が高いので、
コピーのコストを抑えた方がいいケースが多い。

377 名前:デフォルトの名無しさん :04/06/12 00:30
>>355
boost::tokenizerでかなりの事はできない?

378 名前:デフォルトの名無しさん :04/06/12 01:00
>>368
ポイントライトの位置設定とスポットライトの位置設定が同じ処理になることが偶然
と考えれば、別の関数としておくことに意義を見出せないか?

379 名前:デフォルトの名無しさん :04/06/12 01:20
>>376 それを指針に考え直してみます。
詳しい説明有難うございました。

380 名前:デフォルトの名無しさん :04/06/12 08:57
EUCからShift Jisに変換するにはどうしたらいいでしょうか?

381 名前:デフォルトの名無しさん :04/06/12 09:43
nkf

382 名前:デフォルトの名無しさん :04/06/12 10:45
>>376
特徴としてあげている箇条は大筋いいが
目的が示されていない以上そこまでだろ
どっちがお勧めという根拠がないぜ

383 名前:デフォルトの名無しさん :04/06/12 10:55
>>380
EUC2SJISを使えば変換してくれるよ♪

384 名前:デフォルトの名無しさん :04/06/12 10:57
visual cとturbo cとc言語とc++との
区別が付けられません

385 名前:デフォルトの名無しさん :04/06/12 10:59
>>384
区別をつけられなくて困っていることがあるのか?

386 名前:デフォルトの名無しさん :04/06/12 11:00
小文字厨らしいな

387 名前:デフォルトの名無しさん :04/06/12 11:04
>>384
>(visual cとturbo c)と(c言語とc++)との
E-mailとインターネットはどっちがいいですか?
ってのと同じくらい的外れな質問だぞ

388 名前:デフォルトの名無しさん :04/06/12 11:09
>>380
http://tohoho.wakusei.ne.jp/wwwkanji.htm
下の方
半角文字は考えられていないようなので注意

389 名前:デフォルトの名無しさん :04/06/12 11:40
>>380
EUCコード&0x7f7fしてからwctombs()だっけ?

390 名前:デフォルトの名無しさん :04/06/12 12:16
>>389
Shift-JISだぞ。

391 名前:デフォルトの名無しさん :04/06/12 12:25
>>380
iconv()

392 名前:デフォルトの名無しさん :04/06/12 12:33
小文字厨なんてのもいるのか

393 名前:デフォルトの名無しさん :04/06/12 12:39
いるようだ。
全角厨より、100倍マシだと思うけど。

394 名前:389 :04/06/12 12:41
wcstombs()か。つーか寧ろmbcjistojms()で一文字ずつ変換した方が楽か。
>>390
それが何か?

まぁ実際には、自分でコーディングしちゃうんだけどね。

395 名前:デフォルトの名無しさん :04/06/12 12:46
>>394
&0x7f7fしたら1バイト目の8ビット目まで0になってしまうと思うんだけど。

396 名前:デフォルトの名無しさん :04/06/12 12:51
http://ime.st/ime.st/www.personal-media.co.jp/book/c/ansi.html
これ、最強

397 名前:デフォルトの名無しさん :04/06/12 12:52
http://tohoho.wakusei.ne.jp/wwwkanji.htmを見る限り、389が言っているのはEUC->JISに見える。

398 名前:389 :04/06/12 12:57
>>395
それがなにか? EUCの最上位ビットなんて(コードページを切り替えるための)飾りですよ。
飾りを取れば只のJISですから。
#但し、所謂1バイトかなの判定はそれ以前に行う必要があるけど。

>>397
私にはあなたの言いたいことが判らない。

399 名前:デフォルトの名無しさん :04/06/12 12:59
380 :デフォルトの名無しさん :04/06/12 08:57
EUCからShift Jisに変換するにはどうしたらいいでしょうか?

400 名前:389 :04/06/12 12:59
度々スマソ。
wcstombs()がコード変換すると何でか思い込んでたよ。
私が勘違いしてただけなのね。

401 名前:デフォルトの名無しさん :04/06/12 13:10
setlocale(LC_ALL, "jpn");
char buf[101];
wcstombs(buf, L"あいうえお漢字", 100);
puts(buf);

いや、普通にUCS-2からSJISに変換してるが@VC++6.0

402 名前:デフォルトの名無しさん :04/06/12 13:13
文字コードの変換じゃなくて、表現形式の変換。

403 名前:デフォルトの名無しさん :04/06/12 13:21
C+++++++++++++++++++++++++++++++++++++++

404 名前:デフォルトの名無しさん :04/06/12 14:02
EUC-KR からだったらどうするよ

405 名前:デフォルトの名無しさん :04/06/12 15:52
文字コードすれ逝けよ→http://pc5.2ch.net/test/read.cgi/tech/1063177450/

406 名前:デフォルトの名無しさん :04/06/12 21:15
CreditCard *card = new CreditCard("岸部四郎")
if( ! card ){
  printf("ブラックリストに載っています");
  return 0;
}

card.buy(1000000);
delete card;
return 0;

こんな風にしたいんですが、
new("岸部四郎") CreditCard() を回避できないでしょうか?

407 名前:デフォルトの名無しさん :04/06/12 21:22
???

408 名前:406 :04/06/12 21:35
えっと、

・初期化エラー時nullを返すにはnew内で初期化
・初期化に引数をとるにはコンストラクタ内で初期化

で、両立する方法は new("誰それ") CreditCard() とありました。
しかしできれば普通の書式が良いのですが、他に無いでしょうか?
それともnullチェックより例外を使うべき?

409 名前:デフォルトの名無しさん :04/06/12 21:36
>>406
class CreditCard{
CreditCard(const char *);
public:
static CreditCard *New(const char *name){
if(name in list){
return 0;
}
return new CreditCard(name);
}
};

CreditCard *card = CreditCard::New("岸部四郎")
if( ! card ){
  printf("ブラックリストに載っています");
  return 0;
}

card.buy(1000000);
delete card;
return 0;

410 名前:デフォルトの名無しさん :04/06/12 21:38
意味が分からないというか、
その前に本をよく読んでいないか読み間違えていないか?

new で引数をとるコンストラクタを用いたいなら、
new CreditCard("岸部四郎")以外ないと思うが、
回避したいって何が問題で何を回避したいの?

411 名前:406 :04/06/12 22:04
>>409
ありがとうございます。
ただ、やはり特殊な書き方になってしまうので避けたいです…。

>>410
・初期化失敗時にnullを返したい
・普通にnew CLASS(引数)を使いたい//こっち重視
です。

newをオーバーロードして new(引数) CLASS() でも、>>409さんのCLASS::New(引数)でも、
一つ目をクリアする代わりちょっと浮いちゃうので…。
一つ目を諦めると例外を使うことになりますが、あまり失敗の多いところで使うと良くない気がして…。
他に解決方法はあるでしょうか。(例外で問題なければそうします)

412 名前:デフォルトの名無しさん :04/06/12 22:06
滅多に失敗しないのなら、なおさら例外を使うべきでは?

413 名前:デフォルトの名無しさん :04/06/12 22:10
>>409 はファクトリちっくだしそんなに特殊な書き方だとは思わないけど。

414 名前:デフォルトの名無しさん :04/06/12 22:23
>>411
>他に解決方法はあるでしょうか。
無い。

415 名前:デフォルトの名無しさん :04/06/12 22:26
相談の範囲を多少逸脱するかもしれないけど。

チェックしたいのがブラックリストのみで、
それに必要なのがコンストラクタで与える名前だけなら、
ブラックリストをメンバ変数としてもち
内部で>>409 のような処理を行うメンバ関数をもつ発行者クラスを
別に用意してチェックを分離したほうがスマートだと思う。

416 名前:406 :04/06/12 22:47
>>412
失敗はそれほど多くは無いと思います。が、後学のためにと思って。
>>413
そうですか…。勝手に CLASS.Create() はdelphiスタイルと思い込んでいました。
>>414
分かりました、ありがとうございます。他の方法をとります。
>>415
なるほど…。今回の場合ですが、例が不適切でした。
実は一段下でそれに似たことを行っており、(例? Deal *deal = card.startDeal() )、
かつcardを多数作るわけではなかったので三重は大げさかなと思った次第です。

今回は例外で行きますが、今後三種類の方法を適宜使い分けることにします。ありがとうございました。
情報が小出しになった&長文失礼しました。

417 名前:デフォルトの名無しさん :04/06/13 00:08
Cスレより誘導されてまいりました。同じことを質問しますがお許しください。
データの初期化について質問します。
例えば以下の例が有るとします。
enum Type
{
  taaa,
  tbbb,
  tccc,
  tlast
};
static char* lpType[tlast];
void main()
{
  lpType[taaa] = "aaa";
  lpType[tbbb] = "bbb";
  lpType[tccc] = "ccc";
  printf(lpType[tbbb]);
}
これはこれで上手く行ってる訳ですが何となく美しくない。
そこでこれをlpTypeを宣言した時に初期化したいわけですが
何らかの方法って無いでしょうか。
要は
static char* lpType[tlast] = {
  [taaa] = "aaa",
  [tbbb] = "bbb",
  [tccc] = "ccc",
};
見たいな事が出来ないかなぁと思うわけですが。


418 名前:デフォルトの名無しさん :04/06/13 00:11
>>417
http://pc5.2ch.net/test/read.cgi/tech/1087049069/32

419 名前:デフォルトの名無しさん :04/06/13 00:19
グローバルなクラスオブジェクト
...を要素とする配列
...をメンバ変数にもつクラスオブジェクト
...がTypeを添え字にとる配列オペレータを定義
していれば、できるんじゃねーかな。


420 名前:デフォルトの名無しさん :04/06/13 00:49
enum Type
{
  taaa,
  tbbb,
  tccc,
  tlast
};

template< std::size_t N >
class lpType {
static char[] tmp;
public:
static ostream&
operator<<( ostream& os ) const {
os << tmp;
}
};

lpType<taaa>::tmp = "aaa";
lpType<tbbb>::tmp = "bbb";
lpType<tccc>::tmp = "ccc";
template< std::size_t N >
lpType<N>::tmp = "not defined";

int main( void ) {
std::cout << lpType<taaa> << std::endl:
}


421 名前:デフォルトの名無しさん :04/06/13 00:52
あ〜、間違えてら。

422 名前:デフォルトの名無しさん :04/06/13 01:07
いろいろ調べてみましたがどうやらVCはC99に対応していないようなので
>418の方法は無理みたいですね。
それにC99を使うとなるとC++は使えなくなるようなのでこれも問題です。
とりあえず今回は勉強になったのでこれで良しとします。
有難うございました。

>>420
ここまでやるぐらいなら最初にmainで定義したほうが良さげです。
これはこれで面白いのですが。


423 名前:デフォルトの名無しさん :04/06/13 08:40
Javaで言うとことのプロパティファイルを読みこむ自社製ライブラリがあります。
名前=値に加え、型情報などの情報が「バイナリ形式」として納められています。

↓イメージ(実際はバイナリ)
long=name1=-123
unsigned long=name2=123
char *=name3=hello

↓値取得のクラス&メソッド(名前と型が一致しないと例外発生。型を取得するメソッドはない。)
void Conf::Conf(const char *file);
void Conf::getValue(const char *name, long *l);
void Conf::getValue(const char *name, unsigned long *lu);
void Conf::getValue(const char *name, char **s);

■このクラス&メソッドを下のような形式にラッピングしたいと思っています。
適切な型 ConfX::getValue(const char *name);

基底クラスをあとから作る?例外で条件分岐?なにかよい方法ありませんか?


424 名前:デフォルトの名無しさん :04/06/13 08:59
>>423
どうすれば「よい」とみなすのか示せボケ

425 名前:デフォルトの名無しさん :04/06/13 09:56
>>423
役に立つかどうかは知らないが
http://www.ksky.ne.jp/~seahorse/cpp/virtualbase.html

426 名前:デフォルトの名無しさん :04/06/13 16:05
CBaseを基底クラスとしたCAとCBと言うクラスが有ります。
そしてCBaseにはhoge()と言う仮想関数を実装しています。
そして現在、以下のようなコーディングをしていますがー
CBase* pBase;
switch (i)
{
case 0:
 pBase = new CA;
 break;
case 1:
 pBase = new CB;
 break;
}
pBase->hoge();

正直綺麗じゃないし無駄なような気がします。
クラスを配列に定義して以下のように何とか出来ないでしょうか。
pBase = new class[i];

427 名前:デフォルトの名無しさん :04/06/13 16:17
>>426
typedef CBase* NewFunction();
template< typename T > CBase* New(){ return new T; }
NewFunction* const table[] = { &New<CA>, &New<CB> };

pBase = table[i]();

428 名前:デフォルトの名無しさん :04/06/13 16:35
>>1の名前がv(^・^)vでないんですけど。

429 名前:デフォルトの名無しさん :04/06/13 16:55
>>427
うーん、色々やって見ましたが上手く行かないです。
これをどこら辺に定義すれば良いのでしょうか。
とりあえず、こんな感じじゃ無理でした。

#include <windows.h>

typedef CBase* NewFunction();
template< typename T > CBase* New(){ return new T; }
CBase* const table[] = { &New<CA>, &New<CB> };   // エラー

CTest::CTest()
{
 int i = 1;
 CBase* pBase = table[i]();
}

エラーメッセージ
error C2440: 'initializing' : '' から 'class CBase *const ' に変換することはできません。(新しい動作 ; ヘルプを参照)
コンテキストはオーバーロードされた関数の非不明瞭を考慮しません。

430 名前:デフォルトの名無しさん :04/06/13 16:58
っと、上のままの場合だと以下でした。
>CBase* const table[] = { &New<CA>, &New<CB> };   // エラー
NewFunction* const table[] = { &New<CA>, &New<CB> };   // エラー

error C2440: 'initializing' : '' から 'class CBase *(__cdecl *const )(void)' に変換することはできません。(新しい動作 ; ヘルプを参照)
スコープ内でこの名前を持つ関数でターゲット型に一致するものはありません。

431 名前:デフォルトの名無しさん :04/06/13 17:31
>>429
class CBase{};
class CA : public CBase{};
class CB : public CBase{};

typedef CBase* (*NewFunction)();
template< typename T > struct NewT{ static CBase* New(){ return new T; } };
NewFunction table[]={&NewT<CA>::New,&NewT<CB>::New};


int main(){
CBase *p=table[0]();

432 名前:デフォルトの名無しさん :04/06/13 17:34
>>429
まずはVC6を捨てる。

433 名前:デフォルトの名無しさん :04/06/13 17:39
>>431
上手く出来ました。有難うございました。

434 名前:デフォルトの名無しさん :04/06/13 18:14
constは捨てろってことだな

435 名前:デフォルトの名無しさん :04/06/13 18:30
>>434 何の話?

436 名前:デフォルトの名無しさん :04/06/14 00:33
VS2002にVCToolKit2003をいれてstlport4.6.2でboostコンパイルできた人いる?
error LNK2019: unresolved external symbol "__declspec(dllimport)
int __cdecl swprintf(unsigned short *,unsigned int,unsigned short const *,...)"

が4個ほど出るよ…

437 名前:デフォルトの名無しさん :04/06/14 00:45
変な組み合わせすんなよ
2002使えるってことは2003もらってるはずだろ

438 名前:デフォルトの名無しさん :04/06/14 00:54
アカデミックだったり(泣

439 名前:デフォルトの名無しさん :04/06/14 02:23
コンストラクタにテンプレート引数を渡したいのですが引数を使って
暗黙的?に渡す以外はコンパイルエラーになってしまいます
A自体にtemplateをつける以外でどのようによびだせばよいでしょうか?
struct A
{
  template<class T>A()
  {
    cout << typeid(T).name() << endl;
  }

  template<class T>A(T)
  {
    cout << typeid(T).name() << endl;
  }
};

int main()
{
// A a<int>(); こういう感じで呼びたい
  A a(1); //かっこ悪い
  return 0;
}

440 名前:デフォルトの名無しさん :04/06/14 03:41
何で、
>A自体にtemplateをつける以外で
こんなことしたいの?

441 名前:デフォルトの名無しさん :04/06/14 04:45
ちょっとした型推論ですよ。ありがたく省略しないと。

442 名前:デフォルトの名無しさん :04/06/14 05:57
>>439
もしかしてVCか?
明示的なテンプレート実引数の
正当な形を撥ねるケースよくあるぞ

443 名前:デフォルトの名無しさん :04/06/14 08:49
コンストラクタで、そういったことがしたいなら、以下のような手を使うとかね。
ちょっと格好悪いかも知れんけど。

template< typename T > struct type{};

template< typename T >
A::A( type<T> )
{
  cout << tyoeid(T).name() << endl;
}


A a( type<int>() );


444 名前:デフォルトの名無しさん :04/06/14 14:16
>>377
そんなものがあったんですね。ありがとうございました。

で、さっそく使ってみたのですが、
tokenizer.hppをincludeしてビルドしたところ、以下のようなビルドエラーが出ました。

boost\tokenizer.hpp(60) : error C2039: 'begin' : 'CString' のメンバではありません。
c:\program files\microsoft visual studio\vc98\mfc\include\afx.h(368) :
'CString' の宣言を確認してください。
C:\VC_PROJECT\0806\01\Main1.0β_0806\SetUserEntryDlg.cpp(310) :
コンパイルされたクラスのテンプレートのインスタンス化 '__thiscall boost::tokenizer<class boost::char_delimiters_separator<char,struct std::char_traits<char> >,char const *,class std::basic_string<
char,struct std::char_traits<char>,class std::allocator<char> > >
::boost::tokenizer<class boost::char_delimiters_separator<char,struct std::char_traits<char> >,char const *,class std::basic_string<char,struct std::char_traits<char>
,class std::alloca
tor<char> > >(const class CString &)' の参照を確認してください

問題の個所は

template <typename Container>
tokenizer(const Container& c)
: first_(c.begin()), last_(c.end()), f_() { }

となっています。これってboostのバグなのでしょうか。それともこちらの設定か何かが悪いのでしょうか。
長くてすみません。

445 名前:デフォルトの名無しさん :04/06/14 14:25
>>444
CString じゃなくて std::string を使うべき。

446 名前:444 :04/06/14 14:30
すみません。
読ませるのをCStringじゃなくstringにしたら通りました・・
お騒がせしました。

447 名前:444 :04/06/14 14:37
>>445
あ、ありがとうでした。

448 名前:デフォルトの名無しさん :04/06/14 17:26
boost::functionにtemplate関数を代入したいのですが、
以下のコードではコメントアウトした部分ですべてコンパイルできませんでした。
何とかならないでしょうか?

#include <iostream>
#include <boost/function.hpp>

template< typename X >
void
testFunc( const X x ) {
std::cout << typeid(x).name() << std::endl;
}

int
main( void ) {
//boost::function< void ( const int ) > f;
//boost::function< template< typename X > void ( const X ) > f;
//boost::function< void template< typename X >( const X ) > f;
//boost::function< void ( template< typename X > const X ) > f;

f = testFunc;
f( 1 );

return 0;
}

449 名前:デフォルトの名無しさん :04/06/14 17:44
>>448
boost::function<void (const int)> f; // constはなくても変わらない。
f = static_cast<void (&)(const int)>(testFunc); // void (*)(const int)でも良い。

450 名前:デフォルトの名無しさん :04/06/14 17:50
キャストすれば良かったのか…
とおりました、ありがとです。

451 名前:デフォルトの名無しさん :04/06/14 18:40
本番が出来ませんでした…orz
boost/graphの
boost::in_degreeをつっこみたいのですが。宣言だけ書いてみます。
template< class Config, class Base >
inline typename Config::degree_size_type
in_degree( typename Config::vertex_descriptor, const adj_list_helper< Config, Base >& );



452 名前:デフォルトの名無しさん :04/06/14 23:56
関数の戻り値の型(?)がoperatorとなっているものを
見かけたのですが、これはどういう意味でしょうか。

453 名前:デフォルトの名無しさん :04/06/14 23:59
>>449
ふつうは、キャストを嫌ってこっちだとおもうが。
boost::function< void (int) > f = testFunc< int >;


454 名前:デフォルトの名無しさん :04/06/15 00:02
>>452
ttp://www.kuzbass.ru/docs/isocpp/special.html#class.conv.fct

455 名前:デフォルトの名無しさん :04/06/15 00:18
newで作った配列の初期化はどのようにすればいいのでしょうか?
文法がよくわかりません。
int *p = new int[3] = { 1, 2, 3 };

int *p = new int[3] { 1, 2, 3 };
とやっても構文エラーがでてしまいます。
JavaやC#は下のやり方でいけるのですが。

456 名前:デフォルトの名無しさん :04/06/15 00:25
>>455
できません。

457 名前:455 :04/06/15 00:31
>>456
ガ━━━━━━(゚д゚lll)━━━━━━ン

458 名前:デフォルトの名無しさん :04/06/15 00:32
>>455
#include <vector>
static int const initial[3] = {1,2,3};
std::vector<int> v(&initial[0],&initial[3]);

459 名前:デフォルトの名無しさん :04/06/15 03:16
class A
{
protected:
 int a;
public:
 int GetA() const { return a; }
 void SetA(int a) { this->a = a; }
};

class B : public A
{
protected:
 double b;
public:

};

このようなクラス関係で

B bInstance[100];
bInstance[1].SetA(50);

const A* ptr = bInstance;
++ptr;
int result = ptr->GetA();

とやるとポリモーフィズムでresultに50が入ると思うのですが、
実際には正しい値が得られません。
どこがおかしいのでしょうか?ご教授下さい。

460 名前:デフォルトの名無しさん :04/06/15 03:36
>>459
C++のポリモはポインタが指してる先のオブジェクトへの操作
( *ptrか ptr ->mem_function() )についてだけで
ポインタそのものの操作(この場合、++ptr)に対しては
ポリモではないから。

つまり++ptrが間違い。


461 名前:デフォルトの名無しさん :04/06/15 03:46
>>459
ポリモーフィックなクラスを配列にしてはいけない。

参考:More Effective C++ の
「項目3: 配列をポリモルフィズム的には扱わない」

462 名前:デフォルトの名無しさん :04/06/15 03:48
>>460
そういうものなのですね。ありがとうございました。

463 名前:デフォルトの名無しさん :04/06/15 05:09
>「項目3: 配列をポリモルフィズム的には扱わない」
C++っていたるところで腐臭がする言語ですね。

464 名前:デフォルトの名無しさん :04/06/15 05:48
そうでもないよ。

465 名前:デフォルトの名無しさん :04/06/15 06:10
やっぱり
C++は
ダサい


466 名前:デフォルトの名無しさん :04/06/15 06:18
ポリモーフィックなクラスへのポインタ配列を使えばいい。
基底クラスやそこから派生したクラスを同一の配列に押し込むのは、サイズの違う
構造体を一つの構造体配列に無理矢理入れるのと同じ。破綻して当たり前。

467 名前:デフォルトの名無しさん :04/06/15 07:32
>>452
struct mona { operator giko (); };
なら、mona型からgiko型へのキャスト
mona c;
(giko)c;

468 名前:デフォルトの名無しさん :04/06/15 09:37
ポリモーフィックはJavaでは良く使うんだがC++ではちょっと難しいね

469 名前:デフォルトの名無しさん :04/06/15 09:44
boost::tokenizerについて2つ質問です!

typedef boost::tokenizer<> tokenizer1;
tokenizer1 token( strLine );
for( tokenizer1::iterator it=token.begin(); it!=token.end(); ++it ){
cout << "TOKEN: " << *it << endl;
}

strLine には id001,あいうえお,pass,1, という文字列が入ってます。
で、 it の中の tok_ を見てくと、一回目は "id001" がちゃんと切り出されているのですが
二回目は "あいう" となっていて 三回目は "お" となっています。
区切り文字が "," 以外にも使われているのが原因か、日本語がだめなのかどちらかだと思います。
区切り文字を指定する方法、日本語を使う方法、わかりませんか?

2つめ。itに入ったトークンをCString か std::string か char[] にコピーするにはどうしたらいいでしょうか。

470 名前:デフォルトの名無しさん :04/06/15 09:53
単なるポインタの理解の問題に見えるけど?
459ってポリモーフィック関係ある?

471 名前:デフォルトの名無しさん :04/06/15 11:48
>>468
Java や C# のようにいちいち new するやり方なら、C++ も似た様な動きをすると思うけど。

472 名前:デフォルトの名無しさん :04/06/15 11:50
>>470
関係ないですね。
C++ 的にはこの場合ポインタじゃなくて iterator をつかうべし、ということになるんでしょうね。
アドホックに済ませるならポインタ進めるための Next とかいうメンバ関数を用意するとか。

473 名前:デフォルトの名無しさん :04/06/15 13:21
C++のごちゃごちゃな仕様を組み合わせた結果
直感に反する挙動を示したからっていまさらキーキー言うのはナンセンスだよ。
カレーに肥料としての効果を期待するようなもんだ。

474 名前:デフォルトの名無しさん :04/06/15 15:34
すみません。質問ですー
DB検索結果を格納するために
連想配列を使用してやろうとおもっているのですがなかなうまくいきません。
vector<map<string, string>>の型に格納予定です。
要素のmapにアクセスできないみたいです。 どのように書けばうまくアクセスできるのですか?

typedef StringHash map<string,string>
typedef VectorStringHash vector<StringHash>

VectorStringHash *pvsh // 検索結果格納済み
vector<string> vstrFieldName // フィールド名

for (VectorStringHash::iterator vit = pvsh->begin(); vit < pvsh->end(); vit++)
{
 for (vector<string>::iterator it = vstrFieldName.begin(); it < vstrFieldName.end(); it++)
 {
  StringHash shMap = *vit;
  StringHash::const_iterator n = (StringHash::const_iterator) (*vit).find(*it);
  string strMap = n->second; //Segmentation faultでおちちゃう。
 }
}



475 名前:デフォルトの名無しさん :04/06/15 15:39
C++のときはnewは滅多に使わないな。
遅くなるし...面倒だし...
継承もメモリもったいないからなるべくしない...
ようにしてる


476 名前:デフォルトの名無しさん :04/06/15 15:42
>>475
たぶん、その餌じゃ釣れませんよ。

477 名前:デフォルトの名無しさん :04/06/15 15:52
>>474
つーか、そのコードじゃコンパイル通らんぞ普通。

478 名前:デフォルトの名無しさん :04/06/15 16:41
フリーのコンパイラを入れて、とりあえず何か作って練習しようと思ってるんですが
GCC と Borland C++ Compiler だとこちらの方がおすすめとかありますか?
・特殊な部分がなく汎用的で、後から別の環境に移りやすいか
・初心者にも使いやすいか
の2つを気にしてるんですが・・・

479 名前:デフォルトの名無しさん :04/06/15 16:53
>>478
Win32APIに触って窓出したりする必要ないならCygwinのgccが無難なんじゃないの。
フリーのbccは進歩止まってるし。

480 名前:デフォルトの名無しさん :04/06/15 16:53
http://www.skunksoup.com/images/funpics/camelspider1.jpg
こういうのを作りたいんだけど

481 名前:デフォルトの名無しさん :04/06/15 16:57
>>474
typedefの使い方が変。

482 名前:デフォルトの名無しさん :04/06/15 16:57
>>479
フリーのBuilderXに新しいBCCついてるよ

483 名前:デフォルトの名無しさん :04/06/15 17:13
>>474
nがendだから?

484 名前:デフォルトの名無しさん :04/06/15 17:48
>>474

x < it->end() って意味あんの?
x != it->end()じゃね?

485 名前:デフォルトの名無しさん :04/06/15 18:06
>>484
いみあるよ

486 名前:デフォルトの名無しさん :04/06/15 18:26
すみません。解決しました。
>>483さんの助言で見直したところ
表示ルーチンはまったく関係なかったようです。
mapを作るときにどうやらスコープを考えてなくつくったようで
内容がすべておかしくなってました。
お騒がせしました。


487 名前:デフォルトの名無しさん :04/06/15 19:37
>>478
フリーって時点で「初心者向き」は消えたも同然
ベテランにとって必要な機能に限定した軽快な味が売りだからね

手取り足取りのサポートが欲しければ金がかかるのは世の常だよ

488 名前:デフォルトの名無しさん :04/06/15 20:03
>>478
gcc しかないと思う。
風変わりな拡張を多用しないし、処理系固有のクラスライブラリとか覚えなくて済むし。
あと、コンパイラに「使いやすい・使いにくい」っていう差は特にないと思う。
あまり古いものだと規格準拠度が落ちて問題あるかも知れないけど。

489 名前:デフォルトの名無しさん :04/06/15 20:18
>>488
>処理系固有のクラスライブラリとか覚えなくて済むし。
は? 別に付属してるもの全部覚える必要なんぞ無いだろ?


490 名前:デフォルトの名無しさん :04/06/15 20:22
>>489
そういやそうだ。

491 名前:デフォルトの名無しさん :04/06/15 21:47
オーバーライド可能な演算子にカンマがあるのですが

これって何の用途があります?

492 名前:デフォルトの名無しさん :04/06/15 22:49
>>491
cppllにいろいろ例が載ってるよ

493 名前:デフォルトの名無しさん :04/06/15 22:52
>>492
とはいえ、無理に使わないほうがイロイロな意味で幸せな気もする。

494 名前:491 :04/06/15 23:04
>>492
http://www.tietew.jp/cppll/archive/364
この辺ですか?参考にさせてもらいます。
ありがとうございます。

なんだか、ものすごくトリッキーな感じがするので
頭の体操にいはなるけど、素人は近寄らないほうがよさそうですね。


495 名前:デフォルトの名無しさん :04/06/15 23:11
ま、そんくらいでトリッキーとか言い出す人の発言としては嘘じゃあんめえな

496 名前:デフォルトの名無しさん :04/06/15 23:14
>>495
一見してデフォルトとまったく違う動きをするようなコードは、避けたほうが
良いと思うけどな。演算子オーバーロードにせよプリプロセッサのマクロに
せよ。

ネタとしては面白いけど。

497 名前:452 :04/06/15 23:14
>>467
レスありがとうございます。なんとなくそんな気がするのですが、
(giko)c
というより
giko(c)
ではないのでしょうか・・・それともどっちでもいいんですかね。

498 名前:デフォルトの名無しさん :04/06/15 23:17
>>497
いてっ
おめーに突っ込まれるとな・・・
俺もヤキ回ったな

499 名前:デフォルトの名無しさん :04/06/15 23:20
>>496
あんたの「一見」って? (ニヤニヤ

500 名前:デフォルトの名無しさん :04/06/15 23:26
>>499
昔ハマったのは operator&& のオーバーロード。C/C++ だと組み込み演算子の && は
短絡評価できることが保証されているから

return foo() && bar();

だと foo() が真なら bar() は評価されない。しかし operator&& オーバーロードして
あると bar() も評価されちゃうので、意味合いがまったく違ってしまう。

字面が同じで一見してバグを発見できずに数人が半日無駄にした覚えあり。この
オーバーロードをしたヤツが、その後どうなったかはとても言えない。


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