[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 2chのread.cgiへ]
Update time : 05/14 14:02 / Filesize : 217 KB / Number-of Response : 865
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C++相談室 part71



1 名前:デフォルトの名無しさん [2009/07/18(土) 02:54:58 ]
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

前スレ
C++相談室 part70
pc12.2ch.net/test/read.cgi/tech/1244942050/l50

369 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 21:58:44 ]
>>367
この手の場面に相当するような「デカい仕事」では、実際結構な確率で
いま出ているような物を使うことになると思う。

370 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 22:02:12 ]
危険な機能を使わないためと言って変な黒魔術で無理矢理回避する方がよっぽど危険だしな

371 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 22:25:27 ]
Windowsでプログラムしていると
reinterpret_cast と dynamic_cast のオンパレードですよ^^

372 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 22:30:33 ]
>>371
キャストが必要になるのはわかるが、オンパレードはおかしいだろ。
同じ意味のキャストはてきとうにラップしろよ。

373 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 22:39:44 ]
ダウンキャストの意味わかってるのか?
存在しないメンバにアクセスして鼻から悪魔が出るのを承知で
使わないといけないんだぞ

374 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 22:43:35 ]
HWND(構造体へのポインタ)をCWndクラスにキャストさせたり、Windowsプログラミングは楽しいなぁ^^

375 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:12:24 ]
C++やりたての頃はこういう鼻から悪魔の意味もわからなかった

#include <iostream>

class Base {
int i;
public:
virtual void print() const {
std::cout << "Base" << std::endl;
}
};

class Derived : public Base {
public:
void print() const {
std::cout << "Derived" << std::endl;
}
};

int main()
{
Base *p;

p = dynamic_cast<Derived*>(new Base);

p->print(); // ouch!
}

376 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:17:31 ]
>>375
これはどの辺が鼻から悪魔?


377 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:18:56 ]
>>376
BaseにはDerived::print()がない

実行してみればわかるが正しく動かない



378 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:20:46 ]
>>376
dynamic_cast<Derived*>(new Base) この結果がヌルポインタになる。
その後の p-> でヌルポインタをデリファレンスして未定義動作。

379 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:21:39 ]
>>377 えっ?

380 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:25:38 ]
ごめんこういう場合に使うんだったね

#include <iostream>

class Base {
int i;
public:
virtual void print() const {
std::cout << "Base" << std::endl;
}
};

class Derived : public Base {
public:
void print() const {
std::cout << "Derived" << std::endl;
}
};

int main()
{
Base* p;

p = dynamic_cast<Base*>(new Derived);

if (!p)
std::cout << "dynamic_cast failed." << std::endl;

p->print(); // ouch!
}

381 名前:376 mailto:sage [2009/08/09(日) 23:27:43 ]
すみません
>>377

>>378
はどちらが正しいですか?

382 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:29:07 ]
>>381
>>378が正しい
ダウンキャストはポインタが正しい本体を指している時にのみ成功する

383 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:37:32 ]
>>380
これは何でouch!なの?

384 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:38:21 ]
>>380
いや、 Derived* → Base* は暗黙変換で通るから、 dynamic_cast の出番じゃない。

しかも、せっかく dynamic_cast の結果にチェックを入れたのにメッセージ表示の後に
結局 p-> してたらダメじゃん。

385 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:40:07 ]
わかんね
dynamic_castの正しい使い方知ってる人教えて

386 名前:デフォルトの名無しさん mailto:sage [2009/08/09(日) 23:48:07 ]
DerivedがBaseとBase2を継承してるとして

・Derived* → Base* (アップキャスト)
常に成功し、Baseのポインタが得られる

・Base* → Derived* (ダウンキャスト)
DerivedのBase部分を指してるポインタだったら正しいDerivedのポインタが得られる
そうでなければヌルポインタが返ってくる

・Base* → Base2* (クロスキャスト)
DerivedのBase部分を指してるポインタだったら正しいBase2のポインタが得られる
そうでなければヌルポインタが返ってくる

・Base* → int* (無関係)
常にヌルポインタが返ってくる

