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


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

C++相談室 part66



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

前スレ
C++相談室 part65
pc11.2ch.net/test/read.cgi/tech/1230341243/

411 名前:デフォルトの名無しさん [2009/04/05(日) 02:58:05 ]
ねーよ

412 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 03:01:33 ]
std::stringはデフォルトコンストラクタでは空文字列にしてくれることが仕様上保証されているんだよね?
なんて醜態晒すくらいなら
std::string str("");
と書く方がよほどスマート。

413 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 04:02:57 ]
次期規格ではstring()はstring("")に委譲する実装になるだろうから
そうなれば本当に速度に差はなくなるだろう
今は知らん

414 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 04:48:42 ]
普通に、こう考えろ

char* str = NULL;
char* str = "";

同じか?w

415 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 07:26:06 ]
全角のアルファベットを打つ奴はゆとり

416 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 07:47:48 ]
全角ってなんですか?

417 名前:デフォルトの名無しさん [2009/04/05(日) 08:47:43 ]
>>353
> mediatorに相当するクラスのヘッダ
の中では前方宣言するのが吉。
そうしないと冗長すぎる依存関係になってしまう。

アプリケーション全体が10kくらいなら気にしないのも有りかも。

418 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 09:12:22 ]

C言語でWEB操作したいです
証券会社にログインして株価を監視して自動売買が目標です
まずはC言語でWEBページを開く方法を教えてください

419 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 09:58:03 ]
>>413
> 次期規格ではstring()はstring("")に委譲する実装になるだろうから
なんでそんなとこ変わるの?



420 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 10:40:31 ]
>>418
WebProg板へどうぞ。

421 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 13:12:14 ]
>>418
C Web Download をgoogle検索
あきらめろ

422 名前:デフォルトの名無しさん [2009/04/05(日) 13:32:16 ]
>>418
pc12.2ch.net/test/read.cgi/tech/1182323579/

423 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:03:11 ]
デストラクタはpublicで宣言するものだよね?

privateで宣言すると、
まあ普通にコンパイルエラーになるんだけど、
特殊な状況でprivateなデストラクタってある?

なんか俺の知らないイディオムでありそうな気がしてきたんだが。


424 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:16:00 ]
deleteをオーバーロードしてるとかじゃないとコンパイルすら通らなくね?

425 名前:423 mailto:sage [2009/04/05(日) 18:18:06 ]
>>424
そう、通らない。

でも例によってC++は深遠だからさ、
俺が知らないだけで便利なイディオムがあったりするかな〜って興味が出てきた。


426 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:21:59 ]
とりあえずnewで生成してみろよ

427 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:22:20 ]
自動変数や静的変数としては使えないが、newすることは出来る。
deleteはクラスのメンバ関数から出来る。
だから、使えないことはない。具体的にどう役立つのかは分からんが。

428 名前:423 mailto:sage [2009/04/05(日) 18:25:28 ]
あ〜、newで作るのか。
なるほどね。


429 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:26:30 ]
Effective C++にて

const char* const authorName="ScottMeyers";//方式1
const std::string authorName="ScottMeyers";//方式2

この2つが紹介されていたんだけど、結局どっちが良いの?
本によれば方式2の方が良いよ的な書き方されていたんだけど、どうして方式2が良いのか分からない。





430 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:35:41 ]
class MyClass{};
として、
boost::shared_ptr<MyClass> p(new MyClass);
だと大丈夫なのに
boost::shared_ptr<MyClass> p=new MyClass;
だとダメなのは何故でしょうか?

私は宣言時に
(初期化値)とするのと
=初期化値とするのは
等価にコンストラクタを呼び出す物だと思っていたので驚きました。


431 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:38:14 ]
>>430
boost::shared_ptr<MyClass> p=boost::shared_ptr<MyClass>(new MyClass);


432 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:41:49 ]
>>430
コンストラクタに explicit がついていると
> boost::shared_ptr<MyClass> p=new MyClass;
は不可能になる。

