トップページ⇒tech
1001コメント296KB

C++相談室 part54

■ このスレッドは過去ログ倉庫に格納されています
0001v(^・^)v2006/10/30(月) 22:34:08
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE(VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

テンプレその他 >>2-15 付近参照

前スレ
C++相談室 part53
http://pc8.2ch.net/test/read.cgi/tech/1159340181/
0446デフォルトの名無しさん2006/11/12(日) 16:29:37
>>445
それって「私は例外投げませんよ」って指定じゃなかった?
0447デフォルトの名無しさん2006/11/12(日) 16:38:41
>>446
そんなことは分かったうえでの質問だろう。たぶん。
0448デフォルトの名無しさん2006/11/12(日) 17:22:25
それはわかってます。
お尋ねしたいのは、それを宣言に付けさえすれば良いのか、定義の方にも
付けねばならないのかということです。
0449デフォルトの名無しさん2006/11/12(日) 17:27:37
>>447
訊く前に実験実験。

struct hoge{
void payo()throw();
};

//void hoge::payo()throw(){}
void hoge::payo(){}
//error: declaration of `void hoge::payo()' throws different exceptions
0450デフォルトの名無しさん2006/11/12(日) 17:46:56
実験しても環境依存やコンパイラのバグの可能性があるので
仕様そのものを知りたいなあと。
因みに、VC8だとそのコードが通ります。
0451デフォルトの名無しさん2006/11/12(日) 18:28:51
そういう時俺は持ってるコンパイラ全部で通してみるけど。
vcとg++とbcc。
時間があるなら標準規格読む。
0452デフォルトの名無しさん2006/11/12(日) 20:35:39
>>450
http://www.jisc.go.jp/
でX3014で検索。
PDFを開いてから例外指定で検索。
0453デフォルトの名無しさん2006/11/12(日) 22:32:40
#include <windows.h>
class Coordinate{
public:
Coordinate(void): x(coo.X) , y(coo.Y) {}
short& x;
short& y;
COORD coo;
};
class Recta{
public:
Recta(void): t(rec.top) , b(rec.bottom), l(rec.left) , r(rec.right) {}
long& t;
long& b;
long& l;
long& r;
RECT rec;
};
Coordinate C( int x , int y ){
Coordinate c;
c.x = x;
c.y = y;
return c;
}
Recta R( Coordinate c1 , Coordinate c2 ){
Recta r;
r.l = c1.x;
r.t = c1.y;
r.r = c2.x;
r.b = c2.y;
return r;
}
0454続き2006/11/12(日) 22:39:33
>>453
void main(){
Recta r = R( C( 1, 1 ) , C( 10 , 10 ) );
}


環境:VisualStudio.net 2002
やろうとしてること・・・
1. Windows組み込みのCOORDやRECTを、COORDやRECTとして使えるように維持しつつ機能を拡張する
 (サンプルなので余計なメンバ関数は省いてますが)
2. COORD.X とかを小文字のxでアクセスできるように参照変数を付ける
3. (mainでは)頂点を二つ指定して正方形を作る

上のソースを実行すると、四角形の頂点の値が滅茶苦茶な値になっています
(初期化されてない値っぽい?)
1ステップずつ実行すると、どうやらC関数で座標を作るところまではできていて
Cの戻り値でR関数を実行する時点でおかしくなっているようなのですが
どうしてそうなるのかが判りませんです・・・
どこか根本的に無理なことをしようとしてるのでしょうか
0455デフォルトの名無しさん2006/11/12(日) 22:53:08
>>454
デフォルトのコピーコンストラクタが参照の初期化に
コピー元への参照を使ってしまうから、コピー元が
破棄されることによって不正な参照が残ってしまう。
0456デフォルトの名無しさん2006/11/12(日) 22:54:17
MFCのCRectのソースでも見れ
0457デフォルトの名無しさん2006/11/13(月) 00:19:05
レスありがとうございます。
コピーコンストラクタって今まであまり意識していなかったのですが
今回、参照の指す先がおかしいということでしたので
Coordinate( const Coordinate& C )
:x(this->coo.X)
,y(this->coo.Y)
{
this->coo = C.coo;
}
というコピーコンストラクタを明記してみたら、意図していた通りに動くようになりました
0458デフォルトの名無しさん2006/11/13(月) 00:21:14
継承すればいいのに。
0459デフォルトの名無しさん2006/11/13(月) 00:51:56
MFCからですか?
0460デフォルトの名無しさん2006/11/13(月) 00:57:04
>>452
それによると例外指定は関数型の一部にならないってあるから
throw()は宣言にだけ付けときゃ良いわけですね。
0461デフォルトの名無しさん2006/11/13(月) 01:14:28
>460
でも、throw指定するのは(nothrow指定含めて)時代遅れだと
なんかで読んだ気がする。
0462デフォルトの名無しさん2006/11/13(月) 01:57:25
むむ。
nothrowだけは例外的に使うべきだと思ってきたが。(除テンプレート内)
0463デフォルトの名無しさん2006/11/13(月) 02:17:43
nothrowとthrow()は無関係かと・・・・。
nothrowは時代遅れ。
0464デフォルトの名無しさん2006/11/13(月) 05:00:50
>>461-462
多分GotW
Exceptinal C++ Styleでもかかれてる
>>463
文脈嫁
0465デフォルトの名無しさん2006/11/13(月) 05:17:08
>>457
>2. COORD.X とかを小文字のxでアクセスできるように参照変数を付ける
これをする理由がわからん。
参照を返すアクセサを用意するだけでいいような希ガス。
0466デフォルトの名無しさん2006/11/14(火) 09:48:58
>>459
COORD, RECTから
0467デフォルトの名無しさん2006/11/14(火) 18:51:04
nothrowとかthrowは、constみたいにコンパイル時に禁止できる訳じゃなくて、
try { hoge() }
catch(Hoge){throw;}
catch( ... ){ unexpected(); }
みたいなコードを自動生成するだけだら、使えネーって話だな。
0468デフォルトの名無しさん2006/11/15(水) 02:36:58
nothrow と throw() をごっちゃにするなよ。

throw() は呼び出し側の最適化に役に立つ。

nothrow については、ググッたところ、
http://www.nothrow.com/
0469デフォルトの名無しさん2006/11/15(水) 08:06:32
Boostによればthrow()は全然最適化に役立ってないらしいがなw
0470デフォルトの名無しさん2006/11/15(水) 18:32:47
結局thorw()を付けるのと付けないのとでは、どっちがいいんだ?
俺は今まで、デストラクタには必ず付けていたが。
0471デフォルトの名無しさん2006/11/15(水) 18:45:12
>>470
つけなくていいんじゃない?
Boostも例外指定はしないで決定してるみたいだし
0472デフォルトの名無しさん2006/11/15(水) 21:10:08
Binary Hacksになんかこの手のが書いてあったな。
0473デフォルトの名無しさん2006/11/16(木) 09:34:27
Herb Sutter は More Exceptional C++ Item 19 で
「throw() を付けるかどうかは好みの問題だけど、
 個人的には /* throw() */ とコメントで書いておくのが好き」
と言ってるな
0474デフォルトの名無しさん2006/11/16(木) 10:57:47
#if defined(ENABLE_EXCSPEC)
#define NOTHROW throw()
#endif
0475デフォルトの名無しさん2006/11/16(木) 20:12:28
テンプレート使うライブラリはthow()とか書きようがないな
0476デフォルトの名無しさん2006/11/16(木) 21:06:03
Herb Sutter は Exceptional C++ Style でも素敵なガイドラインを
書いてるね。なんとも含蓄があるよ。

教訓#1:例外仕様を決して書いてはならない。
教訓#2:空の例外仕様は除くが、私があなたなら、それさえも避けるだろう。
0477デフォルトの名無しさん2006/11/16(木) 21:09:10
>>476
ゴメン・・
含蓄kwsk
0478デフォルトの名無しさん2006/11/17(金) 10:39:58
質問なんですが、

char型、string型でもいいのですが、
文字列から特定の文字だけを全部削除できる関数はあるんでしょうか?
aaaabbbaaaabbbaaaaa
↓
aaaaaaaaaaaaa
という風にです。
0479デフォルトの名無しさん2006/11/17(金) 10:51:20
remove_if()とerase()を組み合わせれば出来る

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

int main()
{
std::string s = "aaaabbbaaaabbbaaaaa";
std::cout << s << std::endl;

s.erase(std::remove_if(s.begin(), s.end(), std::bind2nd(std::equal_to<char>(), 'b')), s.end());
std::cout << s << std::endl;
}
0480デフォルトの名無しさん2006/11/17(金) 10:52:46
std::bind_2nd〜の部分を別に関数オブジェクトに持てば、もっと
複雑な削除条件も簡単に書ける。

boost::bindで何としても一行で済まそうという傾向もありますが
0481デフォルトの名無しさん2006/11/17(金) 10:57:17
>>479
remove() でいいだろ。
04824782006/11/17(金) 10:59:03
ありがとうございました☆
解決しました
0483デフォルトの名無しさん2006/11/17(金) 11:14:02
>>481
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void main()
{
string s = "aaaabbbaaaabbbaaaaa";
remove(s.begin(), s.end(), 'b');
cout << s << endl;
}
結果:aaaaaaaaaaaabaaa
remove()だけだと削除しきれない。
0484デフォルトの名無しさん2006/11/17(金) 11:23:45
>>483
うむ。 erase() も要るな。
0485デフォルトの名無しさん2006/11/17(金) 11:25:40
>>483 void main() 氏ね
0486デフォルトの名無しさん2006/11/17(金) 13:10:35
何故。
0487デフォルトの名無しさん2006/11/17(金) 13:19:24
戻り値型がvoidのmain関数なんて規格には無い
0488デフォルトの名無しさん2006/11/17(金) 13:22:00
はいはい規格規格
0489デフォルトの名無しさん2006/11/17(金) 13:24:53
まあmainは一箇所だけ直せばいいからなw
0490デフォルトの名無しさん2006/11/17(金) 13:57:17
悪い。483です。void main()は完全なる間違いです。すみません。はい。
0491デフォルトの名無しさん2006/11/17(金) 14:59:22
と思ったら私のはちゃんとint main()になってたか・・・・void mainは別人ですた。

remove()でもいいですね。remove_if()をわざわざ使ったのは、例えば
'b'が2回現れた後は'c'も削除せよ、というような場合に便利ですね。

今回はremove()だけでいいみたいです。
0492デフォルトの名無しさん2006/11/17(金) 15:20:42
何行かの改行されたファイルを文字数を指定して、
文字列を取り出していきたいんですけど、どうしたらいいでしょうか?
0493デフォルトの名無しさん2006/11/17(金) 16:03:51
>>492
無視する文字は改行文字だけ?ホワイトスペース文字全般?
0494デフォルトの名無しさん2006/11/17(金) 16:14:11
改行だけの方法と、
ホワイトスペースも無視する方法のふたつをお願いします。
0495デフォルトの名無しさん2006/11/17(金) 17:14:22
>>494
#include <iostream>
#include <fstream>
#include <string>

int getsome(std::ifstream& fs, std::string& s, int n);
int getwows(std::ifstream& fs, std::string& s, int n);

int main()
{
std::ifstream fs("ws.txt");
std::string s;

int n = getsome(fs, s, 10); // 改行文字のみを無視
std::cout << n << "文字: \'" << s << '\'' << std::endl;

fs.seekg(0, std::ios::beg);
s = "";
n = getwows(fs, s, 10); // ホワイトスペース文字を無視
std::cout << n << "文字: \'" << s << '\'' << std::endl;
}

int getsome(std::ifstream& fs, std::string& s, int n)
{
char c;
int i = 0;

while (i < n && fs.get(c))
if (c != '\n') {
s += c;
i++;
0496デフォルトの名無しさん2006/11/17(金) 17:15:32
}

return i;
}

int getwows(std::ifstream& fs, std::string& s, int n)
{
char c;
int i = 0;

while (i < n && fs >> std::ws >> c) {
s += c;
i++;
}

return i;
}

getsome()が改行文字のみを無視、getwows()はホワイトスペース文字を
全て無視します。
0497デフォルトの名無しさん2006/11/17(金) 17:16:17
なおテストに使ったファイルの内容は
---- ws.txt ----
1234





56

78

90
[EOF]
0498デフォルトの名無しさん2006/11/17(金) 17:26:10
ありゃ
>>497には所々文字列の前に' 'とかタブ文字を入れて見て下さい。
04994942006/11/17(金) 17:29:05
なるほど。get()を使うんですか!
問題を解決する事ができました!
ありがとうございます!
0500デフォルトの名無しさん2006/11/17(金) 18:57:47
void main(void){return;}
0501デフォルトの名無しさん2006/11/17(金) 22:19:28
main(argc,argv)char**argv;{return 0;}
0502デフォルトの名無しさん2006/11/18(土) 00:03:24
char* main(argc,argv)char**argv;{return argv[0];}
0503デフォルトの名無しさん2006/11/18(土) 01:24:38
public static void main(string[] hoge)
0504デフォルトの名無しさん2006/11/18(土) 01:56:27
int main[] = { -61 };
0505デフォルトの名無しさん2006/11/18(土) 02:25:43
class m
{
public:
virtual int main( int argc, char **argv );
};
0506デフォルトの名無しさん2006/11/18(土) 03:43:05
クラスaをmain.cppから分離したいとき、
ヘッダファイルa.hひとつで
class a{
void hoge(){
return 0;
}
};
という感じで定義も記述して、a.cppファイルを作らないのってよくないんでしょうか?
修正があったときhファイルとcppファイルをいじらなきゃならないのが嫌なので…。

今ぶちあたってる問題として、お互いのstaticなメンバ関数を
お互いが使うような二つのクラスがあるときは宣言と定義を分けないとどうしようもないようなのですが。
0507デフォルトの名無しさん2006/11/18(土) 03:51:52
>>506
ヘッダファイルには宣言だけ
cppに定義部を書く
0508デフォルトの名無しさん2006/11/18(土) 04:45:10
俺は面倒だから大体ヘッダファイルに書いてしまうな。
やはりコンパイル時間は遅くなりそうだが。
ちなみにテンプレートを使ってるとヘッダファイルしか使えないよな。
0509デフォルトの名無しさん2006/11/18(土) 05:32:09
毎日コンパイルしてテストしろ
という時代だからな
boostがちょろっと更新されるだけで
pimplパターンなんて水の泡だ
やるだけ無駄
0510デフォルトの名無しさん2006/11/18(土) 09:33:34
>>508
コンパイル時間より、コードの肥大化の方を心配した方がいい
0511デフォルトの名無しさん2006/11/18(土) 11:53:22
>>508
C++的にはexportつかえばヘッダに書かなくても大丈夫だよ!
0512デフォルトの名無しさん2006/11/18(土) 11:56:59
>>511
ちゃんと使えるコンパイラってどれがあるの?
0513デフォルトの名無しさん2006/11/18(土) 12:56:24
糞VCはサポートしていないね。
0514デフォルトの名無しさん2006/11/18(土) 14:04:47
exportって一部のコンパイラしかサポートしてないって聞くけど、
実際のところサポートしてるコンパイラって何てやつ?
0515デフォルトの名無しさん2006/11/18(土) 14:15:35
http://ja.wikipedia.org/wiki/C++
0516デフォルトの名無しさん2006/11/18(土) 14:32:16
Comeauはフロントエンドだけだがお値段が$50、ただし製品ページのjavascriptがウザ過ぎる。
Borlandのってどう?

0517デフォルトの名無しさん2006/11/18(土) 14:48:10
exception C++ Style読んだら分かるけど、
exportがあっても何も解決しないっぽいよ。
0518デフォルトの名無しさん2006/11/18(土) 15:42:49
まじすか
0519デフォルトの名無しさん2006/11/18(土) 15:45:08
その辺りはD言語では改善されてるのかな。
次期C++ではどうなの?
0520デフォルトの名無しさん2006/11/18(土) 22:38:24
>>514
寡聞にして知らん。
糞GCCもずっと長いことサポートしてなかったと思うが、4.0系移行はサポートしたのか?
0521デフォルトの名無しさん2006/11/18(土) 23:20:57
そういや時期BCCはexportサポートするとかしないとか言ってた気がするが、結局どうなったんだっけ
0522デフォルトの名無しさん2006/11/19(日) 01:13:56
何にせよ宣言と定義で二回書かなきゃならないめんどくささはなんとかならんもんだろーか?
c#だと楽だよね
0523デフォルトの名無しさん2006/11/19(日) 01:18:34
>>522
UMLソフトでクラスしこしこ作ればそのへんは
骨だけは作ってくれるぞ
0524デフォルトの名無しさん2006/11/19(日) 03:00:44
そこで全部ヘッダにぶちまけですよ
0525デフォルトの名無しさん2006/11/19(日) 03:17:13
インターフェースクラスだけをヘッダに書いて、それを継承する実装クラスはcppにベタ書きとか結構やる。
0526デフォルトの名無しさん2006/11/19(日) 03:29:21
それだとその実装クラスを他のソースで使えない?
0527デフォルトの名無しさん2006/11/19(日) 04:26:56
実装へのポインタをインターフェースへのポインタとして晒していれば使わなくていい。
0528デフォルトの名無しさん2006/11/19(日) 09:51:20
template<class T> class MYCLASS {
...
};

こういうクラスがあって、実体化するときに以下の用に書きますがが、

MYCLASS<A> myclassA;
MYCLASS<B> myclassB;

こうかける方法を教えてほしいです。

MYCLASS myclassA;
MYCLASS myclassB;

このときTは、それぞれA, Bに死体です。
05295282006/11/19(日) 09:57:35
すいません。間違いました。もう一回最初から書きます。

template <typename T> class MYCLASS {
T* a;
MYCLASS(T* t) : a(t) {}
};

こういうクラスがあって、実体化するとき以下のように書きますが、
A a;
MYCLASS<A> my1(&a);
B b;
MYCLASS<B> my2(&b);

以下のように書きたいです。
A a;
MYCLASS my1(&a);
B b;
MYCLASS my2(&b);

このときTは、それぞれA, Bに死体です。
0530デフォルトの名無しさん2006/11/19(日) 09:59:54
そうですか。
0531デフォルトの名無しさん2006/11/19(日) 10:12:53
class MYCLASS {
boost::any a;
template<typename T>
MYCLASS(T* t) : a(t) {}
};
05325282006/11/19(日) 10:19:01
>531
ありがとう、boostインストールしてきます。
05335282006/11/19(日) 12:37:45
boostインストールして、531を試したんですが、
デストラクタでTが使えないってエラーがでるんですが、
これは無理なんでしょうか?

class MYCLASS
{
boost::any a;

template<class T>
MYCLASS(T* t) : a(t) {}

template<class T>
~MYCLASS() {
cout << sizeof(T);
}
}
0534デフォルトの名無しさん2006/11/19(日) 13:52:02
>>533
無理。 T を決める方法が無い。
何がしたいんだ?
05355282006/11/19(日) 14:29:55
MYCLASSのデストラクタでTのデストラクタを呼びたいです。
0536デフォルトの名無しさん2006/11/19(日) 14:30:35
>>535
何もしなくても呼ばれるだろ?
05375282006/11/19(日) 14:44:10
呼ばれないと思います。コンストラクタで渡してるのは
T*なので
0538デフォルトの名無しさん2006/11/19(日) 14:45:38
これでどうかね?
template<class T>
MYCLASS(T* t) : a(*t) {}
05395282006/11/19(日) 15:02:46
それで呼ばれるデストラクタはコピーされたTだと思いますが、
元々渡されたtのデストラクタを呼んで解放したいです。

529の例がスタック上のインスタンスになってるんですが、
実際はこういう風には使わないで、newしたものを渡します。
0540デフォルトの名無しさん2006/11/19(日) 15:07:05
class MYCLASS
{
boost::shared_ptr< void > p;

public:
template<class T>
MYCLASS(T* t) : p(t) {}
};

型が消えてるから MYCLASS 内で有用な仕事ができないとは思うけれど
0541デフォルトの名無しさん2006/11/19(日) 15:08:41
>>539
デストラクタじゃなくて呼ぶのdeleteじゃね?

とりあえずスマートポインタだと無駄に重装備っぽいので関数ポインタ使ってみた
class MYCLASS{
    MYCLASS(const MYCLASS&);
    MYCLASS&operator=(const MYCLASS&);
    void*ptr;
    void(*delfn)(void*);
public:
    template<class T>MYCLASS(T* t) : ptr(t),delfn(deleter<T>){}
    ~MYCLASS(){delfn(ptr);} 
};
05425412006/11/19(日) 15:10:46
おっと忘れてたこれも宣言する
template<typename T>
static void deleter(void*p){delete (T*)p;}
05435282006/11/19(日) 15:19:31
>>540-542
ありがとうございます。難しそうなのでじっくり調べてみます。

>デストラクタじゃなくて呼ぶのdeleteじゃね?
そうですdeleteです。わかりずらくてすいません。

0544デフォルトの名無しさん2006/11/19(日) 15:33:43
bbbの関数がaaaの動的なメンバにアクセスするにはどうすれば良いんですか。

class aaa{
  int v;
  class bbb{
    void func(int x){
      v+=x;  //コンパイルエラー
    }
  }b;
};
0545デフォルトの名無しさん2006/11/19(日) 15:46:30
>>544
aaa のインスタンスを渡せ。
■ このスレッドは過去ログ倉庫に格納されています