参照の場合は、以上の「ポインタ」を「参照」、「*」を「&」、
「ヌルポインタが返ってくる」を「std::bad_cast例外が投げられる」に読み替えればいい

387 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 00:01:23 ]
よく見ろよw
>>375のは
p = dynamic_cast<Derived*>(new Base);
どこにもDerivedのインスタンスは生成されない
そりゃNULLが帰ってくるだろうって




388 名前:357 mailto:sage [2009/08/10(月) 00:18:37 ]
>>358-359
ありがとうございます。
NaNについてはもっと勉強してきます。


389 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 00:45:20 ]
>>369
そういう話ではなく
> 「できればこれを使わずに済ませたいものだが・・・」
といったらそれは使うフラグ

390 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 01:35:06 ]
>>389
まさにそういう話だと思うが。

391 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 02:23:56 ]
仕事のデカさは関係ないってことじゃないの?

392 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 12:33:39 ]
dynamic_castの意味を今まで勘違いしてたわ
ダウン・キャストしても安全に使用できるかどうかの判定なのね

393 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 15:40:20 ]
VS2008のVC++MFCで
ボタンクリックでピクチャーコントロールにjpgファイルの画像をサイズを変えて表示しています。

以下ソース
CImage img;
CImage img2;
HDC hdc;
img2.Create(80,60,24);
img.Load("jpgファイルのフルパス");
hdc = img2.GetDC();
SetStretchBltMode(hdc, HALFTONE);
img.Draw(hdc, 0, 0, 80, 60);
img2.ReleaseDC();
m_xcPic01.SetBitmap( (HBITMAP)img2 );
img.Destroy();
img2.Detach();
img2.Destroy();

jpgファイルが変わる毎に、画面上の画像も切り替えたいので
上の処理を呼び出して、画面を切り替えてます。
しばらく動かしていたところで気付いたのですが、
メモリの使用量がかなり多くなっていました・・・
ファイルロード側のDestroyやリサイズ後側のDetach、Destroyだけでは解放してくれないのでしょうか?
わかる方、または参考になるサイトやスレをご存知の方、よろしくお願いします。

394 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 15:45:28 ]
Detachしてしまったビットマップは削除されないのでは

395 名前:デフォルトの名無しさん [2009/08/10(月) 15:48:42 ]
ヘッダーに変数を定義することって出来たんでしたっけ?
いや、さっき書いてみたら出来たんで、ちょっとびっくりしたんですが。
インクルードガードしてないとエラーが出るってだけなのかな。Cではどうなんでしょう。
まあ、作法としてはインクルードガードしててもやっちゃダメなのかもしれないですけど。ですよね?



396 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 15:54:56 ]
本当ならリンカが多重定義のエラーを吐くはずだが、デフォルトでは吐かない奴もいる

397 名前:393 mailto:sage [2009/08/10(月) 15:58:12 ]
>>394
レスありがとうございます
Detach後にDestroyすると、メモリ上に残る・・・
つまり、リサイズ後用のimg2がどんどん溜まっている状態
ってことでしょうか?

ためしにimg2.Detach();をコメントアウトして動作させると、
別ウィンドウの後ろに隠れると画像が消えると言う症状がでました。
私、根本的に作り方を間違えているのかも・・・



398 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 16:18:59 ]
>>397
MFCスレでやってくれ

399 名前:393 mailto:sage [2009/08/10(月) 16:28:29 ]
>>398
MFC相談室の方に移動させていただきます。
スレ汚しすみませんでした。

400 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 16:45:42 ]
>>395
ヘッダだからできない事というのはないよ
やるべきじゃないことは、ある。

401 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 17:42:52 ]
>>400
>ヘッダだからできない事というのはないよ

へー、そうなんですか。
逆に、ソースだとできないことってのはありますよね?
テンプレートの定義とか。


402 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:00:51 ]
>>401
.hも.cppもC++の上では本質的には変わりないんだよ。
テンプレートの定義だって、別に.cppの上でやったっていい。
その定義が他の.cppから見えるかどうかは別問題だがな。