例えば
class MyClassA {
 MyClassA(int n);
};
class MyClassB {
 explicit MyClassB(int n);
};
となっていた場合、
MyClassA a(3); // OK
MyClassA a = 3; // OK
MyClassB b(3); // OK
MyClassB b = 3; // NG
となる。

また、
void myFuncA(MyClassA a);
void myFuncB(MyClassB b);
という関数があった場合
myFuncA(3); // OK
myFuncB(3); // NG
となる。myFuncB(MyClassB(3)) は可能。

433 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:42:16 ]
>>431
それはキャストですよね。
つまりキャストしないとダメなんでしょうか?
なぜですか?


…あ、もしかして
boost::shared_ptr<MyClass>のコンストラクタが
explicitになっているということでしょうか?


434 名前:433 mailto:sage [2009/04/05(日) 18:43:20 ]
>>432
すみません。
再読込してませんでした(> <)
失礼致しました。

explicitですね。
もうちょっと勉強して出直してきます。

435 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:44:05 ]
>>430
pc12.2ch.net/test/read.cgi/tech/1232367742/106-109

436 名前:432 mailto:sage [2009/04/05(日) 18:44:11 ]
ごめん、>>432の例だとコンストラクタがprivateになってるね。public: を付け足して読んでほしい。

437 名前:433 mailto:sage [2009/04/05(日) 18:51:15 ]
>>435-436
ありがとうございます。
>newしたらすぐにスマートポインタにセットさせるのが基本。
これがRAIIってやつでしょうか?

438 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 18:52:46 ]
>>423
カスタムデリータを使うときにデストラクタをprivateにして隠して、カスタムデリータ外から勝手に呼べなくする。


439 名前:423 mailto:sage [2009/04/05(日) 19:03:36 ]
>>438
あーなるほどね。
やっぱあるんだ。
サンクス



440 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 21:04:47 ]
仮想関数として指定するキーワードvirtualは、どれだけ付けるのが正しい?
例えば
class Base
{
public:
virtual void m_func(){std::cout << "Base m_func!" << std::endl;};
Base(){std::cout << "Base Constructor!" << std::endl;};
virtual ~Base(){std::cout << "Base Destructor!" << std::endl;};
};

class Derived : public Base
{
public:
void m_func(){std::cout << "Derived m_func!" << std::endl;};
Derived(){std::cout << "Derived Constructor!" << std::endl;};
virtual ~Derived(){std::cout << "Derived Destructor!" << std::endl;};
};

class Derived_Derived : public Derived
{
public:
void m_func(){std::cout << "Derived_Derived m_func!" << std::endl;};
Derived_Derived(){std::cout << "Derived_Derived Constructor!" << std::endl;};
virtual ~Derived_Derived(){std::cout << "Derived_Derived Destructor!" << std::endl;};
};





441 名前:440 mailto:sage [2009/04/05(日) 21:06:11 ]
んで呼び出す時は
void foo()
{
Base* p=new Derived;
Base* q=new Derived_Derived;
Derived* r=new Derived_Derived;
p->m_func();
q->m_func();
r->m_func();
delete p;
delete q;
delete r;
}

このように、俺はBaseのm_func()にしかキーワードvirtualを付けていないんだが、これであってる?

pc12.2ch.net/test/read.cgi/win/1237525619/127


442 名前:440 mailto:sage [2009/04/05(日) 21:09:30 ]
ごめん
別スレで無礼者がいたから
そいつへレスしようとしてたら
間違ってこっちにリンク張っちまった。>>441

マジごめん。


443 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 21:17:07 ]
virtualつけたメンバ関数は、派生クラスではvirtualをつけてようがつけてまいが関係なく
仮想関数になる

DerivedもDerived_Derivedもvirtualはつけてもつけなくても一緒


444 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 21:50:28 ]
>>443
ありがとう。

ちなみにどちらでも同じということだが、その場合
virtualは付ける方が良いとか付けない方が良いとかそういう慣習があったりする?



445 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 21:54:58 ]
>>440のコードを
Baseでvirtualを付けておき、DerivedとDerived_Derivedではvirtual付けない版と、
Baseでvirtualを付けておき、DerivedとDerived_Derivedでもvirtual付ける版と
両方を作ってビルドしてみた。

g++ -O2 〜〜.cpp

としたのだが、挙動は一緒みたいだが、バイナリは違うものになった。
何故?


446 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 22:09:48 ]
-Sで試して確かめるならまだしも…

447 名前:デフォルトの名無しさん mailto:sage [2009/04/05(日) 22:24:44 ]
>>446
-Sだったら同じバイナリになったわ。
なんで??

448 名前:447 mailto:sage [2009/04/05(日) 22:25:58 ]
>同じバイナリ
→アセンブラコード



449 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 00:14:09 ]
>>444
C++ Coding Standards では派生クラスでもつけたほうがよいと書いてある。
(38項.安全なオーバーライドを身につけよう)

単に利用者に意図を明確にするためだけどね。



450 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 00:15:07 ]
速度限界まで最適化するときに
virtualってどう扱うべきなのですかね?

451 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 00:26:22 ]
@Override みたいなのが欲しいよね

452 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 00:41:43 ]
そこで属性でしょきっと。

453 名前:デフォルトの名無しさん [2009/04/06(月) 00:43:53 ]
#define override virtualってうちの会社の元Delphi使いな先輩がやってた。

454 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 00:53:48 ]
>423
遅レスだけど、削除を別のfriend classに委譲する時なんかで使う。

こんなの
class A {
private:
^A() {};
class deleter {
void operator()(A* target) { delete target; };
}
friend deleter;
public:
boost::shared_ptr<A> creator() { return boost::shared_ptr<A>(new A, deleter()); };
}

455 名前:デフォルトの名無しさん mailto:sage [2009/04/06(月) 17:32:53 ]
class Singleton {
 Singleton() {}
 ~Singleton() {}
public:
 static Singleton& Instance() {
  static Singleton instance;
  return instance;
 }
};
みたいなやり方がどっかに載って無かったかな。

456 名前:423 mailto:sage [2009/04/06(月) 21:40:38 ]
>>454-455
あるのね。
うーん、やっぱ奥が深い。

457 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 11:04:11 ]
関係ないけど
singletonをtempleteにするとctorはpublicにせざるをえないのかな?
よくそういう実装をみかけるけど、新しいインスタンスを作れるのがイヤなのですが

458 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 11:20:52 ]
ctorをprivateにしてsingletonをfriendにすればええがな

459 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 11:22:59 ]
そもそもシングルトンをテンプレートにしてまで量産しようという考え自体が間違いだな。



460 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 19:15:55 ]
CamelCaseにするかcamelCaseにするかcamel_case(underscore_style)にするか、
その基準とか主張とかメリットとかデメリットを知りたいんだが、
みんなどうしてる?
確かBoostは俺の知る限りunderscore_styleだったと思うのだが。


461 名前:デフォルトの名無しさん [2009/04/07(火) 19:27:32 ]
>>459
量産するなんて誰か言ったの?

462 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 20:02:19 ]
>>461
テンプレートにしているから量産しようとしているとespしたんじゃない?

463 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 20:05:20 ]
マヌケなespだな

464 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 20:12:33 ]
どうでもいいがespがスタックポインタに見えてしょうがない

465 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 20:50:25 ]
ttp://d.hatena.ne.jp/portown/20090318/1237389062
ここで、
>「デストラクタがヘッダ中に記述されてしまっている」ことにある。
>更に言うと、「deleteがヘッダ中に行われてしまっている」ことが問題であり、
>よりつっこんで言うなら「deleteがCHoge::implの定義と別の場所で行われている」ことが問題なのだ。
>つまり、pimplにスマートポインタを使おうとするなら、デストラクタを必ず明示しなければならないのである。
>それも、implの定義(この場合はhoge.cpp)と同じ場所に、だ。
ってあるんだけど、その意味が分からない。
何でダメなの?
つーかコンパイルは一応通ったんだけど。