403 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:06:33 ]
>>401
だからできないことはないって。
逆に聞くが、ヘッダとソースってどうやって区別してんの?

404 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:08:23 ]
定義そのまま他の.cppに丸ごとコピペすればいいわけだが、
後々修正する際に全部直して回るのが面倒だからそういうことはやらないだけだ

405 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:09:46 ]
#include "header.cpp"
この場合、header.cpp はヘッダなのかソースなのか

406 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:38:26 ]
>>405
いわゆるクソコードってやつだよ。

407 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:46:46 ]
オブジェクト指向について質問なんだけど。

クラスAのインスタンスをクラスBで作り
クラスBのメソッドからクラスAのprivateにあるメンバ変数をゲッターセッターを使って弄る(クラスBのメンバ変数にも同期させる)。
そして、又クラスCのメソッドからクラスBにあるメンバ変数を参照して、判定なりをする。

そういう風に包含を重ねて行くのがオブジェクト指向なの?
C++をやって間もないんだけど、俺のプログラムはこんな感じなんだ。
良いのか悪いのか分からない、アドバイスお願い



408 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:48:16 ]
>>405
学生の時にバイトしていた会社のコードにそういうのがあった
日本のロケットがクソ高くて落ちるわけだ、と思った

409 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:54:57 ]
クソコードでバグを入れて、
そのバグを取るのが仕事ですから
それでいいんです。

410 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:56:03 ]
>>407
俺はメソッドとかC++標準にない用語を使われても起こらない。
しかし
>>クラスAのインスタンスをクラスBで作り
これはどういう意味だい?

411 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 18:58:28 ]
>>410
えっと
クラスBのprivate領域に、クラスAの実体を包含するって意味で書いたつもりだった

412 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 19:03:01 ]
>>406
クソかどうかは関係ない。
できないことがあるのかどうかが論点であり、やるべきではないことはまた別の話

413 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 19:44:54 ]
>>407
>又クラスCのメソッドからクラスBにあるメンバ変数を参照して、判定なりをする。
クラスBでクラスBのメンバ変数を参照して判定するようにして、外からメンバ変数を
見せないように隠蔽するのが、オブジェクト指向のカプセル化の基本かな。
セッタ/ゲッタはそれを破ってしまうから避ける様に設計するのがお勧め。

414 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 20:12:31 ]
雪駄とか下駄はオブジェクト指向じゃないと個人的には思う。
単一責任原則をはたすためにも、
メソッドは単に状態を書き換えるだけでは十分でないと思うから。


415 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 20:15:25 ]
セッタ/ゲッタは最終手段であり、
それに突入した瞬間からクソコードが始まると考えて
「一般には」さしつかえないくらい。


416 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 20:33:13 ]
C++ code - 95 lines - codepad
ttp://codepad.org/xR4PHa3G
この
std::numeric_limits
の明示的特殊化のコードは、
g++ 4.4.0では問題無くコンパイル・実行できました。
しかし
Microsoft Visual Studio 2008
Version 9.0.30729.1 SP
では
 error C2910: 'std::numeric_limits<MyTempl<MyInt>>' : 明示的な特殊化にすることはできません。
となり、コンパイルエラーとなってしまいます。
VCでも通す方法はありませんでしょうか?

Compiler Error C2910
ttp://msdn.microsoft.com/en-us/library/cx7k7hcf(VS.71).aspx
このあたりを読んでみましたが、よく分かりませんでした。
よろしくお願いします。



417 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 20:52:34 ]
stdの中を無理矢理いじくってるからかなあ
多分ヘッダーlimitsのどこかとぶつかってるよ



418 名前:416 mailto:sage [2009/08/10(月) 20:56:41 ]
std名前空間は
新しい物を追加したりすれば未定義の動作となる。
しかし関数・クラステンプレートの特殊化のみ
認められる。

ということは知っているのですが、
私のやり方がまずいのでしょうか。。。



419 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 20:57:14 ]
template <typename MyInt>
この行いらない

420 名前:416 mailto:sage [2009/08/10(月) 21:04:44 ]
すみません。
その辺確かにまずかったです。