466 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 20:52:21 ]
間抜けな設計に合わせてespのレベルも落としたんだろ

467 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 21:05:05 ]
>>465
まず、「不完全型(名前だけ分かってるけど完全な定義がまだ見えていない型)のポインタのdeleteは危険」
であることを知ってほしい。これはコンパイルは通るけどきちんと動かないことがある。
(その型に自分で定義したデストラクタやoperator deleteがある場合、ちゃんと呼ばれない。)

class CHogeのデストラクタを記述しない場合、コンパイラが勝手に ~CHoge() を作る。
その中でスマートポインタである pimpl のデストラクタが呼ばれ、不完全型であるimplのポインタをdeleteしようとする。

468 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 21:13:26 ]
未定義動作だからまともなコンパイラなら警告くらい出すはずだけどな
たまたまデストラクタもdeleteも定義してなかったからスルーしちゃったのかな

469 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 21:53:18 ]
>>467-468
ありがとう。

「pimplがスマートポインタであるために特殊なdeleteが必要である。
だがコンパイル時にはpimplが不完全型であるためにその特殊なdeleteを呼び出すコードが作られない。」
ってことか。

となると、今回のケースでは
CHoge::~CHoge(){}
を自分で明示的に記述したとしても、それをhoge.hに書いている限りは解消されないんだよね。
hoge.cppのCHoge::implクラスの定義の後に自分で明示的に記述するならOKってことですかい?




470 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 22:00:43 ]
>>469
前半は違う。スマートポインタであることは本質的な問題ではない。
pimplが単なるポインタであっても、 hoge.h でCHogeの定義の中に
CHoge::~CHoge() { delete pimpl; }
と書いたら、全く同じ問題が生じる。

後半はあってる。とにかく、明示的にであれ暗黙的にであれdeleteが出てくるところでは、
そのdeleteされるものの完全な定義が分かっていなければまずい場合があるということ。

471 名前:469 mailto:sage [2009/04/07(火) 22:25:09 ]
>>470

なるほど。
根本的な問題は「デストラクタが云々」じゃなくて、
「不完全型のポインタのdelete」にあった訳か。

んで、その辺を全部気にせず丸投げしてもいけるのがshared_ptrなのか。
ありがとう。

・・・しかし
>>>468
>未定義動作だからまともなコンパイラなら警告くらい出すはずだけどな
VC++2008で試して見たのだが
>auto_ptrを用いた例ではVC++2008では警告しか吐かれない。
なぜか警告すら出てこなかったなぁ。


472 名前:471 mailto:sage [2009/04/07(火) 22:29:09 ]
>>468
警告でた。
お騒がせしました。

warning C4150: 'CHoge::impl' 型を削除するため delete 演算子が呼び出されましたが、定義がありません。
: 'CHoge::impl' の宣言を確認してください。


473 名前:471 mailto:sage [2009/04/07(火) 22:33:37 ]
追記:

g++でも警告出た。
note: neither the destructor nor the class-specific operator delete will be called,
even if they are declared when the class is defined.

bcc5.5.1では警告でなかった。


474 名前:デフォルトの名無しさん mailto:sage [2009/04/07(火) 23:21:08 ]
explicitをデフォルトコンストラクタに付ける意味はありますか?
また、explicitを引数を2つ以上取るコンストラクタに付ける意味はありますか?

475 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 00:39:21 ]
1.デフォルト引数が付いてて、結果的に引数1個で呼べるなら意味がある
2.付けても害はないのでとりあえずコンストラクタには全部付けるポリシーにして付け忘れを防ぐ

476 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 01:14:57 ]
explicitを付けさせる仕様でなく、
implicitを付けさせる仕様にすべき

477 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 03:43:39 ]
>>476
いまさら仕様変更されても困るから、そうなってたらいいな、って話にしかならん。

478 名前:474 mailto:sage [2009/04/08(水) 07:09:56 ]
>>475
なるほど。ありがとう。

479 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 19:07:19 ]
copy-and-swapイディオムってすげーのな。
これって自作クラスのoperator=のオーバーロードの定義以外に使い道ある?



480 名前:デフォルトの名無しさん [2009/04/08(水) 19:11:38 ]
何がすごいの?

481 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 19:24:53 ]
>>480
例外安全なところ。


482 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 19:39:37 ]
>>479
コピーしないでスワップするだけなら、
参照型の引数で値を戻す場合にも。
void foo(hoge_t& result)
{
hoge_t x;
//xにあれこれ手を加える
swap(x, result);
}
まあ、何も考えなくていいときには、resultを直接いじることもあるけど。

483 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 20:12:23 ]
全部正常に終わるまで変更を反映させたくない処理全般に使えるよね。

484 名前:479 mailto:sage [2009/04/08(水) 20:21:49 ]
>>482-483
ほほー
ありがとう。

485 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:10:57 ]
オーバーロードしたoperator=を
コピーコンストラクタの定義で使っても大丈夫?


486 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:34:30 ]
よゆー
operatorほにゃららは普通の関数と全く同じように呼び出して可。

487 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:38:45 ]
>>482
ドラゴン・スゴイコビッチ!(とてもすごいの意)

用件としては、自作クラスに swap 関数を装備することと、
その swap が例外を投げないようにすること?


488 名前:485 mailto:sage [2009/04/08(水) 21:49:40 ]
>>486
ありがとう。
コピーコンストラクタ(に限らずコンストラクタ一般)から
メンバ関数を呼び出す時、
construct中なのにメンバ関数を呼び出しても
大丈夫なのだろうかと思ったのだ。。。


489 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:51:32 ]
>>488
virtualなら気をつけないといかんかもしれんが
そうじゃないなら大概大丈夫



490 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:54:37 ]
大丈夫

491 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 21:56:15 ]
>>489
>virtualなら気をつけないといかんかもしれんが
ああ、
基底クラスのconstruct中にvirtualなメンバ関数呼ぶと
その基底クラスでの対応するメンバ関数が呼ばれるってやつね。
ありがとう。

>>490
ありがとう。

492 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 22:03:58 ]
C++0xは本当に後 数ヶ月で策定されるんだろうか。
されたとして、ちゃんと動作するコンパイラが出て来るのはいつだろうか。

・・・うむ、心配だ。

493 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 22:35:04 ]
別に心配することじゃない。
まともなコンパイラが出てから考えればいいこと。
早く出てくれないと困る事情でもあるのか?

494 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 22:50:26 ]
すまぽとかは早く表順になってほしいなぁ。
もうすまぽを書くために何リットルのインクを消費したことやら。
(インク?)

495 名前:492 mailto:sage [2009/04/08(水) 22:52:55 ]
>>493
>早く出てくれないと困る事情
いや、全然ないw
g++が速いかVCが速いか。

496 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 23:00:35 ]
>>493
IntelC++は既にlambda関数がサポートされてるんだけど、IntelC++はコンパイル遅いんでdebugはVCでreleaseはIntelでやってるとlambda関数は使えなくて残念。
boost::lambda使えば済む話ではあるんだけど。


497 名前:492 mailto:sage [2009/04/08(水) 23:12:20 ]
現在のTR1のライブラリ達は、正直なところ十分動作することが
確認されるまでは使わない方がいいんではないかと思うんだが。
それまではboostのが安心かなぁ。

でも標準に入ってる方が使うのは(気分的に)もっと楽になる事は確か。


498 名前:デフォルトの名無しさん mailto:sage [2009/04/08(水) 23:56:20 ]
class A{
public: virtual ~A() = 0;
};

class B :public A {};

class C :public B
{
public: ~C(){};
};

gccでundefined reference to B::~B()って怒られるんだけど、Bでd-tor書かないとダメ?