C++ code - 95 lines - codepad
ttp://codepad.org/yovzUoIJ

これはどうでしょうか?
やりたいことは
template <typename hoge_t>
struct numeric_limits< MyTempl<hoge_t> > : numeric_limits< hoge_t >
の部分で現れていると思います。


421 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:07:00 ]
template <typename hoge_t>
の前の
template <>
が要らないんじゃ

422 名前:416 mailto:sage [2009/08/10(月) 21:25:35 ]
>>421
それで通りました!

皆様ありがとうございます。
本気で助かりました。。。

423 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:32:54 ]
そのままで通るBCC6.1.3は欠陥コンパイラという事か

424 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:36:47 ]
いやg++も通っているから別に欠陥ではないのでは?
VCが厳しいのかな。

g++ + 訂正前 -> 通る
g++ + 訂正後 -> 通る

VC++ + 訂正前 -> 通らない
VC++ + 訂正後 -> 通る

BCC6.1.3 + 訂正前 -> 通る
BCC6.1.3 + 訂正後 -> ???

訂正後はBCCで通る?


425 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:43:25 ]
>>424
訂正後も通るよBCC

426 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:47:26 ]
g++ + 訂正前 -> 通る
g++ + 訂正後 -> 通る
VC++ + 訂正前 -> 通らない
VC++ + 訂正後 -> 通る
BCC6.1.3 + 訂正前 -> 通る
BCC6.1.3 + 訂正後 -> 通る

じゃあ通る動作と通らない動作、
どっちが規格的には正しいのだろう?


427 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 21:55:42 ]
BCCは歴代的にテンプレート周りが怪しいとして(もっとも
今回のバージョンからboostに部分的に対応しているんだが)
g++が通ってるんだからvc++が厳しすぎるんじゃね?



428 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 22:29:15 ]
@aaaaaaaaa.cpp
ttp://codepad.org/8b4slwrj
こうすると、VC++では
 error C3767: 'foo': 候補の関数はアクセス可能ではありません。
 'aaaaaaaaa.cpp(26)' の friend 関数である可能性があります : 'foo' [引数依存の
 照合を使って検出される可能性があります]
というエラーになります。
ところが
namespace MyNS
を外してグローバルスコープにすると
ttp://codepad.org/nBmNHA3H
このコードのようになりますが、VC++で通ります。
なお、g++ではどちらも通ります。

Aまた、//問題の箇所2の行をコメントアウトした
C++ code - 50 lines - codepad
ttp://codepad.org/J3kjckz1
はg++, VCどちらも通らなくなります。
(インスタンス化されていないため?)

@Aの問題の原因としては
//問題の箇所1
あたりのやりかたがまずいのかと思っているのですが、
正解のコーディングをご教示いただけますでしょうか?

よろしくお願いいたします。


429 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 22:55:18 ]
BCC6.1.3はg++に準ずる結果となりました
VC++だけ挙動が違うね

430 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:07:02 ]
VC++, g++, BCC 以上に
標準C++準拠度が高いコンパイラって無いのかな?

性能は悪くても良いから標準C++準拠度だけを命にしているコンパイラ。

431 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:17:19 ]
Comeau C++とかか?

432 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:20:27 ]
using namespace MyNS;で通るね
MSDNによると Friend function names are no longer introduced into containing namespace
だそうなのでMyNS::fooの時点でADLが利かなくなるってことかな?規格なんて読んだことないから知らないけど。

433 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:22:02 ]
補足 using namespaceしてからMyNS::fooをfooだけに

434 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:34:50 ]
違いますか?
どのあたりが違いますか?

435 名前:430 mailto:sage [2009/08/10(月) 23:35:35 ]
Comeau C/C++ - Wikipedia, the free encyclopedia
ttp://en.wikipedia.org/wiki/Comeau_C/C%2B%2B
こんなん初めて聞いた俺がいる。
ありがとう。>>431

436 名前:デフォルトの名無しさん mailto:sage [2009/08/10(月) 23:36:44 ]
事実上exportキーワードに対応させてるコンパイラは
今の所これだけだしな