499 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 00:13:43 ]
ごめん。純粋仮想d-torに定義書くの忘れてた



500 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 00:17:10 ]
俺としては以下のやり方でMyClassクラスによるstd::swap関数テンプレートの特殊化を行い、
using std::swap;
swap(x,y);
で特殊化したstd::swap<MyClass>が呼び出せるかと思ったのだが、
以下のやり方だとなにか定義がかぶっているようなことを言われてエラーになってしまう。
再現するソースは次のようなもの。
//以下はMyClass.h
class MyClass
{
char *p;
public:
void swap(MyClass &hoge);
MyClass();
~MyClass();
};
//以下はMyClass.cpp
#include <algorithm>
#include "MyClass.h"
MyClass::MyClass():p("pointer"){}
MyClass::~MyClass(){}
void MyClass::swap(MyClass &hoge)
{std::swap(this->p, hoge.p);}
namespace std
{
template<>
void swap(MyClass &lhs,MyClass &rhs)
{lhs.swap(rhs);}
}

501 名前:500 mailto:sage [2009/04/09(木) 00:18:28 ]
//以下はmain.cpp
#include <algorithm>
#include "MyClass.h"
int main()
{
MyClass x,y;

using std::swap;
swap(x,y);

return 0;
}
としたら、g++にて
MyClass.cpp:(.text+0x42): multiple definition of `void std::swap<MyClass>(MyClass&, MyClass&)'
main.cpp:(.text$_ZSt4swapI7MyClassEvRT_S2_[void std::swap<MyClass>(MyClass&, MyClass&)]+0x0): first defined here
collect2: ld returned 1 exit status
というエラーが出る。
どうしたらいい??


502 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 00:31:28 ]
理由は覚えてないけどstd名前空間の中でswapの特殊化しちゃだめだった気がする。
ちょっと俺も確認してくるか。

503 名前:502 mailto:sage [2009/04/09(木) 00:33:03 ]
別に駄目じゃないか。ごめんスルーしてくれ。

504 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 00:37:36 ]
>>485
大丈夫だけど、普通operator =ってcopy (construct) and swapで書かない?

ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E3%82%B3%E3%83%94%E3%83%BC%E3%81%97%E3%81%A6_swap(Copy-and-swap)

505 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 00:58:49 ]
>>500
std::swapの特殊化はヘッダに書かないと駄目だろう。
main.cppでは特殊化したstd::swapが見えないから標準のstd::swapが実体化され
MyClass.cppで特殊化した物と衝突してるんだろう。

506 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 06:57:11 ]
>>504
そうか。
コピーコンストラクタの定義に代入演算子を使うと定義が循環しちゃうのか。

507 名前:500 mailto:sage [2009/04/09(木) 06:58:19 ]
>>505
なるほど。
std::swapの特殊化をヘッダに書く場合はinline指定しないと、
そのヘッダをインクルードするたびにまたmultiple definitionってなっちゃうかな?

508 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 08:13:54 ]
>>507
いや、そういう話じゃない。

509 名前:500 mailto:sage [2009/04/09(木) 08:22:57 ]
>>508
(1)main.cppでは特殊化した定義がその前になされていないから通常通り実体化。
(2)MyClass.cppでも特殊化した。

この(1)と(2)でmultiple definitionってことか。
つーことで
MyClass.hにstd::swapの特殊化を書く(1)
main.cppでMyClass.hをインクルード
ってこと?



510 名前:508 mailto:sage [2009/04/09(木) 08:24:06 ]
>>507
あ、ヘッダに書かないといけないのは理解してるのか。ごめん

テンプレートの定義は inline じゃなくてもいいよ。 >500 の場合は inline が
適切だと思うけど。

511 名前:デフォルトの名無しさん mailto:sage [2009/04/09(木) 08:25:44 ]
これが inline じゃないといけないんなら全部の関数テンプレートが
inline にならないといけなくなるな。






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

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

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