437 名前:434 mailto:sage [2009/08/10(月) 23:37:55 ]
誤爆しました。
失礼しました。



438 名前:428 mailto:sage [2009/08/10(月) 23:56:23 ]
Comeau C++のWebサイトで

ttp://codepad.org/J3kjckz1
を実行してみました。

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 44: error: namespace "MyNS" has no member "foo"
MyNS::foo<double>(MyNS::MyTempl<MyNS::MyInt>());
^

"ComeauTest.c", line 44: error: type name is not allowed
MyNS::foo<double>(MyNS::MyTempl<MyNS::MyInt>());
^

2 errors detected in the compilation of "ComeauTest.c".

だそうです。


439 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 00:01:41 ]
という事は例のダイヤモンド継承のバグを除けば
VC++の方が標準に近いわけか

440 名前:428 mailto:sage [2009/08/11(火) 00:05:46 ]
>>420

ttp://codepad.org/yovzUoIJ
のtemplate <>あり&無しについて

g++ + 訂正前 -> 通る
g++ + 訂正後 -> 通る
VC++ + 訂正前 -> 通らない
VC++ + 訂正後 -> 通る
BCC6.1.3 + 訂正前 -> 通る
BCC6.1.3 + 訂正後 -> 通る
Comeau C++ + 訂正前 -> 通らない
Comeau C+++ 訂正後 -> 通る

でした。

441 名前:428 mailto:sage [2009/08/11(火) 00:07:05 ]
>>428の@の
ttp://codepad.org/8b4slwrj
ttp://codepad.org/nBmNHA3H
は両方とも通りません。
(VC++で通った)グローバルスコープにおいたら方のttp://codepad.org/nBmNHA3H
でも
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 41: error: identifier "foo" is undefined
foo<double>(MyTempl<MyInt>());
^

"ComeauTest.c", line 41: error: type name is not allowed
foo<double>(MyTempl<MyInt>());
^

2 errors detected in the compilation of "ComeauTest.c".

となりました。

どうやらComeau C++が正しいとすれば、
私の@のコードはどちらも「通る方がおかしい」コードという事になるようです。


442 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 15:32:28 ]
気になったので少し調べてみた
でも憶測も入ってるので間違ってたら突っ込みキボン

1. グローバルかMyNSかで違う
クラス内で定義されたfriend関数はADLを通してしか利用できないっぽい

なので、定義をグローバルに置いたからじゃなくて、
利用側で名前空間を指定しなくなったからコンパイルが通るようになるんだと思う

2. それでもComeauでは通らない
これはワカンネ
関数テンプレートのテンプレート実引数が暗黙的に決まるようにして、
関数呼び出し時に明示的な指定をしないように変えたら、MyNSに入っていてもコンパイルできるようになった
明示的にテンプレート実引数を指定するとダメ
誰か理由を教えてくれ

443 名前:428 mailto:sage [2009/08/11(火) 15:55:47 ]
ttp://codepad.org/405cfVvH
とりあえずfooがテンプレートかつクラス内定義friend関数であることが問題である
可能性が高いと考え、
この様にbar関数(テンプレートでないクラス内定義friend関数)にしてみましたところ
g++ 4.4.0
VC++ 2008
BCC5.5.1
Comeau C++
の4つで問題無くコンパイル・実行できました。

ちなみにbar(MyNS::MyTempl<MyNS::MyInt>());の場所を

MyNS::bar(MyNS::MyTempl<MyNS::MyInt>());
にするとttp://codepad.org/wewb2LHcの様にエラーになります。
::bar(MyNS::MyTempl<MyNS::MyInt>());
にしてもttp://codepad.org/hj2uJmG0の様にエラーになります。

グローバルスコープを明示的に指定するとダメになるところをみますと、
どうやら>>442さんがおっしゃる1.が理由の一つである可能性が高いですね。


444 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 15:59:07 ]
どこで聞いたのか失念したけど
friendとtemplateを併用するとADLがうまく働かなくなるって話を
聞いた事がある

445 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 16:03:18 ]
ちなみにbcc6.1.3では

>MyNS::bar(MyNS::MyTempl<MyNS::MyInt>());
>にするとttp://codepad.org/wewb2LHcの様にエラーになります。
>::bar(MyNS::MyTempl<MyNS::MyInt>());
>にしてもttp://codepad.org/hj2uJmG0の様にエラーになります。

どちらも通ります

どうもADL周りの作り込みが甘いのか構文解析の手抜きをしているのか

446 名前:428 mailto:sage [2009/08/11(火) 16:07:21 ]
みなさんありあがとうございます。

とりあえずfriendにすることを諦めて、次のような逃げ道に走ってみました。
C++ code - 55 lines - codepad
ttp://codepad.org/yBp6Lo3p
こちらのコードは、
g++ 4.4.0
VC++ 2008
BCC5.5.1
Comeau C++
の4つで問題無くコンパイル・実行できました。
事前のインスタンス化なども不要なので、
逃げたような気がしてなりませんが一応解決はできました。。。


447 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 16:16:22 ]
規格票を持っていたら§14.5.3 Friends
を参照してみて欲しい

いろいろと制限がきついことがわかると思う



448 名前:428 mailto:sage [2009/08/11(火) 16:45:41 ]
>>447
すみません。
一介の趣味プログラマ(職業とは関係ない)でして、
規格票は買ってはおりません。

日本工業標準調査会:データベース-JIS詳細表示
ttp://www.jisc.go.jp/app/pager?id=40240
ここで探してみます。

449 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 17:05:27 ]
namespace MyNS
{
//省略

template<typename int_t>
class MyTempl;

template <typename hoge_t, typename boke_t>
hoge_t foo(const boke_t& arg);

template<typename int_t>
class MyTempl
{
public :

int_t num;

MyTempl(int_t n = 0) : num(n) {}


template <typename hoge_t>
friend hoge_t foo(const MyTempl<int_t>& arg)//問題の箇所1
{
return static_cast<hoge_t>(arg.num.num);
}
};
}//namespace MyNS

450 名前:449 mailto:sage [2009/08/11(火) 17:06:42 ]
Comeau C++でコンパイルOK
VC++2008で実行可能

だった。

451 名前:449 mailto:sage [2009/08/11(火) 17:16:19 ]
template<typename int_t>
class MyTempl;

この前方宣言は要らなかった。スマソ。

452 名前:449 mailto:sage [2009/08/11(火) 17:17:00 ]
namespace MyNS
{
//省略

template <typename hoge_t, typename boke_t>
hoge_t foo(const boke_t& arg);

template<typename int_t>
class MyTempl
{
public :

int_t num;

MyTempl(int_t n = 0) : num(n) {}


template <typename hoge_t>
friend hoge_t foo(const MyTempl<int_t>& arg)//問題の箇所1
{
return static_cast<hoge_t>(arg.num.num);
}
};
}//namespace MyNS


453 名前:428 mailto:sage [2009/08/11(火) 17:22:28 ]
>>449さん
その方法なら
テンプレートかつクラス内定義friend関数に
できるのですね。

ありがとうございます。


454 名前:428 mailto:sage [2009/08/11(火) 17:47:41 ]
>>449さんのコードを記しました。
ttp://codepad.org/xotYKfl3
g++ 4.4.0
VC++ 2008
Comeau C++
では通りましたが、
BCC5.5.1
では通りません。
まあどうせBCCが悪いのだろうとは思いますが。

BCC6.1.3をお持ちの方、試していただけませんでしょうか?

455 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 17:49:51 ]
struct { ... } var; という感じで名前のないクラス/構造体を作れると思いますが、
これにコンストラクタ/デストラクタを付けたいなら名前を付けるしかないですか。

456 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 17:51:28 ]
ということは、
>>446の言う逃げのコード(>>446のttp://codepad.org/yBp6Lo3p)
はbcc5.5.1ですら通る互換性の高いコードということか。

bcc5.5.1を見捨てるならどうでもいいんだろうけど。


457 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 17:52:29 ]
>>455
4章:クラス
ttp://www5c.biglobe.ne.jp/~ecb/cpp/04_15.html




458 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 17:56:08 ]
>>454
エラー E2015 codepad9.cpp 49: 'MyNS::double foo<double,MyNS::MyTempl<MyNS::MyInt> >(const MyNS::MyTempl<MyNS::MyInt> &) at codepad9.cpp:8' と
'MyNS::double foo<double>(const MyNS::MyTempl<MyNS::MyInt> &)' の区別が曖昧(関数 main() )

と出てしまいます

459 名前:428 mailto:sage [2009/08/11(火) 18:02:27 ]
>>458
ありがとうございます。
BCC6.1.3でも無理なようですね。

・・・ちなみに、
少し改変した
ttp://codepad.org/LQvoBRSP
g++ 4.4.0
VC++ 2008
Comeau C++
では通りましたが、
BCC5.5.1
では通りません。



460 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 18:10:33 ]
>>457
#include <cstdio>
class {
int foo;
public:
void func() {printf("Whee!:%d\n", foo);}
void set(int v) {foo = v;}
} bar;

int main()
{
bar.set(3);
bar.func();
return 0;
}
--
無事に実行できるけど?

461 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 18:11:59 ]
>>460
元質はコンストラクタ/デストラクタが作れるか聞いているのは判る?

462 名前:457 mailto:sage [2009/08/11(火) 18:12:22 ]
>>460
正直スマンかった。

463 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 18:17:56 ]
>>460
つまり、そのサイトはダメダメということで宜しいか?

464 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 18:34:44 ]
>>459
エラー E2015 codepad10.cpp 59: 'MyNS::double foo<double,MyNS::MyTempl<MyNS::MyInt> >(const MyNS::MyTempl<MyNS::MyInt> &) at codepad10.cpp:8' と
'MyNS::double foo<double,MyNS::MyInt>(const MyNS::MyTempl<MyNS::MyInt> &) at codepad10.cpp:38' の区別が曖昧(関数 main() )

となってやはりbcc6.1.3でも無理です

465 名前:428 mailto:sage [2009/08/11(火) 18:45:35 ]
>>464
Borlandはこのあたり伝統的に対応がおそいようですね。

ありがとうございます。



466 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 18:50:23 ]
template <typename T>
bool is_not_zero(const T& arg);
テンプレート引数T型はint型からT型へ暗黙のキャストが可能なものを選ぶとするとき、
operator!=(const T&, const T&)が定義されていれば
template <typename T>
bool is_not_zero(const T& arg)
{return arg!=static_cast<T>(0);}
とし、定義されていないならoperator==(const T&, const T&)を利用して
template <typename T>
bool is_not_zero(const T& arg)
{return !(arg==static_cast<T>(0));}
とする。
こんな方法は可能でしょうか?
可能でしたらご教示ください。


467 名前:デフォルトの名無しさん [2009/08/11(火) 18:56:51 ]
今朝来たMSDNのメールて、 【64 ビット プログラミング ガイド日本語版を公開中!】 次世代 Windows 環境に備えよう
なんてのが届いたので、みていたら。
int i1 = -2;
unsigned int i2 = 1;
char *s = "Hello";
printf("%s", s + 1 + (i1 + i2));
このコードは32ビットなら動くけれども、64bitだと修正しろとあります。
ぱっと見た目変なところはなさそうにみえるのですが・・・
1.int が 64bit → 問題なし
2.int/unsigend は 32bit で64bit int にキャストされる → 問題なし
3.int + unsigned = unsigned → 0x000000000ffffffffL になるから?
 なんで long int になんねーんだよwなのだろうか?

64bitもっている人誰かいたら解説ください。



468 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 19:00:50 ]
そんな不気味なコード書かないだろうたぶん
たしかWindowsはlongも32ビットだから、size_tやptrdiff_tを使わないとだめなんじゃ?

469 名前:デフォルトの名無しさん mailto:sage [2009/08/11(火) 19:40:33 ]
printfの行がキモすぎるwww
たぶんポインタまわりのことを言いたいんだと思うが。






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<217KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef