1 :
v(^・^)v :
2007/09/26(水) 03:41:13
テンプレ終了。 ISO のリンクが "301 Moved permanently" だったんで更新しといた。
ぉぉ。すごい。乙です。
注:私の有意義な発言に対し、自分の理解不足を棚に上げ煽り、1行レス で返す方が多いようですが、そのような方はスレの皆様を混乱させるだけでなく スレの雰囲気を崩しかねないのでお黙り下さい。 また質問者は回答者に知識を披露する場を与える貴重な存在なので、 質問者を見下した回答、あまりにも儀礼を欠いた回答も厳重に禁止いたします。 忙しい中、少ない時間の合間を縫って質問しに来てるわけですので、 その辺ご承知下さい。なお、当方が質問に対して有意義な答えであると 判断した方には評価いたしますので各自よく調べ、よく考え正確な回答をするように。
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
やっぱり貼られるんだなこれ
地鎮祭が済んだな乙
そこまでがテンプレだからな。
stlとかboost使いまくったら通常は1M程度で住むものが 10M超えたりするんでしょうか?
「通常」の定義がわからん
それでは、よくある「クラスと継承が使えるbetter Cとして書いたC++のコード」を「通常」だと想定して答えて下さい 今作ってるものがboostをヴァリヴァリに使っているので それと比較すればどれぐらいバイナリサイズは肥大するのかがちょっと気になります
バイナリサイズよりコンパイル時間の肥大が気になる。
通常、増える場合と減る場合、そして変わらない場合があります。
25 :
デフォルトの名無しさん :2007/09/26(水) 20:27:10
int data[10] ={10,20,30,40,50,60,70,80,-999} このようなint配列があります 配列の内容を実行結果のように表示するプログラムを作りなさい -999になれば処理を終了します ポインタを固定して表示させる処理とポインタを変化させて表示させる処理の2つ作成しなさい この内容がわからないので教えて下さいお願い致します
なんだマルチか
スレ建て乙
>>1 おつかれ
>>10 GJ!
有用なサイトを手っ取り早く見つける方法...
それはテンプレを見ることだ。
29 :
デフォルトの名無しさん :2007/09/27(木) 00:22:33
int *p = data; int i = 0; while(*p++ != 999) std::cout << *p << std::endl; while(*(p + i) != 999) std::cout << *(p + i) << std::endl;
999ではなく-999 2つ目のループ前にpを初期化しないといけない
31 :
デフォルトの名無しさん :2007/09/27(木) 09:48:49
C++で書かれた、正規表現処理クラスみたいなものってありませんか?
boost/random.hpp
ミスった。 boost/regex.hpp
!?
double a[3000][3000]; て定義すると蹴られるんだけど、なんでかわかる人いますか?
環境は?
37 :
デフォルトの名無しさん :2007/09/27(木) 11:14:19
VC6のSDKでウィンドウを持ったクラスの継承がしたいです。 Hoge1クラス:メインウィンドウになるクラス Hoge2クラス:継承元となるウィンドウを持ったクラス Hoge3クラス:Hoge2クラスを継承したクラスでHoge1ウィンドウのボタンを押したときに表示されるウィンドウを持ったクラス Hoge2クラスはWinProcをstaticでクラス内に入れています。クラスの登録やウィンドウを生成する関数はprivateとして存在します。 Hoge3クラスも同じような構成です。 で、Hoge3クラスで不用なメッセージ処理はHoge2のウィンドウクラスに回してやりたいのですが、 その方法がいまいちわかりません。手順・・がいまいちです。 Hoge3クラスの登録をする前に、Hoge2クラスのウィンドウを登録する必要があると思い、 WNDCLASSEXを使ってウィンドウの登録をする?と思いきや、横取りするHoge2にあるプロシージャとかも指定しないといけないわけですよね? でもこの段階だと、Hoge2クラスの存在すら誰も知らないわけで・・・この辺りがよくわかりません。 ボタンのスーパークラス化と同じようなイメージでいるのですが、ボタンの場合は ウィンドウズが予めその存在を認識しているからGetClassInfoExを使って情報を取得する ことができますが、自作ウィンドウクラスの場合はそれができなくて・・・
>>35 配列が大きすぎてスタック領域が足りてない。と思われる。
巨大な配列を宣言するときは new するか static にするべき
俺の環境ではgcc 3.4やvc2005でも文句言われないんだけど… そのかわり実行時にスタックオーバーフロー そういうオプションでもあるの?
>>39 必要ないのに無駄にnewなんか使うなよ。
どうしてもSTLは使いこなせないってことなら話は別だが。
>>43 スタックじゃサイズ足らないって理由だけでnewすんのもSTL使うのも大差ないだろ
46 :
37 :2007/09/28(金) 01:30:59
>>44 そこは何度も見てるのですが・・・。そこに書いてあるクラスは、
それを継承させると簡単にサブクラス化できたり元に戻せたりする
クラスってことですよね?
>>37 >で、Hoge3クラスで不用なメッセージ処理はHoge2のウィンドウクラスに回してやりたいのですが、
>その方法がいまいちわかりません。手順・・がいまいちです。
Hoge3 クラスは Hoge2 クラスを継承してるんだから、ただ単に継承元クラスのメンバ関数を呼ぶだけでいいのでは
ムダに難しいこと考えてない?
Windows に登録するウィンドウクラスと C++ のクラスが一致してる必要はないよ
C++ のクラスを継承してるからってウィンドウクラスをスーパークラス化したりサブクラス化したりする必要はない
インナークラスっておまいら普通に使ってる?
pimplの形でなら使ってるよ
>>45 大差なくはない。vector使え。
例外安全な上に組込配列よりずっと便利だ。
2 4 16 256 65536 4294967296 * sizeof(double) = 8589934592b = 8192MB
そこまでいったら流石にメモリマップドファイル使う
53 :
37 :2007/09/28(金) 10:45:46
>>47 「ウィンドウ作成データとして、CWinBase クラスの派生クラス CxxxWnd オブジェクトを指定することを忘れないで下さい。」
が、何を指しているのかわからないです。どこにCxxxWnd オブジェクトを指定するのでしょう?
54 :
37 :2007/09/28(金) 10:50:39
WNDCLASSEXを登録するとき、サンプルではBaseWnd::WindowMapProcを指定 しろとあるけど、指定するものを自分自身のWinProcを指定してやり Attachを呼べばいいのかな?
>>53 それは、CreateWindowExの最後の引数。
CxxxWnd wnd;
CreateWindowEx(..., &wnd);
こういう感じ。CreateWindow(Ex)の引数は
WM_CREATEまたはWM_NCCRAETEでCRATESTRUCTとして全て参照できる。
いつもこうしなければならないだから、
CreateWindowExもクラスのメンバにしてこの処理はしばしば隠蔽される。
そろそろスレ違いが近付いているぞ。
56 :
37 :2007/09/28(金) 11:29:40
死ね
58 :
37 :2007/09/28(金) 11:33:38
static Hoge3* pWnd = NULL; pWnd = (Hoge3*)(((CREATESTRUCT*)lp)->lpCreateParams); こんな感じか?な?
CxxxWnd *wnd = (CxxxWnd*)lpcs->lpCreateParams;
60 :
37 :2007/09/28(金) 11:37:44
>>55 できますた。ありがとうございます!
あとは54なんですが・・・これがまた・・・orz
死ね
>>58 そこでstaticはやめとけ。
>>60 Hoge2::WinProcに相当するのが、44の指したページで言うCWndBase::WindowMapProc。
64 :
37 :2007/09/28(金) 12:38:27
class Hoge:public CWndBase public: BOOL InitInstance( HINSTANCE hInstance ); private: //オーバーライドしたWndProc static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); }; 使うとき、 Hoge hoge; hoge.InitInstance(hInstance); InitInstanceの中ではウィンドウの登録、作成をする WNDCLASSEX wcex; : wcex.lpfnWndProc = (WNDPROC)BaseWnd::WindowMapProc;//WndProc; : RegisterClassEx(&wcex); で、CreateWindowする。最後の引数はthisを渡す。 こうすると、メッセージは、まずWindowMapProcで処理されて、 BaseWndのWndProcへ飛んできます。が、オーバーライドした自分のWndProcには飛んでこない です。CreateWindow後のAttachとか呼んでみたのですが、変わらずです。 なんか、おしい気がするのですが、ぜんぜんですかね?
なぜ static が付いてる? それでオーバーライドになってると思ってるのか?
>>64 44のページを良く見ろ。
WindowMapProcはstaticで、WndProcはvirtualだ。
静的メンバ関数で多態的なオーバーライドは不可能だ。
お前らの優しさに嫉妬
68 :
37 :2007/09/28(金) 13:29:59
あ、static付いてる。コールバックはstatic付けることで解決、なんての ばかり気にしてたので、普通につけちゃいました。 で、取ったらコンパイラ エラー C2555が出て、「そんなの聞いてませんが何か?」 とか思いつつ、調べること数分、どうにかメッセージを受信するとこまで できたようです。 今は、慣れてないのにいろんなことやってしまった(気でいる)ので、 これから1つ1つ整理して、ちゃんとしたものを作っていきます。 みなさまありがとうございました。
やれやれ ┐(´ー`)┌
でさ、なんでこの話題がC++スレで?
相手する低脳がいるから
72 :
デフォルトの名無しさん :2007/09/29(土) 08:31:08
class A{ int a[10]; public: }
73 :
デフォルトの名無しさん :2007/09/29(土) 08:34:44
途中で書いてしまいました失礼しました class A{ int a[10]; public: int *get_a(){return a;} } int main(){ int *p; p = get_a(); for(int i = 0; i < 10; i++){ p[i] = ... ... = p[i]; } return 0; } このようなコードってカプセル化を壊してますか?
75 :
73 :2007/09/29(土) 08:45:15
やはり配列のポインタを返すというのはまずいのでしょうか?
早漏は経験をつめば治ります。めげずに頑張りましょう。
こんな感じにしちゃえば? int get_a( int i ){return a[i];}
代入は?
>>81 int& get_a(int i) { return a[i]; }
int get_a(int i) const { return a[i]; }
effective C++読めよー。
っていうか言語以前の問題だろ。 っっていうか全部ネタだろ。
なんで誰も内部ハンドルを返すのは云々って言ってあげないのか
hoge.hの中で class hoge { public: virtual double CalcF1(Double_t r) const throw(std::exception); } hoge.cxxの中で double hoge::CalcdF1dr(Double_t r) const throw(std::exception) { } としてるんだけど、g++でcompileしようとすると src/hoge.cxx: In member function 'virtual double hoge::CalcdF1dr(Double_t) const': src/hoge.cxx:87: error: expected primary-expression before ';' token と怒られます。どこが書き方間違ってるんでしょうか。
あ、ごめん。 class hoge { public: virtual double CalcdF1dr(Double_t r) const throw(std::exception); } でした。
あ、ごめん。勘違い。 スルーして下さい。
VC2003で作られた 静的なlibは、 VC2005でリンクすることは不可能なんですか?
91 :
デフォルトの名無しさん :2007/09/30(日) 20:19:13
クラスの内側で定義したクラステンプレートを特殊化する、 class X { template<typename T> class Y {}; template<> class Y<int> {}; }; のようなコードは、VC++(2003/2005)ではコンパイルできますが、g++3/4では error: explicit specialization in non-namespace scope ‘class X’ というエラー になってしまいます。 Y<int>をXの中ではなく、名前空間スコープで template<> class X::Y<int> {}; と書けばg++でもVC++でも問題なく特殊化できることは知っているのですが、 なんとかg++で、特殊化されたクラスの定義をXの中に書く方法はないでしょうか? Y<T>とY<int>の定義が離れた場所にあると、コードが読みにくいと思うのです。 boost(特にmpl)の使用は歓迎です。 よろしくおねがいします。
>>89 クラス末尾にセミコロンがありませんでした。ごめんなさい。
とちゃんと書こうYO!
>>91 定義位置を近づけたいなら、両方クラス外に書けばいいんじゃね?
94 :
91 :2007/09/30(日) 20:45:33
>>93 ああ、たしかにそうですね。他に案がなければそうしたいとおもいます。
ただ、Y<T>とY<int>を両方クラス内に書けると、宣言と定義の位置も離れない(定義だけになる)ので、
より読みやすいと思っています。
というわけで、引き続きお願いします。
>>91 規格ではネストされたクラス内での明示的特殊化は禁止されているけど
部分特殊化はOKなので、
class X {
template <typename T, class U = void> class Y {};
template <typename T>
class Y< T
, typename boost::enable_if<
typename boost::is_same< T, int>
> > {};
};
のようにenable_ifとis_sameを使って書くといいっぽい(初心者スレから一部拝借w)
VCでコンパイル可能なのはmsの独自拡張でgccの方が正しいとのこと
96 :
91 :2007/09/30(日) 20:57:38
なお、メンバ関数テンプレートで同様のエラーをくらう件については (下記の2行めがエラーになる)、 class X { template<typename T> void foo(T x) {} template<> void foo<int>(int x) {} // error }; 下記方法でごまかしています。 #include <boost/type.hpp> class X { void foo_(int x, boost::type<int>) { /* specialized */ } template<typename T> void foo_(T x, ...) {} public: template<typename T> void foo(T x) { foo_(x, boost::type<T>()) ;} };
97 :
91 :2007/09/30(日) 20:59:12
>>95 部分特殊化はOKだったんですか。気づきませんでした。
早速試してみます。どうもありがとう〜!!
>>91 私はC++初心者ですが、
>>93 さんと同意見です。
>>95 さんの言うようにgccの方が正しい(つまり規格どおりということですよね)ならば、
なおさらそう思います。
それに、Xクラスの定義を見たいときには、むしろYは外にあった方が見やすいのではないでしょうか?
ちなみに関数テンプレでもこの手は使えるようだ この手法も名前があったと思うけど思い出せない 使うなら適当にローカルなメタ関数を専用の名前空間に自作して階層を浅くする工夫が必要だね 使ってればわかるけど、凄く見にくくなるから
あ、::type付けわすれた…
読み易くするのが目的で読みにくくなる手法を選ぶか。
>>99 名前があるならソレをコメントに書いておけば良いかも。
>>98 >>101 読みやすいかどうかは読み手にもよるし、あまり
>>91 や
>>94 はよい聞きかたではなかったですね。
C++のコードを自動生成するツール(自作)の都合でX内に定義を書けると嬉しい、というのが実際の事情です。
103 :
91 :2007/09/30(日) 22:32:03
102は91です。
>>99 concept-controlled polymorphism ですか?
104 :
デフォルトの名無しさん :2007/09/30(日) 23:06:47
>>100 > あ、::type付けわすれた…
検索エンジン経由で来るひとのために、一応訂正版貼っときますね。
#include <cstdio>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
struct X {
template<typename T, typename U = void> struct Y {
Y() { std::printf("genecic\n"); }
};
template<typename T> struct Y <T, typename boost::enable_if<boost::is_same<T, int> >::type> {
Y() { std::printf("specialized for int\n"); }
};
};
class Z {};
int main() {
X::Y<Z> a;
X::Y<int> b;
X::Y<float> c;
}
実行結果は、
genecic
specialized for int
genecic
です。
boostが使えない場合は、VC++2003/2005/g++対応だけ考えるならこんな感じでしょうか。 #include <cstdio> namespace b00st { template <bool B, class T = void> struct enable_if_c { typedef T type; }; template <class T> struct enable_if_c<false, T> { /* NO TYPEDEF! */ }; template <class Cond, class T = void> struct enable_if : public enable_if_c<Cond::value, T> {}; template<bool b> struct bool_ { static const bool value = b; }; template<typename T, typename U> struct is_same : bool_<false> {}; template<typename T> struct is_same<T, T> : bool_<true> {}; } using namespace b00st; struct X { template<typename T, typename U = void> struct Y { Y() { std::printf("genecic\n"); } }; template<typename T> struct Y<T, typename enable_if<is_same<T, int> >::type> { Y() { std::printf("specialized for int\n"); } }; }; そろそろウザいとおもうので、これで打ち止めにします。ありがとうございました。
このtemplate感、実に小気味良い 久しぶりにC++スレを実感した
キモ
小気味良いのは確かだけど、言葉遣いが丁寧すぎてちょっと痒い、というのが俺の感想。 うん、俺の感想なんかどーだっていいってのは承知。
109 :
デフォルトの名無しさん :2007/10/01(月) 02:02:08
>>99 enable_ifの関数テンプレへの適用で質問。ある条件で2つの関数を呼びわけたいときは、こんな感じにすればいいみたいだけど、
template<typename T>
static void foo(T t, typename boost::disable_if<boost::is_same<T,int> >::type* = 0) {
}
template<typename T>
static void foo(T t, typename boost::enable_if<boost::is_same<T,int> >::type* = 0) {
// intへの特殊化版
}
3つ以上を呼びわけるにはどうすれば? たとえば、
template<int V>
static void boo(typename boost::enable_if_c<V == 0>::type* = 0) { }
template<int V>
static void boo(typename boost::enable_if_c<V == 1>::type* = 0) { }
template<int V>
static void boo(typename boost::disable_if_c<V == 0 || V == 1>::type* = 0) {
// default
}
とかだと、default caseな関数の引数が大変なことになってしまうような。
boostスレのほうがいいのかな。。
複雑な場合はmplの出番になるんじゃないかな mpl::if_< ..., mpl::if_< ..., > >::type::call();
111 :
109 :2007/10/01(月) 03:23:49
>>110 すみません、それはどこに書くコードなんでしょうか?
call() とは一体。。
112 :
109 :2007/10/01(月) 03:28:24
>>110 が理解できず、独自に考察を進め中。
template<int V>
static void boo(typename boost::enable_if_c<V == 0>::type* = 0) {}
は、
template<int V>
static void boo(typename boost::enable_if<
boost::is_same<
boost::mpl::int_<V>,
boost::mpl::int_<0>
>
>::type* = 0) {}
であり、さらに
template<int V>
static void boo(typename boost::enable_if<
typename boost::mpl::lambda<
boost::is_same<
boost::mpl::_1,
boost::mpl::int_<0>
>
>::type::apply<boost::mpl::int_<V> >::type
>::type* = 0) {}
だから、この数値0-Nでlambdaしたのをmpl::listで抱えて、特殊化版はlistのat<i>したのでenable_ifして、default版はこれらをandでfoldしたのにdisable_ifすればいいと思うんだぜ?
・・・絶対方向が間違ってる。
いや、単に、mpl::if_で関数を実装したクラスを選んで呼び出す boost/smart_cast.hppが参考になるかも
114 :
デフォルトの名無しさん :2007/10/01(月) 03:44:43
>>113 私は、単に boo(0); boo(1); boo(2); とだけ書くと、呼び先の関数がコンパイル時に決まるようにしたいと
思っているんですが、
>>110 は、このbooを *呼ぶ側* をif_で工夫しろということ?
まぁ、boo()でif_を使って、適切なboo_()を呼ぶようにしてもいいのかもしれませんが、
委譲してしまうとタグディスパッチと大差ないようにも思うし。。
なんか勘違いしてたらすんません。smart_castは早速見てみます。
どうしてもenable_ifを使いたいなら 複雑な条件を書かずに済ますことは不可能だと思う
116 :
109 :2007/10/01(月) 05:41:56
>>115 enable_ifが使いたいわけでは無くて、
1.メンバ関数テンプレートの特殊化(相当のこと - オーバーロードでもいい)を行いたい
2.特殊化の定義は、クラス内に書きたい (
>>91 と同じく, 見た目の問題で)
3.メンバ関数を呼ぶ側はあまり難しいことを考えたくない
4.タグディスパッチのような別関数への処理の委譲は、できれば避けたい (これも見た目の問題で)
という条件で、Pという場合と!Pという場合の処理の振り分けだったら、
enable_ifを使ったオーバーロードでOKとわかった(
>>109 )が、P, Q, (!P && !Q)
の3関数に振り分けたい場合にこの4条件を満たすようなのないですかね?
というのが質問です。ちゃんと書かずにすみません。コンパイラはgccです。
>この4条件を満たすようなのないですかね
自分で書いた
>>109 が満たしてると思うんだが
118 :
デフォルトの名無しさん :2007/10/01(月) 05:58:35
>>117 おっしゃる通りなんですが、
>>109 は、V==0やV==1という条件が
繰り返し登場してしまい、メンテナンス性がいまいちかなと思いまして。
実際はenumとか扱いたいので。
109の繰り返しになりますけど、条件1-4をみたし、かつdefault case
template<int V>
static void boo(typename boost::disable_if_c<V == 0 || V == 1>::type* = 0) { /* default */ }
を綺麗にかけないですかね。
template<int V> static void boo(...) { /* default */ }
とかが通れば最高なのに。
struct a_condition : mpl::bool_<...> {}; としてenable_ifに渡すとか
120 :
デフォルトの名無しさん :2007/10/01(月) 09:08:09
kwsk
引数忘れた こんな感じ enable_if< my_conditionA<V> > まあディスパッチすべきだな enable_ifはこの場合必要ないから
デザパタのプロトタイプパターンを使ってみたいのですが ばらばらに clone() 関数をとりつけるよりも ひとつ Clonable クラスを作って、そのクラスから 継承したほうがよいでしょうか?
そういう継承ってどうなんだろうね。
noncopyableとかあるし、いいんじゃね?
traitsを作れば継承はいらないと思うよ
#include <boost/numeric/ublas/vector.hpp> using namespace boost::numeric::ublas::inner_prod; VC++2005EEの環境でビルドすると、 error C2867: 'boost::numeric::ublas::inner_prod' : は名前空間ではありません。 というエラーが出ます。 エラーの原因は何ですか?
名前空間ではないものをusing namespaceしたこと
128 :
126 :2007/10/02(火) 23:00:22
>>127 http://sealsoft.jp/namespace.html このサイトの
> usingを使って、ある識別子をグローバルな名前空間に持ち上げることができる。こうするとその後は大域解決演算子を使う必要がない。
> using namespace seal::foo;
> // 関数fooを呼び出す
> int a = foo();
ここ見てできると思ったんですけど、このサイト間違ってますか?
usingディレクティブ (using namespace)の対象にできるのは、名前空間だけ。 代わりといってはアレだが、その他の識別子一般には、using宣言が使える。 using boost::numeric::ublas::inner_prod;
130 :
126 :2007/10/02(火) 23:49:25
>> 129
なるほど、そうなんですか。
http://msdn2.microsoft.com/ja-jp/library/6f133eff (vs.80).aspx
ここを勘違いして見てました。(classの中のusingとは別物なんですね)
クラスの中でnamespace内の関数をusingしたい場合、
class A {
using boost::numeric::ublas::inner_prod;
};
エラーになってしまうのですが、クラス中でnamespace内の関数をusingするのは無理ということですか?
そういうこと。クラス定義内のusingは基底クラスの名前を指定することに特化している。 なお、型名だけはtypedefで代用できる。
132 :
126 :2007/10/03(水) 00:14:05
ありがとうございました。
マクロ使って、行数と引数を連結させたいのですが、 #define macro( name )\ const char *x = "name##__LINE__"; とかやってもできません。 こんなことは可能ですか?
__LINE__は定数だからダブルクォーテーションで囲っちゃだめっしょ で、定数を文字列にするのは単純なマクロじゃ厳しいと思うけど・・・ おとなしく関数にしたほうがよさそう
一応マクロでこんな感じでいかが? #define macro( buf, name ) sprintf( buf, "%s%d", "name", __LINE__);
#define NUM2TEXT_(n) #n #define NUM2TEXT(n) NUM2TEXT_(n) #define macro(name) \ const char *x = name ## NUM2TEXT(__LINE__)
演算子オーバーロードって副作用完了点のことも考慮しないといけないんですか? std::cout << "test" << std::endl; で (a) "test" << std::endl; が先に評価されて、次に std::cout << (a) が評価される、という事態にはならないんですか?
優先順位の同じ演算子の並びは左から評価じゃなかったのか
左結合と右結合があってね・・・
140 :
133 :2007/10/03(水) 05:13:05
ありがとうございます。
>>136 さんのは
どういう原理なんでしょうか?
7**7**7 の下一桁の数字は?
>>137 多重定義されている場合、通常の関数と同様、
呼出の直前に副作用完了点が現れるので心配は要らない。
<<は左結合だから、まずstd::cout << "test"から取り掛かる。
これは多重定義されているので、std::cout.operator <<("test")という関数呼出に相当。
関数呼出の直前には副作用完了点が来るので、ここまでにstd::coutと"test"が評価される。
と言っても、共に副作用を持たないので何も起きないが。
仮に副作用を持つ式だった場合、通常の関数呼出同様に
<<の左側と右側のどっちのオペランドが先に評価されるかは決まっていない。
std::cout.operator <<("test")の戻り値をrとすると、
次にr << std::endlの評価に掛かる。以下同じ。
>>140 > 16.3.2 The # operator
> 16.3.3 The ## operator
>>133 #define XY(X,Y) X##Y
#define MAKENAMEXY(FX,LINE) XY(FX,LINE)
#define MAKENAME(FX) MAKENAMEXY(FX,__LINE__)
というマクロで連結させている例がある。
評価順その他の関係で、間に一段置かないとならないらしい。
VS2008EEで
>>136 が正常に動作しないんだけど・・・
コンパイラの仕様かな?
プリプロセッサの仕様じゃね?とかつまんない事言うね。義務として。
すみません。継承について質問です。 クラスBaseを基底とするクラスDerivAやクラスDerivBがあるとして、 そこからインスタンスを作成するとすると、 Base* pA = new DerivA; Base* pB = new DerivB; となると思います。 そこから、pAもしくはpBから新たなインスタンスpCを作りたいと思っているのですが、 どうしたらいいでしょうか? 単にpA(DerivA)だけであれば、DerivA *pC=*pAだけでいけるのですが、 pAとpB(最終的にはBaseを基底とするクラス全部)にも対応できるものを作りたいので、 どうか力をお貸しください。
class Base { public: virtual Base *NewInstance() = 0; }; class DerivA : public Base { public: virtual Base *NewInstance(){ return new DerivA; } }; class DerivB : public Base { public: virtual Base *NewInstance(){ return new DerivB; } }; Base *pA = new DerivA; Base *pB = new DerivB; Base *pC = pA->NewInstance(); Base *pD = pB->NewInstance();
Base* pA = new DerivA(); Base* pB = new DerivB();
150 :
147 :2007/10/04(木) 01:02:02
>>148 、149
目からウロコが落ちました。
インスタンスを作成する関数を別途で作ればいいわけですね。
ありがとうございます。
>>148 DerivA::NewInstanceはDerivA*を返し、
DerivB::NewInstanceはDerivB*を返し、
という具合に、そこは共変にしてほしいな。
152 :
デフォルトの名無しさん :2007/10/04(木) 01:06:08
凶変を許したことでできるようになったことってなんだっけ? なんかの本にかいてあったが忘れた
153 :
デフォルトの名無しさん :2007/10/04(木) 01:15:57
>>136 boostにはなんて名前で入ってたっけ
>>152 pAはDerivA*と分かっているとき、
DerivA* pA2 = static_cast<DerivA*>(pA->NewInstance());
のようなキャストを型安全性を損なうことなく排除できる。
155 :
デフォルトの名無しさん :2007/10/04(木) 02:07:15
dynamic_castすれば共変なしでも安全じゃね?
>153 BOOST_PP_STRINGIZE
これじゃだめなん? Base *pC = new DerivC;
Base *pC = new DerivC(pA); Base *pC = new DerivC(pB);
俺的c++開発環境構築メモ 目的:最終的にlinuxで動かせるようにしないといけないけどVisual Studio捨てれない winxpにvmwareいれてゲストOSとしてubuntu7を入れる ubuntuの/home/srcをsambaで共有できるようにしてホストOSのwinxpからみれるようにする /home/src = \\ubuntu\src の下にVisual Studioのプロジェクト作成 makefileはeclipse/CDTで自動生成 あとはemacsでメインのコードの編集するけど、flymakeとか使いつつ インテリセンスも使えてeclipse/cdtのリファクタリング機能も使える環境のできあがり
俺がいる
もう遅いだろうがcoLinuxを薦めてみる
164 :
デフォルトの名無しさん :2007/10/05(金) 12:27:41
coMomongaを勧めてみる
coLinuxの方が便利なの? 速度が速い以外のメリットがないなら、もう乗り換えれない
coLinuxってkernelのバージョンあがるたびに中身を全消ししないといけないって聞いたのだけど 違うの?
ヘッダファイルなどで記述したグローバルなstatic変数は, includeしたソースが複数ある(各ソースではincludeガードが起きずに展開される) 場合も単一の存在となるんでしょうか? それとも別々の独立した変数となるんでしょうか?
それをインクルードしたソースファイルごとに別々に作られることになる
ありがとうございます. あれ,でもクラス変数などは単一なんですよね? うーむ,基本の理解が全然出来ていない.
クラスの static 変数はどこかで1個だけ実体を定義する必要がある。 class A{ static int x; }; int A::x; // <-- これ 2個以上のソースファイルで定義したら、定義が重複してるってリンクエラーになる。 static でない普通のグローバル変数と同じあつかい。
#includeは単にファイルをくっつけてるものと考えれば理解しやすいかも
>#includeは単にファイルをくっつけてるものと考えれば理解しやすいかも くっつけるというのはちょっと違う。単にインクルードするだけ。
>>169 ファイルスコープの static はクラスメンバやローカル変数の static とは全然
意味が違う。これは理解するとかじゃなくて覚えておく必要がある。
C の仕様設計ミスとも言われている
ここで聞いて良いか解りませんが HTMLのtableタグを抜き出して2次元配列化するのに簡単な方法ありますか?
簡単な方法かどうかわからんが、文字を読み込みながら解析していきゃいいんじゃね? 表の大きさがあらかじめ分かってるなら楽、わかってなくても確保すりゃできる。
rowspanとかの扱いが面倒くさいなと(´Д`;)
>>177 大丈夫、Lynx辺りのソースを見れば書いてあるはずだ。
# 簡単とは思えないが。
100行くらいあるテーブルで 最後の行にだけ colspan 書いてあったり?
それは困らんだろ
181 :
デフォルトの名無しさん :2007/10/07(日) 22:00:29
Linuxでg++4.1.2を使ってるんですが、簡単なODR違反って、リンカが検出してくれたりしないんでしょうか?
>>181 簡単なやつならシンボルの重複が発生してリンカのエラーになるよ。
g++だと、クラステンプレートの中の関数はweak symbolになってしまうようで、 重複しても怒られないんだよね.....
最近C++やったのだけど ただクラスを作って使うだけでもCよりは使いやすいよね、これ。
186 :
デフォルトの名無しさん :2007/10/08(月) 14:10:02
クラスを作らないで使わないでもCよりは使いやすい
C+関数オーバーロード+テンプレートで作ると意外と強力
BOOST_PPだけで作ると読めない。
>>185 関数型や今時のLLの真似をしようとすると
すぐに泣くことになるけどな
BjarneStroustrup様に感謝しなさい。
以下のコードがsegmentation faultで落ちます。 #include <boost/regex.hpp> int main() { boost::regex re("^(..)*\\xA4"); } (ひらがなを含むEUCコードの文字列の正規表現) コンパイル/実行環境: i686, linux-2.6, gcc-4.1.2, boost-1.34.0, -O3オプション ia64、-O2オプションでも試しましたが、その場合は問題は発生しませんでした。 私はこれ以上調べる知恵を持たないのですが、GCCのバグなのでしょうか?
ICE? 実行時のSEGV? boostのバグかもしれんよね。
とりあえず core から stack trace を見るんだ
194 :
191 :2007/10/08(月) 18:07:48
GDBで覗いてみたら解決しました。 原因は恥ずかしくて言えません。あまりにも下らないミスでした。 スレを汚して申し訳ありません。
いや、相談しに来たなら原因言ってから取り下げろって。
>>194 恥ずかしがることないじゃないか、減るもんじゃなし。
このまま消えたらそれこそスレ汚し。質問に対して考えてくれた人に対して礼を欠く事になるぞ。
おまえら恥ずかしい原因聞きたいだけだろと
198 :
191 :2007/10/09(火) 00:44:29
自分でインストールしたboostとシステムの管理者がインストールしたboostがあって、 後者の存在はこの問題を解決するまでは知りませんでした。 自分のboostを使うときは-lboost_regex-gcc41としなければならないのですが、 -lboost_regexと間違えていました。 管理者の用意したboostと何事もなくリンクしてしまうのでミスに気付かなかった。 GDBの出力に /usr/lib... という文字列を見つけて始めてミスに気付きました。 あれ? でもおかしいな。違うboostをリンクしたらそれはそれでうまく動くんじゃないんでしょうか?
>>198 「違うboost」の何が違うのか調べないと、原因はわからんな。
別に恥かしいことじゃなかったな。 しかし管理者か。 自分の視野外からバグが入り込むとはまるよな。
boostって何者ですか? どっかの誰かによって拡張されたものですか? 標準ライブラリではないとは思うのだけど、それなら、 boostを使って記述すると、環境依存(バージョン依存)物とか言って怒る人います?
202 :
デフォルトの名無しさん :2007/10/09(火) 01:32:43
怒る人がいるかどうかは、お前の環境依存。会社とか。
>>201
>>198 原因は措いておくとして。
自分がスーパユーザじゃなくて自前でインストールした
ライブラリとかを利用するときは、-I でインクルードパスを明示するのと、
リンク時には -L でライブラリパスを明示するのを習慣付けておいたほうが
良いで。
>>198 >>203 実行時のLD_LIBRARY_PATHも忘れずに。
それが面倒なら、boostの場合は、.soでなく.aのほうをリンクしてしまうのも手だ。
-lを使わず、/home/mona/lib/libboost_regex.a とフルパスを書いてしまう。
boost/regexで日本語扱うにはユニコードに変換しないと駄目なんじゃないの?
namespaceで区切ってグローバル関数を使うのと クラスを作ってメンバ関数として使うのと どちらがパフォーマンスがいいのだろうか?
>>206 どちらも同じコンパイル単位内に関数の実体があると仮定していいなら、後者の方がインライン展開されやすいので
パフォーマンスが高い可能性がある。但し、コンパイラによっては全く同じになる可能性も高い。
>>207 ありがとう!
つまり、ソースの読みやすさを優先すればいいって事ですね?
パフォーマンスは置いといて、こういうのって、 (自分流でも)オブジェクト指向に沿って考えたら自然と決まるもんじゃないの? それともC++のクラスってオブジェクト指向以外の用途も一般的?
test
testy
testest
>>209 構造化にしろオブジェクト指向にしろ、ソースのメンテナンス性を上げるための物だと理解してます
グローバルな関数にした方が使い勝手が良ければグローバル関数で処理するし
クラス化した方が使い勝手が良ければクラスを使います
使い勝手というのが、ある場面ではパフォーマンスであったり、ある場面ではメンテナンス性であったりするわけですが
また、メンテナンス性は、ソースの可読性に大きく左右されるので、パフォーマンスが同等であるならば、ソースの可読性を優先するのは自然だと思います
namespace hage{namespace hoge{ void func() {} }} struct hage2 {struct hoge2 { static void func() {} };}; int main() { hage::hoge::func(); hage2::hoge2::func(); } どちらでも階層を実現できるけど class struct を使う方法ならアクセス指定もできる よって選らぶなら後者?…なわけないな
×選らぶ ○選ぶ らぶ
>>213 なるほど、C++初心者だけどOOPに慣れてるから、まずOOがあるものとして考えてたよ
ただ、
> ソースの可読性を優先するのは自然
って考えた時に、オブジェクトとして捉えられる物はクラス化した方がいい場合があるのは当然として、
そうでないものをクラスにまとめることもあるのかな?ってのを疑問に思ったの
名前空間とクラスのどっちを選ぶかは目的の持っている意味で分けられて、
それで結果的に可読性が向上すると思ってるから
char hoge[5000*5000]; とか書いといて走らせると、hogeがちゃんと確保されないんだけど、 これって当然なんでしょうか。 100*100とかだと大丈夫。 アクセスするとseg faultしちゃう。 newしてやるとちゃんと確保される。 gcc + Linux or OS X
コンパイラでスタックの量を24MB以上許容してくれるように設定しなさい。
>>218 ああ、そういうのがあるんですか。
newしてポインタがNULLかを調べるほうが普通?
とりあえずスタックとヒープの違いについて調べるのが普通
C++の規格にスタックとかヒープなんてあったっけ?
ないね
>>219 標準 C++ で、ただの new がヌルを返すことはありません。
まぁ規格になくても知っといた方がいいやな。
225 :
デフォルトの名無しさん :2007/10/10(水) 21:01:39
Javaでスタックにオブジェクトおくにはどうすればいいの? もちろん、スレちがいだかんね。
226 :
デフォルトの名無しさん :2007/10/10(水) 21:13:13
SomeClass *p = new SomeClass(); SomeClassのコンストラクタの処理が凄い思いとする。 この重い処理中、p は NULL? 非NULL? どちら?? 処理系の実装依存なのかな。
ごみ値。
VC6やそれ以前を前提に話をしたいならそれ専用のスレに行ったほうがいい。 あれの動作は特殊だからねぇ〜
229 :
デフォルトの名無しさん :2007/10/10(水) 22:01:04
スレチ杉てわらってしまった
230 :
デフォルトの名無しさん :2007/10/11(木) 12:10:34
SomeClass *p = new(nowthrow) SomeClass(); ってやれば、一応失敗すればヌルポを返す
そしてコンストラクタが例外を投げるとw
>nowthrow
233 :
デフォルトの名無しさん :2007/10/11(木) 18:40:50
いま投げる??
ナウいな
C++TESTって使ったことある人いる? あれで構造体が「truncated」ってなって設定できないんだけど、何で? 教えてくださいエラい人。
>>230 例外を使ったことない人が、例外を使いたくなくてひっかかる勘違いだな。
237 :
デフォルトの名無しさん :2007/10/12(金) 05:59:42
ICUのUnicodeString クラスのインスタンスの比較で operator== 使ったんだけどおれは今まで bool(最悪でもint)を想定してコードを書いてきたんだ。 そしたら、 返された型がUBool = signed char だったんだ・・・ UBoolってboolっぽいから盲点だったよ。 pimplでラップしろとのお告げなのだろうか・・・ std::cout << o1 == o2 << std::endl;//で判明
比較演算子はboolじゃなくてintが基準だよ。
239 :
237 :2007/10/12(金) 09:12:42
>>237 冗談かと思ったら散々な結果・・・
比較演算子の型は不明?w
std::cout << typeid(1.0==1.0).name() << std::endl;//VC6(int),VC7.1(int),VC8(bool),GCC3.4.4(bool)
std::cout << typeid(1==1).name() << std::endl; //VC6(long),VC7.1(bool),VC8(bool),GCC3.4.4(bool)
結論:boolは関数オーバーロードしない。または、明示的に呼び出す。
>>239 これまじで?
もうVC6とかVC7.1は使わないから、いまさらどうでもいいんだけど。
>>238-239 規格では組み込みの比較演算は全部 bool になる。
VC の比較演算か typeid がバグってるんだろ。
#ifndef HOGE_H #include "hoge.h" #endif と、hoge.h内で #ifnedef HOGE_H #define HOGE_H 1 class hoge{ }; #endif ってするのはどっちにどういう長所短所があるんでしょうか。
前者はISO-C以前のアナクロな手法。C++でそんなことやるのは馬鹿。
>>243 あざっす。
数十種類の色んな環境でmakeできるソフト読んでたんで、
前者はそういうとこで念のために使う感じですね。
>>242 コンパイル速度上げるための小細工。hoge.h の中で #ifndef してると、当然
hoge.h を読み込んでプリプロセッサが解析するコストがかかるが、前者だと
ファイル開く必要がない。
ちなみに #pragma once 使える環境なら、そっちの方が良い。
#ifdef _MSC_VER # pragma once #else # ifndef XXX_IS_INCLUDED # define XXX_IS_INCLUDED /* */ # endif #endif こうですか?わかりません><
>>245 gcc は #pragma once 使わなくてもインクルードガードのパターンを認識して
同等の処理をしてくれるらしい。
つまり #pragma once しか使えない環境なら付けといたほうがいいかも、って感じ。
>>246 未知の#pragmaは無視してくれるんじゃなかったっけ?
まぁでも#pragma once に別の意味があるコンパイラもあるかもしれん
>>248 コンパイラによっては同じ名前でも違う意味だったりする可能性もあるから
#pragma はたちが悪い。
インクルガドのパターンは標準的だしそれでいいんじゃねーの
252 :
デフォルトの名無しさん :2007/10/14(日) 04:02:26
void fh() { try { throw; } catch(int) { printf("1\n"); } catch(bool) { printf("2\n"); } } int main() { try { throw true; } catch (...) { fh(); } return 1; } これってhack? これ許されるなら、TypeListの 要素全てをcatchするなんてのも出来そう。
253 :
デフォルトの名無しさん :2007/10/14(日) 04:20:38
>>252 なにがうれしいのかよくわからん。kwsk.
例外処理として使うならいいが、ダブルディスパッチ的に使うのは好かん
> 254 C++つかってもう直ぐ10年だが初めて知ったorz > 253 template <typename TL,typename T> struct Catch { void do_catch() { try { throw ; } catch (T) { /*何か処理*/ } catch (...) { Catch<mpl::pop_front<TK>::tyep,mpl::front<TL>::type>::do_catch(); } } }; こんな感じにすればTypeList全要素のcatchもできそう。 パフォーマンスわるそうだけど。 ほかにも工夫すればあれやこれが(うひひ
例外のパフォーマンスが良ければ迷わず使うんだがな…。 あと、例外指定との相性もわかんねえし
例外処理のやってはいけない利用法の代表だな
そこまでするならRTTI使ったほうが良いと思うな。
あ、そういう意味じゃなかったか。すまん
261 :
デフォルトの名無しさん :2007/10/14(日) 16:03:25
>>247 「パターンを認識」って具体的には何よ?あいまいすぎて水伝みたいだとオモタ
>>262 ファイル内のコード全体が #ifdef で囲まれてて、その中の先頭で対応するマクロの定義が
ある、ってパターンを認識するんじゃないか?
gcc の話だから、確実なところが知りたいんなら実験してソース読んだほうがいいな。
boost.waveでもインクルードガードパターンの認識してた気がする
265 :
デフォルトの名無しさん :2007/10/14(日) 16:44:09
VC++で#pragma onceに以降したのはインテリセンスやアウトラインで#defineされた名前も拾うようになったってのもあるだろうな
Typelistの全キャッチして何かできるの?
普通にmplのイテレータ使って回すんじゃだめなの?
269 :
デフォルトの名無しさん :2007/10/15(月) 01:09:41
Exceptional C++ Styleの「汎用コールバック」のところに、こんなコードが乗ってるんですが、 callbackのoperator()をconstにしていい理由がよくわかりません。 A::foo()がconstではないのに、なぜoperator()はconstでいいんでしょうか? struct A { void foo() /* const */ {} }; template <class T, void (T::*F)()> class callback { public: callback(T& t) : object(t) {} void operator()() const { (object.*F)(); } private: T& object; }; int main() { A a; callback<A, &A::foo> cb(a); cb(); } メンバ変数objectが、値でなく参照だから? おしえてくださいませ。
thisがconstでも、ポインタの指す先はconstにならないんだよな・・・
272 :
269 :2007/10/15(月) 01:15:58
ソウダッタノカ... 結構長いことC++もconstも使ってきたつもりだったけど、しらんかった。ありがとー
じゃあconst性を保てるコールバックオブジェクトってできないの?
callback(const T& t) : object(t) {} とか const T& object; にすればいいだけでは?
275 :
デフォルトの名無しさん :2007/10/15(月) 01:47:14
template <class T, void (T::*F)() const> class ccallback {
public:
ccallback(T& t) : object(t) {}
(あとは一緒)
でも作って、そっち使えばいいんでない?
>>273
const性の定義が...
277 :
デフォルトの名無しさん :2007/10/15(月) 20:26:42
クラスのオブジェクトのポインタからnewで配列を作ったとき、 それぞれにコンストラクタを作用させる方法ってありませんか? class A{・・・}; int main(){ A* a; a=new A[10]←ここでコンストラクタは使えない? } アホですいません
>>277 new[]では、デフォルトコンストラクタしか呼べない。
ほかのコンストラクタを使いたければ、今はおとなしく
std::vector<>でpush_backするなどしかない。
279 :
277 :2007/10/15(月) 21:21:48
どうもありがとう
a=new A(obj)[10]; なんて出来ないのか。 デフォルトコンストラクタしか呼べないのには 何かしらの理由あるの?
規格の汎整数昇格のところ読んでるんだけど、 変換「できる」って書いてるんだよね。 つまり、変換するかどうかは処理系定義ってことなのか・・・。 うちの環境じゃその下の浮動小数点昇格が行われないみたいだし、 処理系定義臭いな・・・。
>>280 うまい文法が思いつかなかったんじゃねーの。
A * p = static_cast<A *>( ::operator new (sizeof(A) * 10) ) ;
std::uninitialized_fill_n(p, 10, A(/*初期値*/) ) ;
A *iter = p ;
A * const end = &p[10] ;
for ( ; iter != end ; ++iter )
{ iter->~A() ; }
::operator delete(p) ;
うん、自分でやるのは、果てしなく面倒だな。
>>280 現行の規格では無理だね。
文法としては↓で問題ないような気がするんだけど。どうなんだろ。
a = new A[10] { ... };
>>281 実際にどこで汎整数昇格が実行されるべきかどうかが別途規定されている。
処理系定義じゃないよ。
浮動小数点昇格は 5.2.2p7 の可変個引数の所でしか出てこないから ここでしか昇格は行われないという認識でいいのかな? #include <iostream> using namespace std; void Hoge(float ) { cout << "float " << endl; } void Hoge(double) { cout << "double" << endl; } int main() { Hoge(0.0f + 1.0f); } で float が出力されるのは別にいいというわけね?
new int[10](); は出来るのにな
>>283 a = new A[size] { ... };
として、... にはどう書くよ?
>>288 ↓と同じでいいだろ。
A a[] = { ... };
>>289 size が動的に決まる場合どうするのよ
>>290 new する。
っていうか、それ初期化の話と関係ない。
>>291 size の値によって { ... } の ... に書くべき要素の数が変わるじゃん。
それ動的って言わない
>>292 それ考えたら構文とか以前にコンパイルが必要な言語という時点で無理だね。
new しない配列と同じ制約のうえで初期化子が使えるって感じが考えられるかも、
もっと考えていったら、やっぱりやめようってことになるのかね?
禿が「組み込み配列なんか使うな」で済ませたことも考えられる。
あとは std::initializer_list にがんばってもらおう。
>>293 new してるのに動的じゃない場合を考えるって何て矛盾。
>>293 { ... } を使う時点で動的じゃないっつーことだ。
>>285 各演算子のとこに書いてあるよ。
たとえば + は両オペランドに通常の算術型変換を施すけど、>>はしない。とかがわかる。
人の作ったやつんなんだけど、豪快にメモリリークしてる。。 初心者の漏れはどやって調べればいいんだああ
>>298 リークしていることが確実なのならば、全てのmalloc()/newからのロジックを追えばいい。
>>298 _CrtSetBreakAlloc();
302 :
300 :2007/10/16(火) 13:43:46
>301 うぜー じゃあ boundschecker valgrind で満足したか?
>>300 =302
環境依存スレじゃないんだから、環境依存の手法をいくら提示してもダメでしょ。
まして、>298は環境を明示していないんだから。
>>298 つーことで、愚痴じゃないなら該当スレでどうぞ。その節は環境を明示することをお忘れなく。
つーか、該当環境スレで聞いたほうが早いかな。
でも「井の中の蛙」は意味違うよな。
>>305 Windows環境の知識しかないなら、あってんじゃないの?
尤も、>300は>302で井の中のみならず多少の外界の知識もあることを披露している訳だが。
因みに、「井の中の蛙」と言った場合、通常は「井の中の蛙、大海を知らず」と言う意味で使う。
更に「されで空の青さを知る」などと付け加えてしまうのは無粋と言うものだと思う。
まぁ実際、>302で「うぜー」とか「満足したか」なんて言っているようではやはり、>300は井の中の蛙だと思うんだ。
一字訂正 s/されで/されど/
豪快にメモリリークしているなら、環境依存ではなく調べる方法。 適当にダンプしてみる。 もし、普通に使うメモリが数十MBなのに、数百MBも使っているとすれば、 かなりの確率で、リークしているメモリをダンプすることが出来る。 あとは特徴的なビット列なり、なんなりで、何のメモリかを特定すればよい。
どっちも必死なのは分かったからどっちも消えろよ
自分では自分のことを「おりこうさん」だと思っているのだろうから、 たぶんこの辺りからがしつこいと思うよ。
311 :
300 :2007/10/16(火) 16:05:08
いや俺は302以降発言してねーよ。勝手に必死認定すんな。
312 :
デフォルトの名無しさん :2007/10/16(火) 16:59:19
コマンドライン等から x*x+5*x+10+sin(x) のような関数を読み込んで、 この関数を実行時に作成するような方法ってありますか。 double func(double x){ return x*x+5*x+10+sin(x); } ↑こんなイメージの関数を実行時に作りたいと考えてます。 文字列を式として認識するようなこと自体難しいと思いますが、 それを仮にクリアしたとして、 とにかく引数を与えたときにその式の値を得る方法を知りたいです。 いい方法をご存知の方がいたら、ご教授いただきたく。
>>314 tccというコンパイラのライブラリを使うと実行時に文字列からコンパイルできる。
C++ならboost.spirit web検索かければサンプルコードも沢山あるから 比較的楽に実装できると思うよ
ファイルに書き出してコンパイラを呼び出してDLL的なものにしてロードして実行。
319 :
314 :2007/10/16(火) 21:12:53
>>315-318 こんな短時間に色々ありがとう。
とりあえず、試してみます。
この前boost入れたんで、まずspiritっての使ってみようかと。
しかし上記のアルゴリズムを自分で書こうとしたらどうなるのか気になりますね。
結局インタプリタを作るハメになるだけ
》319 トークン解析してひたすら関数オブジェクトを合成するような感じでしょう。きっと… インタプリタなら関数(オブジェクト)になんかしなくていいわけですし…
>319 自作するならPEGがお勧め。 結局spiritだけどな
324 :
デフォルトの名無しさん :2007/10/17(水) 09:20:12
>>314 #include </dev/tty>
私ゃawkを使ったけどね。
326 :
デフォルトの名無しさん :2007/10/17(水) 17:27:41
質問失礼いたします。 引数付きのオブジェクト型の配列についてなのですが Object **obj = new Object*[N]; for( int n = 0; n < N; n++ ) obj[n] = new Object( 0 ); こんなんがweb上に乗ってたんですが、 オブジェクト型の配列の添え字数分コンストラクタを呼びたいとき もっと簡単の書き方はありますでしょうか?
327 :
326 :2007/10/17(水) 17:28:59
もっと簡単'な'でしたm(__)m
328 :
デフォルトの名無しさん :2007/10/17(水) 21:11:44
レベルが低い質問かもしれません。 C++で割り込み処理(ex.ctrl+Dが入力されるまで永遠ループ)はできますか? c=getchar() != EOF とかですと毎回止まってしまうので駄目です。 「C++ 割り込み処理」などでぐぐりましたが、ちょっとわかりませんでした。 CUIでやりたいのでVC++のみで可能ですと終わります。。
標準ライブラリの範囲では無理。
今ググってみたら signalって標準だったのか・・・
C++で文字列からそのクラスを作るのはできないですか? class base{}; class super1:public base{}; class super2:public base{}; という風になっていて base *s1 = getClass("super1"); // base *s1 = new super1(); と等価 base *s2 = getClass("super2"); // base *s2 = new super2(); と等価 ってのをやりたいです 事前にこんなので登録して、ここから呼び出したいのですが… なにかうまい方法は無いでしょうか map<string, ???> classmap; classmap["super1"] = super1; classmap["super2"] = super2;
332 :
デフォルトの名無しさん :2007/10/17(水) 22:17:16
>329,330 ありがとうございます。同一の方ですか? signalを調べてみようと思います!
C++にはリフレクションがないので・・
>>331 関数ポインタでも使ってみる?
class derived1;
base* create_derived1(){return new derived1();}
class derived2;
base* create_derived1(){return new derived2();}
map<string,base* (*)()> classmap;
classmap["derived1"] = create_derived1;
classmap["derived2"] = create_derived2;
335 :
sage :2007/10/17(水) 22:31:24
>333 だ、だめか・・・ すいません。ありがとうございます!
keyとなる文字列とクラス名がある程度一致してるならboost.preprocessorとanyでなんとかできるかもしれない
C++ド初心者ですが vector<int>のイテレータを vector<int>::iterator p = .....; と記述してるのですが、なんで、vector<int>::としなければならないのですか? 自分としては、なんとなく(iteratorがclassなら) iterator< vector<int> > p = .... と記述するのが普通じゃないのかと思うのですが
iterator はクラスとは限らないからねぇ 単なるポインタの typedef ということもありうる
boost::range_iterator<std::vector<int> >::type なんてお呼びでない。
vector<int>のクラス内でかかれているiteratorというクラスを使いたいから vector<int>::iteratorがint*な実装がある。BCCがそうだし… でもlist<int>::iteratorはまた別物で list<int>の内部構造にあわせたクラスにしてある。 大事なのはiteratorという同じ型を使うのではなくて iteratorという型を通して同じように要素を操作できることだから…。 型名::型名 が分らないのならば vector<int>::iterator の vector<int> はコンテナクラスの型であると同時に 名前空間名でもあります。 クラスの名前空間とかインナークラスで探せば説明サイトが見つかると思う。
>>334 それも考えたんですけど、100個ぐらいあるから関数を作るのが面倒なので…
boost使って自動化できたり出来ないですかね…
>>341 boost::function, boost::lambda::constructor を組み合わせれば、道が開けるかも。
344 :
326 :2007/10/18(木) 11:05:17
>>343 すみません、3行目は
obj[n] = new Object( n ); でした。
理解していないわけではないのですが、
ただ単にオブジェクト型の配列として定義したときに
カウンタとして用いているnをコンストラクタの
引数として用いたいのです。できればnewを用いずに。
配列宣言で引数付きコンストラクタを呼び出すことは
できないのでしょうか?
レベルが低くて申し訳ありませんm(__)m
>>344 Object がコピーコンストラクタでコピーできるクラスなら。
std::vector<Object> obj;
for( int n = 0; n < N; n++ )
obj.push_back( Object( n ) );
これなら delete も要らなくて簡単。
C++0xを待つんだな。
347 :
326 :2007/10/18(木) 11:53:56
>>345 早いご回答ありがとうございます!
やってみます!
コピーでOKなら std::vector<Object> obj( N, Object(n) );
350 :
7=9 :2007/10/18(木) 14:25:42
>>349 Objectにコピーコンストラクタがあるなら大丈夫だと思うのだが…
(N回コピーコンストラクタが呼ばれる)
コンストラクタをメモ化したい
>>341 template<class T> base* create_derived(){return new T;}
classmap["derived1"] = create_derived<derived1>;
classmap["derived2"] = create_derived<derived2>;
boostなんて必要ないですね…orz...
>352 #define REG(name) classmap[ #name ] = create_derived<name> までやれば最強?
現在ゲームで使うベクトル構造体を作っています。 struct Vec3 { union { struct { float x; float y; float z; }; float v[3]; }; // オペレータ群 ・・・・ }; これを、 Vec3 v0, v1; v0.xy = 1.0f; v1.xyz = 1.0f v0.xz = v1.zx; みたいな使い方をしたいのですがどのようにすればいいのでしょうか? よろしくお願いします。
とりあえず代入する必要なところだけ。もっと面白いことも出来るだろうけど、ここに書くには余白が足りない。 struct proxy { float & r1 ; float & r2 ; public : proxy(float &r1, float & r2) : r1(r1), r2(r2) { } proxy(proxy const & p) : r1(p.r1), r2(p.r2) {} proxy const & operator = (float f) const { r1 = f ; r2 = f ; return *this ; } } ; struct Vec3 { float v[3] ; public : proxy xy(void) { return proxy(v[0], v[1]) ; } proxy xz(void) { return proxy(v[0], v[2]) ; } proxy yz(void) { return proxy(v[1], v[2]) ; } } ; int main() { Vec3 v ; v.xy() = 1.0f ; v.xz() = 1.0f ; v.yz() = 1.0f }
>>355 ありがとうございます。
参考にしていろいろ弄ってみます。
>>354 とりあえず作ってみた。これで「v0.xz = v1.zx;」のような表記ができるよ。
完全にするにはSxy,Syz,Szx,Sxz,Szy,Szx,Sxyzの実装を網羅する必要がある。
struct Sxyz {
float x,y,z;
Sxyz & operator = (float f) { x=y=z=f; return *this; }
};
struct Sxy;
struct Sxz;
struct Szx;
struct Sxy : public Sxyz
{
Sxy & operator = (float f) { x=y=f; return *this; }
};
struct Sxz : public Sxyz
{
Sxz & operator = (Szx r);
};
struct Szx : public Sxyz {};
Sxz & Sxz::operator = (Szx r) { x=r.x; z=r.z; return *this; }
// つづく
358 :
357 :2007/10/19(金) 02:42:19
// つづき struct Vec3 { union { struct { float x, y, z; }; float v[3]; Sxy xy; Sxz xz; Szx zx; Sxyz xyz; }; Vec3() : x(0.0f), y(0.0f), z(0.0f) {} Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} }; int main() { Vec3 v0, v1; v0.x = 1.0f; v0.xy = 2.5f; v1.xyz = 4.0f; v0.xz = v1.zx; }
やべ、本当に
>>355 の要求した文法通りだ。
この発想はなかった。
でもunionってこんなことできるのかなと調べてみたら、やっぱり規格違反だった。
unionのメンバにクラスは使えるんだけど……。
>An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor
>(12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an
>array of such objects.
というか、union自体がメンバ関数とか、コンストラクタやデストラクタ持てたんだ。
規格読んで今初めて知ったよ。
360 :
357 :2007/10/19(金) 03:00:30
もし v0.xyz = v0.zxy なんてことまでやろうとしたら、組み合わせの数がとんでもないことになるね。
361 :
359 :2007/10/19(金) 03:09:28
あ、間違えた。copy assignment operatorだったorz 疲れてるみたいだ。もう寝よう。
>>357 おおっ!私のやりたかったことできるみたいですね!
参考にさせていただきます。ありがとうございます。
363 :
357 :2007/10/19(金) 04:04:00
>>354 すまん、訂正です。
「v0.xz = v1.zx;」はv0.x=v1.z, v0.z=v1.xという意味だろうから、以下のように直して。
(ついでに引数はconst参照の方がいいと思うので。)
Sxz & Sxz::operator = (const Szx &r) { x=r.z; z=r.x; return *this; }
>>359 , 361
>でもunionってこんなことできるのかなと調べてみたら、やっぱり規格違反だった。
>>An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor
>>(12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an
>>array of such objects.
>あ、間違えた。copy assignment operatorだったorz
面白そうだから作ってはみたけど、実は規格とか良く理解せずにいました。
non-trivial copy assignment operator というのはコピー代入演算子ということで
Sxz & Sxz::operator = (Sxz) ということでしょうか。
Sxz & Sxz::operator = (Szx) ならば問題なしという認識であっていますか?
>>350 n が宣言されてない。 >344 のやりたかったこととたぶんちがう。
だからなに。
みっちゃん と入力しても みっちゃん が見つかりません。比較関数の書き方を教えて下さい。 #include <iostream> #include <map> #include <string> class human{ private: std::string name; int age; public: human(std::string name, int age){ this->name=name; this->age=age; } int getAge(void){ return age; } std::string getName(void){ return name; } }; typedef std::map< char* , human > clsmap_t; int main(void){ clsmap_t clsmap; human yosida("吉田", 21), mitui("三井", 20); char buf[100]; clsmap.insert(clsmap_t::value_type("よっちゃん", yosida)); clsmap.insert(clsmap_t::value_type("みっちゃん", mitui)); std::cout << "あだ名を入力して下さい : "; std::cin.getline(buf, sizeof(buf)); clsmap_t::iterator n = clsmap.find(buf); if( n == clsmap.end() ) std::cout << buf << " not found." << std::endl; else std::cout << n->second.getName() << " " << n->second.getAge() << std::endl; return 0; }
bufをstringに入れて、そのstringでfindかけてみてはどうだろう
mapのキーもstringね ってマルチかよ
370 :
デフォルトの名無しさん :2007/10/20(土) 10:31:32
スタティックなメンバ関数と friendな関数 どう使い分けたらいい?
static 性的 friend 友達
>>370 C++3rdでは、friend、static、無印、の3つのメンバ関数を、こう分類してる。
メンバ関数の特性には次の3つがあって、
(1) 関数がクラス宣言の非公開部にアクセスできること
(2) 関数がクラススコープに含まれること
(3) オブジェクトを対象として関数を実行しなければならないこと(thisポインタを持っていること)
無印は(1)〜(3)、staticは(1)〜(2)、friendは(1)だけを持っている。
だから使い分けを考える時も、ここから出発するのがいいんではないかと。
どーしても(3)で困るならstatic、さらにどーしても(2)で困るならfriend、みたいな。
まぁ俺だったら、friendはよほどのことが無い限り使わないけど・・・。
374 :
デフォルトの名無しさん :2007/10/20(土) 11:42:06
375 :
デフォルトの名無しさん :2007/10/20(土) 11:54:56
(3)ということは void Class::Delete() { delete this; } は禁則事項?
376 :
デフォルトの名無しさん :2007/10/20(土) 11:56:46
ごみん読み違いだったw
377 :
337 :2007/10/20(土) 13:21:52
>>338 ,
>>340 トンクス
相変わらずよく分からずですが、そのクラスで用いるiteratorを
typedefでクラス内で定義しているのからだろう程度の理解で、C++の勉強を
先に進めるこすますた。
そこでboost::range_iteratorとtypeof_の組みあわせ技ですよ std::vector<int> v; boost::range_iterator<BOOST_TYPEOF(v)>::type iter;
379 :
337 :2007/10/20(土) 15:11:20
STLすら解らないのに、boostなんて、>< boost::range_iterator<BOOST_TYPEOF(v)>::type iter; のtypeもやっぱtypedefされてるから boost::range_iterator<BOOST_TYPEOF(v)>::が付くのですか?
>>379 それがboost::range_iterator<>の中で宣言された物だから。
typedefされたものかどうかは問題ではない。クラスや関数やその他いろいろなものでも同じ。
実を言うと、宣言、定義が何なのかも解らないのです><
だから
>>380 の意味が解りません><,orz
382 :
380 :2007/10/20(土) 16:35:59
バカ同士仲良くしろよ
384 :
デフォルトの名無しさん :2007/10/20(土) 16:43:08
385 :
デフォルトの名無しさん :2007/10/20(土) 16:53:49
>>383 バカじゃないのなら(頭良いなら、サクッと)
宣言、定義の解説汁
387 :
デフォルトの名無しさん :2007/10/20(土) 17:04:38
取りあえず、痔スレが立ったので この相談スレは終了です。 *************** 相談スレ 終了 *************** これよりC++雑談スレになります C++談話室 part1
何がしたいんだよ
389 :
380 :2007/10/20(土) 18:35:29
どうでもいいことだけど、382は俺じゃないよ。 2chで初めて騙られたw まあ381はへこまずに、基本をちゃんと勉強すべきだ。 とりあえず宣言や定義について書いてある入門書くらいは読むこと。
390 :
デフォルトの名無しさん :2007/10/20(土) 20:42:38
質問なんですが、ある特定の型だけ使える new のオーバーロードって定義できますか?
その型がクラスなら、クラスの中に書けばそれが使われる class X { public: void *operator new(size_t n); void operator delete(void *p); };
すいません。先月から開発の部署に配属されまして、C++の習得が必要になったのですが、 ただの事務職の経験しかなく、勉強しはじめたものの、正直申し上げてさっぱりわかりません。 みなさんはどうやってだんだんと使えるようになっていきましたか? コツコツと努力が必要なのは重々承知しておりますが、 努力の方向を誤らないよう、先人のたどった道がどんなものかを教えていただければと思います。
こういう質問って、好きで始めた人間には答えづらいね。 俺の場合、少なくとも初期の頃は、本を読んで、ソースを書いて、何か疑問を持ったらネットで調べる、 というのを、その時その時の好奇心のままに続けてきただけだから、 教えるべき「道」なんてものがあるのかどうか、そこからしてわからない。 「握力を鍛えるにはどうすればいいですか?」→「何か握ってれば?」くらいシンプルな問答に思える。 嫌々この道に入らざるを得なかった人の回答を待ったほうがいいね。
>>392 金とって開発してる組織でそんなことしてたらほとんど詐欺だな。
395 :
390 :2007/10/21(日) 00:01:28
>>391 ありがとうございます。早速試してみます。
Accelerated C++とEffective C++だな それとSTLを一通り使えるようにしとけば、まぁ問題ないだろ そこからexceptionalとかいってもまぁ一般的な理系学部卒程度の素養があれば半年もかからないさ
仕事だから勉強にいくらでも時間をかけられるということはないだろうけど、 基礎はしっかり身につけたほうがいいだろうね。 まずは入門書を読みながら、実際に書いて動かすこと。 読んで理解したつもりになってるだけでは、実際はほとんど身についていない。 書いてあるままを試して終わりにするのではなく、新しく習ったこれについて こう変えてみたらどうなるか、などいろいろ試してみること。 本を写したつもりでもきっとどこか間違えるから、コンパイルエラーとか動作がおかしいということが 発生するだろうから、それを解決することで何が間違いかを学んでいくこと。 独学だと問題に行き詰ったときに大変だから、誰か身近に教えてくれる人がいると良いね。 業務でやるんだから、先輩とかに聞けば教えてくれるはず。 …その先輩が平均程度には良心とか責任感があるなら。
そもそも半年も猶予があるのかという それに、プログラミングは合わない人は全く習得できないからなあ
>>392 好きでやろうが嫌々やろうがやることは一緒じゃないかな。
適当な入門書から入って真似して試して考えて調べて、、、
初心者にアドバイスしたいことは、
情報源は複数持つこと。一人の言うことを鵜呑みにせず、本やnetも並用すること。
何かに取り組むとき、現在の知識だけで何とかしようとするな。きっとより良い解決方法がある。
理解するまでは使うな。たまたま動いただけかも知れぬ。
C++ Coding Standardは……ちょっと微妙かな。 趣味でC++やる/エキスパートを目指すなら必須だと思うけど。
401 :
デフォルトの名無しさん :2007/10/21(日) 00:23:50
分からなかったときがあれば昼でも人がいるVipのプログラムスレお勧めw
業務でプログラミングするときは、理想と現実の違いを受け入れることも大切。 勉強していくうちに、単に正しく動くものが書けるというだけではなく、保守性だとか 論理的な正しさとかに気を配るようになったり、自分なりのより良いと思えるスタイルができてくる。 でも職場ではそこ独自の理解しがたいルールがあることが多い。 悪い点を指摘して改善するように提案することも効果がある場合もあるけど、 変に我を通さずに協調する(受け入れる・理解する・妥協する)ことも必要。
403 :
392 :2007/10/21(日) 00:56:56
みなさんのお言葉感謝します。
とりあえずまともにレスできるところにだけ・・・・
>>393 なるほど、元々のアプローチが違いますからね。
聞かれても困ってしまうかもしれません。
>>394 全くです。金もらってこんなことしてるので、会社に居辛いです。
>>396 学部も文系、職種も文系で、C++に更に種類があることも存じませんでした。
>>397 基礎からみっちりと身につけるつもりでいます。
ただまあ、仕事は待ってくれないという問題はたしかにございます。
今ぶつかっている問題は、例えば、
「参考書のAの項目とBの項目は理解できました。」
「じゃあAとBを組み合わせて使ってください」 → ( ゚д゚ )
という、初歩の部分でも応用が全くできないというところです。
404 :
392 :2007/10/21(日) 00:58:35
>>398 なんだか入社時の適性ではプログラマ寄りの適性だったらしいのですが、
変数の概念が理解できない時点で色々とダメな気がします。
>>399 なるほど、情報源を複数持つことですね。
今は黙々と入門書とにらめっこしている状態ですが、
入門書を真似する>試す>わからないところが出てくる>考える>やっぱりわからない>調べる>何をどうやって?
でもって、周囲は待ってはくれないので、「そういう風に動くもんなんだ」と自分を納得させてます。
>>402 困ったことに理想を持つ前に、来月自分の机がそこにあるかという現実がありました。
通そうとする我すらありません。
Accelerated C++ も Effective C++ も Exceptional C++ も本の名前 そういう種類の C++ があるわけじゃない どれも、まだ C++ がさっぱりわからない状態では読む本じゃないな
ほんとに何も知らない人に Accelerated/Effective/Exceptional C++ 進める奴とか結構いるけどさ どう考えたって間違ってるだろ
>>403 ちゃうw
Accelerated C++とEffective C++はC++の種類じゃなくて本ね。
特に、Effective C++はC++使ってるなら知らないとモグリだと言われるくらいの本なので、
いつか辿り付くといいね。
初心者にはちときつい。
>>403 世のため人のためこのスレのため、仕事を断れ。
いきなりc++はきついやろ できるならjava方面にしてもらえよ つかそれって肩たたきなんじゃねえの
皆さん、わて、Accelerated C++ とEffective C++ はじめてしました。 Effective C++ って第2版と第3版有るのですが、買うならやっぱり第3版のほう? あと、C++の趣味グラマーにお薦めの入門書の次に読む本って何かある?
411 :
デフォルトの名無しさん :2007/10/21(日) 09:23:26
>>410 自分も最近始めたC++趣味グラマーだが、C++ Primer 第4版を読んでる。
分厚いけど結構おすすめ。他の入門書よりかなり詳しく書かれているから。
1冊目としてはおすすめできないけど。2冊目にはいい。
特にAccelerated C++を読んだ人にはおすすめ。著者も一部共通しているし、
クラスの書き方からではなく、使い方から学んでいくという方針も共通している。
自分もAccelerated C++の後にこれを読み始めた。
今はちょうどPart Iを読み終えたところ。
ここまででやっと300ページ。あと残りページ600ページほど。
413 :
デフォルトの名無しさん :2007/10/21(日) 10:15:58
415 :
デフォルトの名無しさん :2007/10/21(日) 20:42:42
開発環境での相談なんですが... 研究者でデータ集めの道具として2年ほどC,C++を見よう見まねでいじっていました。 VS2005でなんとか自分のデータをいじるプログラムを作る事は出来ていたのですが、 サーバ側でデータをいじる必要がでて来て、LinuxでのC++統合開発環境を物色しています。 ずっと昔はemacs か mule ,少し前だとWideStudio, 最近はeclipse が定番のようですが、 アマチュア向けのC++開発環境としてVS2005から移行するのに今お勧めなのはどれ?
eclipseでいいと思うよ
メモ帳
この辺が即答できないところがデスクトップとしてのLinuxの課題
「サーバ側でデータをいじる必要」というのは単発的に必要なだけ? それとも継続的に開発することになるのかな? 前者で、プラットフォームに依存したコードなんかもいらないなら、 開発は今までどおりVS2005でして、コンパイルだけLinuxですればいいと思う。
>>415 eclipse以外に、KDEならKDevelopが、GNOMEならAnjutaが定番。
Windowsっぽさを求めるならKDEが無難。
最近のGNOMEはAnjuta使われてないよ。 もっぱらEmacsで書かれてる。ついでにいうとほとんどPythonで。
C++最大の注意点は1冊目何読むかだよな。 Cの場合K&Rでいいような気がするけどそれはどうよと突っ込まれる事もある。
424 :
415 :2007/10/22(月) 02:36:46
早速の御指導ありがとうございます。
>>420 継続的に必要になります。
今はデータを全部Windowsマシンにコピーしてそれを材料にしながらVS2005でコードを書いて
同じデストリのLinuxを入れたテスト系マシンに移してコマンドラインでコンパイルしなおして
さらに本番系にコピーしてしのいでいるのですが、どうも不自然な気がして....
も能率的なやり方とは思えないので.....
>>424 WinScpを巧く使えば、ソースをLinux側に置いたままVSでコーディングと事前コンパイルだけすることができるよ。
# 勿論、一時的にWindowsに転送しているのは言うまでもないけど。
つーか、スレ違いなんでほどほどに。
426 :
415 :2007/10/22(月) 11:10:30
>>425 スミマセン、特定の環境のスレだと擁護者やらアンチやらがいて初心者にとっては
誰を信じて良いか判らなくなりそうだったのでここで聞きました。eclipseはJ系
の人が多そうなので、C++で使っている人の意見を聞きたかったんです。
linux板の範疇だと思うがね。
428 :
デフォルトの名無しさん :2007/10/23(火) 00:32:35
すいません教えてください。 boost の bind の練習で、rubyのeachのようなものを作ろうとしたんですが エラーが下のように出てしまってうまくコンパイルできません。どこが問題なのでしょうか。 test1.cpp: In function `int main()': test1.cpp:32: error: no matching function for call to `Foo::Foreach(boost::_bi::bind_t<void, void (*)(int, int&), boost::_bi::list2<boost::_bi::value<int>, boost::arg<1> > >)' test1.cpp:8: note: candidates are: void Foo::Foreach(T&) [with T = boost::_bi::bind_t<void, void ( *)(int, int&), boost::_bi::list2<boost::_bi::value<int>, boost::arg<1> > >]
429 :
428 :2007/10/23(火) 00:35:49
練習用のコードはこれです。 #include <iostream> #include <boost/bind.hpp> class Foo { public: template <typename T> void Foreach( T& f) { for(int i= 0 ; i<10; ++i) { f(data[i]) ; } } ; private: int data[10] ; } ; void bar( int& data ) { data = 1234 ; } void hoge( int x, int& data ) { std::cout << data * x << std::endl ; } int main() { Foo foo ; foo.Foreach( bar ) ; foo.Foreach( boost::bind( &hoge, 10, _1 ) ) ; return 0 ; }
エスパー出動!!
432 :
デフォルトの名無しさん :2007/10/23(火) 00:43:17
>>429 またはconst T& なら通るんじゃない?
433 :
429 :2007/10/23(火) 00:54:03
>>431 >>432 ありがとうございます。
値渡し、const T&のどちらでもコンパイルがとおりました。
どうもありがとうございました。
434 :
デフォルトの名無しさん :2007/10/24(水) 21:03:07
こういうこと思ったことない? 関数内でインスタンスごとのstatic変数(=関数内private変数)が欲しい!! その関数内でしか使わないprivateな変数でもメンバ変数にしないとあかんやん これって、ソースが膨大になった時ってこのprivate変数はどこでつかわれてるんやろうなって 探した結果、この関数内だけかい!! って時に欲しくない?
>>434 関数内 だったら 単なる Auto 変数 ってことじゃないの!?
典型的なクラス分割のサインだと思う
だな。
438 :
デフォルトの名無しさん :2007/10/24(水) 21:42:48
>>434 class Foo
{
private:
int hoge;
public:
Bar(Foo f): { f.hoge = 99999; }
};
自分はこんなこと出来ちゃうのがちょっと気になる。
クラスごとでなく、インスタンスごとのprivate変数があれば、
こういう操作を禁止できるわけですよね?
Bar(const Foo& f)
440 :
デフォルトの名無しさん :2007/10/24(水) 22:02:46
あるクラス(test2)のオブジェクトを持つクラス(test)で、 testクラスのfriend関数からtestクラスにある test2クラスのオブジェクトの参照をしようとすると エラーになります。 class test2{ double d; public: test2(){d=10;} double np(){return d;} }; class test{ static test2 te; public: friend double xxx(double d){return te.np();} }; これはだめですか?
「友達の友達は友達だから、好き勝手にできる」と思って? まずはその厚かましさを恥じろ。 test2はxxxを友達だなんて思って(宣言して)ないでしょ?
442 :
440 :2007/10/24(水) 22:24:12
返答ありがとう。
>>440 のコードそのまま貼り付けたままならビルドできましたが
void main(){
cout<<xxx();
}
のように使うと駄目みたいです。
えーと、本当にやりたいことは
クラスのメンバ関数を関数ポインタに入れられないかと思いまして、
だからと言って、そのままやるとできなかったので、
一旦friend関数か何かを経由してやればできるかなぁと考えました。
無理みたいでしたけど。
(C言語でかかれたコードで、関数ポインタを渡して使う関数があったので、
どうにかしてC++で作ったクラスのメンバ関数を渡せないかと考えてます)
どうダメなんだ? friend double xxx(double d){return te.np();} を呼ぶつもりなら void main(){ cout<<xxx(); } は xxx に引数がないようだが?
444 :
デフォルトの名無しさん :2007/10/24(水) 22:53:32
>>435 Auto変数じゃなくてstatic。関数を抜けた後も値を保持してるってこと
445 :
デフォルトの名無しさん :2007/10/24(水) 22:58:11
>>436 ってことは、C言語の時は関数内でstatic変数を使用したことがないってことですか?
446 :
デフォルトの名無しさん :2007/10/24(水) 22:59:43
>>436 もし、そうでしたらC言語の場合はモジュール分割ってことになるんですよね?
>>442 静的メンバ関数なら普通の関数へのポインタへ変換できる。
こっちから関数への引数を1つくらい
渡せれば、(例えばWinAPIのEnumWindowsのように)
それを使って非静的関数も呼べる。
448 :
デフォルトの名無しさん :2007/10/24(水) 23:03:36
>>438 こういうのは不思議に思ったことがあるんだけど
そういうことではないんだよね
メンバ関数の先頭でthisポインタと比較すればいいんじゃね 実行時のアクセス制御になっちゃうけど
450 :
440 :2007/10/24(水) 23:26:25
>>443 あ、すいません
void main(){
cout<<xxx(0.0);
}
でも駄目です。
error C3767: 'xxx': 候補の関数はアクセス可能ではありません。
1> '.\NNN.cpp(30)' の friend 関数である可能性があります : 'xxx' [引数依存の照合を使って検出される可能性があります]
こんなエラー文になります
451 :
440 :2007/10/24(水) 23:36:07
>>442 こんなふうにしても駄目でした。
class test;
class test2{
friend test;
double d;
public:
test2(){d=10;}
double np(){return d;}
};
class test{
static test2 te;
public:
static double x;
static double xxx(double d){return x;}
};
void main(){
cout<<test::xxx(0.0)<<endl;
}
変なエラーが出ます。
>>445 メンバ変数と関数内static変数ではライフサイクルが違うじゃないか
>>434 の話と違っている
453 :
440 :2007/10/24(水) 23:51:32
アッー!! 変数の再宣言忘れてました・・・ どうも、おつかれさまです
454 :
デフォルトの名無しさん :2007/10/24(水) 23:55:48
>>452 そう?
クラス分割のサインって言うのはちょっといいすぎな気が・・・。
もちろん、時と場合によるけど。
ただ、privateなインスタンス変数より、さらにアクセスが厳しくなるんですよ!!
privateなインスタンス変数だとクラス内から使用できるけど、関数内インスタンス変数はその関数内でしか使えない。
よくないかい?
455 :
デフォルトの名無しさん :2007/10/24(水) 23:58:54
>>452 C言語でもC++みたいな、すなわちクラスみたいに作成したら結局同じかなっと思ってるんですけど・・・。
私は、C言語でもクラスみたいに書いてたので・・・。
456 :
デフォルトの名無しさん :2007/10/25(木) 00:08:24
>>453 関数ポインタでやるんだったら、関数ポインタでやらないと。
フレンドなんか滅多に使うことはないんだから。
関数ポインタがあるってことは、イベントを呼ぶってことでしょ?
そのソースの目的を見失わないようにね
メンバ関数内staticな変数(クラスメンバではない)を使いたいってことだよね うーん……
その関数と変数をクラス化して集約させるのが普通だと思うが。 関数が2個以上の場合でも汎用的に使えるし。
459 :
デフォルトの名無しさん :2007/10/25(木) 01:43:56
class Foo{ int v; public: Foo(int a = 10):v(a){} int get(){return v;} }; class Bar{ static Foo f1; Foo f2; public: friend int func1(); friend int func2(Bar); }; Foo Bar::f1; int func1(){return Bar::f1.get();} int func2(Bar b){return b.f2.get();} int main () { std::cout << func1(); Bar b; std::cout << func2(b); return 0; }
460 :
デフォルトの名無しさん :2007/10/25(木) 02:07:49
クラス内でのfriend関数の宣言、定義はprivateなメンバへの参照とは関係ない。 (Effective C++ 第3版の24項と46項を参照)
461 :
デフォルトの名無しさん :2007/10/25(木) 02:14:59
>>460 friend によって非メンバ関数になる
第一引数はそのクラスのオブジェクトでないと駄目
stl の begin, end などは引数が void の関数オーバーロードなのにどうして戻り値が const_iterator か iterator かを判別できるんですか? 使用先で関数を推論しているのかと思い同じような事をしてみたんですが、どうにもうま最適なく関数を絞り込めないようです。
463 :
デフォルトの名無しさん :2007/10/25(木) 02:55:43
ue
>>462 iterator vector::begin();
const_iterator vector::begin() const;
↑これが↓こんな感じでオーバーロード解決される。
iterator vector_begin(vector* this);
const_iterator vector_begin(vector const* this);
奈良自分で同じような事する場合はどうすりゃいいの
同じことをすれば、勝手にやってくれるだろう。 そうなってくれないとしたら、それは何らかの意味で「違うこと」をやっているのでは。
stlのソース読めば?
468 :
デフォルトの名無しさん :2007/10/25(木) 10:12:04
>>457 ごめん。言い方が少し悪かったです。反省します。
staticという言葉は無視してください
まとめると
「関数内でしか使えないメンバ(インスタンス)変数が欲しい」ってことです
なのでもちろんクラスのメンバです。
469 :
デフォルトの名無しさん :2007/10/25(木) 11:33:13
32bit表現の浮動小数点数を10進数に直せるプログラムってあるんですか? いくらぐぐってもみちかんない……
こんな感じだな #include <iostream> #include <sstream> #include <iomanip> int main() { float f = 3.14f; std::ostringstream s; s << std::setprecision(4) << std::showpoint << f; std::cout << s.str() << std::endl; }
472 :
デフォルトの名無しさん :2007/10/25(木) 12:04:34
>>469 32bit表現の浮動小数点数とは IEEE-754 のことですか?
そういうのは標準関数ではないと思います。
出来ない……標準関数じゃないのか…… そもそもC++にこだわる必要ないんだった…… 他スレ行ってきます。
std::stringstream ss; float x = 12.34; ss << x; でいいんじゃないの?
475 :
474 :2007/10/25(木) 18:27:44
ウボァ
int** a = new int*[2]; a[0] = new int[3]; a[1] = new int[2]; for(int i=0; i<3; ++i) a[0][i] = i; for(int i=0; i<2; ++i) a[1][i] = i; とかやったときに、a[0]行の配列のサイズを知る方法ってありますか? sizeof()を使ってもうまく出力できません。
素直にvectorでも使ってろ
478 :
aho :2007/10/26(金) 00:16:40
動的にメモり確保してるんだから、単純に int a0_size = 3; int a1_size = 2; int ** a = new int*[2]; a[0] = new int[a0_size]; a[1] = new int[a1_size]; ....... printf("size of a0 is %d\n", a0_size); では、あかんのかね? これでも十分なきがするけど・・・
こんなコード保守する羽目になったらformat c: だな…('A`)
480 :
デフォルトの名無しさん :2007/10/26(金) 22:03:30
リストを関数に渡したり、クラスの外部にリストを公開する場合って どんな方法使ってる? begin()とend()?
以下の様な形でstaticなメンバをcppで宣言する際に /* a.h */ class a{ static type_0 m0; static type_1 m1; }; /* a.cpp */ type_0 a::m0(123); type_1 a::m1(a::m0);//m1はコンストラクタでtype_0の変数を必要とする プログラムの都合上a::m0はa::m1の前に初期化されている必要があるんですが、 m0がm1の前に初期化されているという保証はあるんでしょうか?
宣言じゃなくて、定義か。
483 :
デフォルトの名無しさん :2007/10/26(金) 23:57:17
プログラムを実行した後、 Dos画面がすぐに閉じてしまうのですが 「何かキーを押してください」のような画面を表示して待機するためには どうするのが普通なのでしょうか
>>483 VS2005ならCtrl + F5でデバッガに乗せずに実行
デバッガに乗せて実行するなら、<conio.h> _getch()を実行
486 :
デフォルトの名無しさん :2007/10/27(土) 01:28:55
ビルドした.exeをダブルクリックで実行したときの フォルダの情報と、 ファイルをドラッグ&ドロップしたときのフォルダの情報が 違うのですが、 どうやって対処したらよいですか
多分Windowsのことだと思うがカレントディレクトリについて勉強する。 そしてそういうのはスレ違いだから二度と質問しないように。
俺のエスパー能力が、
>>486 の意味するところはカレントディレクトリだと告げているが、
俺には力不足だ。
490 :
486 :2007/10/27(土) 01:49:51
そうなんですか? ドラッグ&ドロップした場合は2番目の引数の文字列に c:\xxxx\file.txt ってなるので c:\xxxx\ の部分だけ抽出して対処しようとしたのですが もっと普通の方法があると思って質問しました。まあいいや。 c:\xxxx\ を抽出して、そのあとに任意のファイル名の文字列を追加する いい方法あるでしょうか。
だめだ、俺のエスパー能力をはるかに超えた強敵だった。 とりあえず言えることは、ファイルパスを分離する標準ライブラリはない。
_splitpath
どういう育ち方をすると、ここまで説明が下手になるんだろうな。 それとも、「自分の頭の中にあるものは、そのままでは相手には見えない」ということに まだちゃんと納得できていない年齢なのか?
自分が何を分かっていないかを的確に説明できる奴は、そもそもこういうとこで質問するまでもなく自分で解決できちゃうからだよ
そうじゃない できてないのは起こった問題の説明
vector<int,vector<int>> v; みたいなことできなかったけ?
>>496 vector<vector<int> > v;
ならできるが。
498 :
デフォルトの名無しさん :2007/10/27(土) 04:14:55
using namespace std; class A{ int x; vector<int> y;}; vector<int> z;
499 :
デフォルトの名無しさん :2007/10/27(土) 04:17:23
class A{ int x; vector<int> y;}; vector<A> z;
int → A?
vector<pair<int, vector<int> > > v; だな。やるなら。
503 :
デフォルトの名無しさん :2007/10/27(土) 04:37:48
vectorの中にいろいろ入れるとわかりづらい classでまとめよう
typedefじゃない? いちいち class 使う?
505 :
デフォルトの名無しさん :2007/10/27(土) 12:17:57
用途が不明だから外れているかもしれないけど、 map<int, vector<int> >とかmultimap<int, vector<int> >はどう?
typedef pair<int, pair<int, pair<int, pair<int, vector<pair<int, pair<int, pair<int, vector<int> > > > > > > > > type;
pair< int, pair< int, pair< int, pair< int, vector< pair< int, pair< int, pair< int, vector< int > > > > > > > > >
508 :
486 :2007/10/27(土) 12:52:16
なんか色々言われてるけど
できたからいいよ。
とりあえず役立たずの
>>493 は死んでいいよ
>>508 たしかに
>>493 は口が悪いから怒るのも分かるが、
>>508 の最後の1文も醜い。
やってることは同レベルだ。
つまらない仕返しなどせず、ほっとけ。
それと説明が下手だというのは事実だから、素直に受け止めたほうがいい。
そして俺もスレ汚し。すまそ。
コンパイルエラーのときに出る、 ”実体化” というのがわからないんですが、 これは何ですか?
テンプレートのインスタンス化
>>509 ある程度の年齢に達したお馬鹿さんというのは
「指摘を活かせない人生を送ってきたから今そうしてそこにいる」わけで、
そういう人に指摘しても無駄。イジることに終始してたほうが面白いよw
でも2chにしろネットにしろ、自分の身分を隠せるから普段恥ずかしくて人に訊けない様な事はどんどん聞けて便利だよねフヒヒh
515 :
デフォルトの名無しさん :2007/10/27(土) 20:23:50
同感ふふぃふぃふぃ
あんまりマニアックな事になると誰も答えてくれないけどね… cppllは閑古鳥無いてるし どこか良いコミュニティはないものか
ここでマニアックな質問が放置されたことなんて最近あったか? スレ違いならずっとあるけど。
みんなcppよりも大事な事があるんだよ
520 :
デフォルトの名無しさん :2007/10/27(土) 23:04:56
adobeのdng_sdkのコードを読んでるんだけど、メンバ変数名の頭に f がくっついています。 これって何の略なんでしょか。friendではなさそうだし、fuckもあえりない。 気になってしゃあないっす。。。
field の略じゃねーの?
203 名前:198 [sage]: 2007/10/26(金) 03:26:09 Exceptional C++ Style P.29 >・デフォルトパラメータを持つメンバー関数のシグニチャは、 > 「等価な振る舞いを持つ2つ以上のメンバー関数のシグニチャ」に > 置き換えても良い。 >・メンバー関数のシグニチャには、追加のデフォルトパラメータが > 含まれていても良い。 P.30 >つまり、コードの移植姓を保ちながら標準ライブラリのメンバー関数 >へのポインタを生成することは不可能なのだ。 理解できん。ここで教えてくれw
Exceptional C++ Style嫁
>>522 Exceptiol C++ Style は持ってないおれが説明してやるからちょっと待ってろ。
まず、そのルールは規格の 17.4.4.4 にある記述に対応するもの。言い回しや
順番は違うけど同じことを言っている。
見た目上のシグネチャが標準準拠ならデフォルト引数を使っていいよ 【実装者A】 うはwwwww list.clear(int hogehoge = 8) 【実装者B】 おkwwwww list.clear(bool hige = false) 【使う人】 ちょwww関数ポインタに移植性ナスwwwwwwww
526 :
524 :2007/10/28(日) 00:22:10
>>522 (1/2)
長くなったからレス2つに分けるよ。
以下のクラス S とそのメンバ関数 foo が標準関数として規定されている場合。
// 規格の表記
struct S {
int foo(int a, int b = 0);
};
以下の実装はどちらも >522 に挙げられた明示的な許可によって、規格に
準拠したものと言える。
// 実装 A
struct S {
int foo(int a) { return foo(a, 0); }
int foo(int a, int b);
};
// 実装 B
struct S {
int foo(int a, int b = 0, c = 1);
};
527 :
524 :2007/10/28(日) 00:22:42
>>522 (2/2)
規格の表記にある S::foo(int, int) へのポインタを使って、以下のような
コードを書くことが考えられる。
void f(std::vector<int>& v, S& s, int x) {
std::for_each(v.begin(), v.end(), boost::bind(&S::foo, s, x, _1));
}
実装が規格のとおりであればこのコードは問題なくコンパイルでき、意図した
とおりに動作する。
しかし実装 A のように実装されていた場合、 &S::foo では
オーバーロードされた2つの S::foo うちのどちらかコンパイラは判別
できず、コンパイルエラーになる。その場合、コードを以下のように
変更することで問題を回避できる。
void f(std::vector<int>& v, S& s, int x) {
std::for_each(v.begin(), v.end(),
boost::bind(static_cast<int (S::*)(int, int)>(&S::foo), s, x, _1));
}
このコードは規格の表記のとおりの実装と、実装 A の両方に対応できて
いる。
しかし実装 B のように実装されていた場合、 int (S::*)(int, int) に
マッチする S::foo は存在しないので、コンパイルエラーとなってしまう。
現状の規格ではどの実装も規格に準拠したものとされてしまうため、すべてに
対応するような(移植性のある)方法で S::foo へのポインタを使うことは
できない。
528 :
デフォルトの名無しさん :2007/10/28(日) 01:09:33
質問なんですが、Typelistを使わないでテンプレート引数の数を可変にすることはできますか? 下のようなScatteredHierarchyクラスを習作で作ってみたんですが、なんとかTypelistを見せないようにしたいんです。 ・テンプレート引数にTypelistが必要なScatteredHierarchy template <class T> struct ScatteredHierarchy ; template <class T, class U> struct ScatteredHier: public T, public ScatteredHierarchy<U>{} ; template <> struct ScatteredHierarchy<NullType> {} ;
529 :
528 :2007/10/28(日) 01:12:08
× template <class T, class U> struct ScatteredHierarchy : public T, public ScatteredHierarchy<U>{} ; ○ template <class T, class U> struct ScatteredHierarchy<Typelist<T,U> > : public T, public ScatteredHierarchy<U>{} ;
任意個は無理だが個数限定ならデフォルト引数でいけるんじゃないかな
>528 C++0xにならないとムリみたい。 とりあえずはboost::mplで我慢
532 :
528 :2007/10/28(日) 10:29:13
>>530 >>531 ありがとうございます。
デフォルト引数とmplの両方を使ってみてもう少し考えてみます。
可変個テンプレート引数といえばむしろBoost.Preprocessor
534 :
デフォルトの名無しさん :2007/10/28(日) 13:42:41
IDirectDrawSurface7 * DXC_ddraw::pCreateOffScreenSurface( DWORD dx, DWORD dy ) { IDirectDrawSurface7 * pdds; // 色々 retrun pdds; } 上記のようなソースを見たのですが、このメンバ関数を2回以上呼び出すと 最初の同じppdsの値を何回も返したりしないのでしょうか?
535 :
534 :2007/10/28(日) 13:47:24
すんません、自己解決しました。 色々のところで初期化(CreateSurface)してました。
最初も何も、pddsを宣言した時点では初期化していないのでpddsの値は不定。 「//色々」のところを省略されては、答えようがない。
>>536 なるほどpddsの値は不定ですか
勉強なりますた
>>527 ありがとう。やっと理解できた。ありがとー
template < class T, class T1 > struct s< T (*)(T1) >{ typedef T result; }; template < class T, class T1 > f( T (*p)(T1) ){ typename s<T (*)(T1)>::result r; } int F(char){...}; void test(){ typename s< &F >::result r; //エラー f( &F ); //エラーじゃない } こうなるのは何でですか?
>>539 まず、まともにコンパイルできるものをだせよ。
クラスsのプライマリテンプレートがないし、
関数fに戻り値がない。
関数testはテンプレートではないので、中でtypenameは使えない。
あと、何が疑問なのか分からん。
クラスsのテンプレートパラメータに渡せるのは型だ。
&F ; //これは関数Fへのポインタ、int(*)(char)型への値
int (*)(char) ; // これは関数Fへのポインタの型
541 :
デフォルトの名無しさん :2007/10/28(日) 17:08:33
template<class T> struct foo{}; int main(){ foo<int>::foo a; } でこれのコンパイルが通ってしまうんですが、理由がわかりません。 ::foo のところです。 どなたか教えてください。
542 :
541 :2007/10/28(日) 17:14:30
struct bar{}; int main() { bar b1; bar::bar b2; bar::bar::bar b3; } これも通るんですね。。 何故?!
>>541-542 クラス名自身がクラスのメンバとして登録されているから。
メンバになってるクラス名は "injected-class-name" と呼ばれる。
規格の 9 (Classes) p2 より
> A class-name is inserted into the scope in which it is declared immediately after the class-name is seen.
> The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
> For purposes of access checking, the injected-class-name is treated as if it were a public member name.
visual C++ 2005では通らない… gccの方が準拠度はいいのか?
>>545 へえ。VC++はもってないのだが、
typedef struct bar_ {
typedef struct bar_ bar;
} bar;
とか,
struct bar_ {
typedef struct bar_ bar;
};
typedef struct bar_ bar;
とかすれば同じ事ができる?
できてもうれしくない。 そもそも何のために規格でこんなことを決めているのかわからない。
こんな感じなのかな。 class Base { protected : int value ; } ; class Derived : public Base { int value void f() { value = 0 ; //どっちのvalueなのかややこしい Base::value = 0 ; Derived::value = 0 ; } } ;
は?
>>547 クラス(構造体)名に限って、同じスコープにある他の型と名前が重複しても
ODR違反にならないため、
int f;
struct f { int i; };
と書ける。このとき、単にfと書くとint型の方が、f::fと書くとstructの方が選ばれる。
int main() {
f a; // [ERROR] int型のfが選ばれるが、「<識別子> <識別子>」という構文はない
f::f b; // [OK] struct fの方が選ばれる
f = 1; // [OK] int型のfに1を代入
return 0;
}
>> 541 gccのバグ 規格の3.4.3.1/1a 見ろ。
>>550 その場合は struct f と書けばいい。 f::f が必要な理由にはならない。
553 :
デフォルトの名無しさん :2007/10/28(日) 19:06:05
>>551 すまんがいま手元に本がない。簡単に何が書いてあるか教えて。
3.4.3.1 (Class members) p1a より > If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, > when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the > constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition > that appears outside of the class definition.
おまいら・・・何食ったらそんな詳しくなれるんだ。
暗記パン
n2315 見たら >557 の DR 318 が取り込まれてるっぽいんだが、 A::A はやっぱり駄目で struct A::A は OK とか、もうさっぱり意味がわからない。 > A::A a; // error, A::A is not a type name > struct A::A a2; // object of type A
561 :
デフォルトの名無しさん :2007/10/28(日) 20:54:00
2315って古くない?
n2369 が出てた。この話題に関係あるところは同じだったけど。
563 :
デフォルトの名無しさん :2007/10/29(月) 23:04:27
質問なんですがあるクラスの親クラスの型をコンパイル時に取得する方法ってありますか? 親クラスの型毎にクラステンプレートの特殊化を定義したいのですが方法がわからないのです
>>563 無いはず。あるとしたら、多重継承したときにどうなるのかわからない。
>>563 boost::is_base_ofでenable_ifとかそういう話じゃなくて?
566 :
563 :2007/10/29(月) 23:53:59
568 :
デフォルトの名無しさん :2007/10/30(火) 00:31:59
下のような擬似2次元配列クラスを作っていて、 現在GetValueをオーバーロードすることで 1次元的にも2次元的にもアクセスできるようにしています。 それに加えて添字演算子を使って [i]で1次元的、[x][y]で2次元的にアクセスできるようにしたいのですが 何かよい方法はないでしょうか? 1次元、2次元どちらかだけ対応させることはできるのですが 両方に対応させる方法が思いつきません。 template<class T> class CArray{ T* m_array; int m_width; int m_height; public: //中略 //1次元的アクセス T& GetValue( int i ) { return m_array[i]; } //2次元的アクセス T& GetValue( int x, y ){ return m_array[ y*width + x ]; } };
つ[proxyクラス]
つ more effective C++
>>570 と more effective C++ を持ってる香具師
その本買う価値ある?
翻訳がこれ以上はないというほどひどいけど、代理クラスについて 簡単に知ろうと思うなら買っとけ。
ちょっと混乱してよく分からない状態なのですが T** ptr; のとき ptrをdeleteするとptrが保持してたポインタも一緒にdeleteされてしまいますか?
int *p; のとき pをdeleteすると、pの示す先(*p)に0が代入されると思いますか?
されるわけがない。
>>568 とほぼ同じことをするためにproxyクラスを使う必要があって
more effective c++を買った。
該当部分の翻訳:
> そのようなクライアントは、あたかもアラーの神に忠実な本物の生々した2次元配列を使ってプログラムする。
は、いまだに何を言ってるのかサッパリだが、ソースコード部分は(他の節も含め)とても参考になった。
吉川さんが訳してくれればいいのに……。
すげえな。原書では >Such clients program as if they were using real, live, honest-to-Allah two-dimensional arrays. になってる。honest-to-Allah は「神に誓って」ぐらいで強調でしかないだろうから、 「そのようなクライアントは、まるで本当に本物の2次元配列を使っているかのようにプログラムを書くことになる」 くらいでいいんじゃないかと思う。
そんな原文だったのか。卒研生の輪講並に酷い訳文だなぁ。
うーん、やはり原書を買った方がいいな……英語のがはるかにわかりやすい。
>>577 ありがとう。やっと決心がついた。
////classA.h//// #ifndef CLASSA_H_ #define CLASSA_H_ template<class T> class A { publilc: void func(T); }; #endif ////classA.cpp//// #include "classA.h" template<class T> void A<T>::func(T t) { //略 } ////test.cpp//// #include "classA.h" int main() { A a; a.func(T); // Tについては略 // 以下略 このときmain内でfuncなんてねーよって怒られるのですが どう解決したらいいのかわかりません どなたかご教授を・・・
テンプレートの内容は全部ヘッダに書いておく
581 :
579 :2007/10/30(火) 13:34:14
具体的にどのように書いたらいいのでしょうか
>>581 >>579 ////classA.h////
#ifndef CLASSA_H_
#define CLASSA_H_
template<class T> class A {
publilc:
void func(T);
};
- #endif
- ////classA.cpp////
- #include "classA.h"
template<class T> void A<T>::func(T t) {
//略
}
+ #endif
////test.cpp////
#include "classA.h"
int main() {
- A a;
- a.func(T); // Tについては略
// 以下略
>>581 ////classA.h////
#ifndef CLASSA_H_
#define CLASSA_H_
template<class T> class A {
publilc:
void func(T t) {
//略
}
};
#endif
584 :
579 :2007/10/30(火) 14:45:14
>>582-583 そいういうことだったんですね
なんとなくtemplateについて解ってきた気がします
ありがとうございました
templateって多用するとバイナリ大きくなるから 組み込みではほとんど使われないと聞いたが メモリの使用量も同様に増えるもん? 何だかスレ違いですまん
>>585 実行バイナリのテキスト部分、つまりマシン語のコードの分もメモリ食うから、その分は消費が増えていると言える。
ヒープやスタックを余分に食うかはコードの書き方によるが、ヒープの消費は若干減るケースが多いと俺は思う。
589 :
587 :2007/10/30(火) 21:45:22
おっと組込みか。組込だと、バイナリの分はRAMは喰わないこともあるな。ま、自分で考えてw
>>576-577 初版や原書持ってないから場所間違ってるかもしれないけど、2版の場合こうなってる。
「そのようなクライアントは、実在する、生きた、本当の2次元配列を使っているかのようにプログラムする」
まあ、割と普通。初版は相当キてるようだね
英語の小説とかだとあらすじがうっすら解るぐらいなのに 技術書は英語でもスラスラ読めるよね 不思議なもんだ 新聞も読めない
実在する、生きた とかいらねぇぇぇ
>そのようなクライアントは、「そのようなクライアントは、実在する、生きた、本当の2次元配列を使っているかのようにプログラムする」2次元配列を使っているかのようにプログラムする これのどこが普通なんだ? まずクライアントってのが変だろ。どう考えても。 ここは思い切って、「ライブラリを使用する側にとっては」などにしておいたほうが分かりやすいだろう。 「実在する、生きた、本当の」ってのも、くどすぎるだろ。アラーに忠誠を誓うのとあまり代わり映えしてないぞ。 「あたかも、本当に2次元配列であるかのように」などのように、何で出来なかったのか。 あと、「プログラムする」って何か違和感がある。 「プログラミングする」、とか、「コーディングする」という言い回しならそういう違和感も感じないんだが。 ハリポタや戸田奈津子並だな。
クライアントは普通だと思う この業界ではよく使うし
原文でもくどく書いてる
char (&test(...))[3] ってどういう意味ですか?
このシリーズで使われている「クライアント」という用語の意味については ちゃんと書いてあるのに。業界とか何の関係も無いし。 EffectiveC++すら読んでないということだね。
現在注目しているコードを使用する側のコードの事だっけ デザパタ系の解説記事とかでよく見る気がする
一応書いておくと、
筆者は、STLのような「再利用可能な実用的なライブラリ」を書く、という立場で記述している。
つまり、この本での「クライアント」とは、「ライブラリの利用者」のこと(ちゃんとそう書いてある)。
それを前提を知っている人から見れば、
>>591 はそんなにおかしくはない。
>>595 書籍や映画の字幕と較べるのは如何なものかと。
# それに、あの脱税社長と較べたら戸田さんが可愛そうだ。
Q:アラーの神とか、そういう慣用的というか比較的くだけた表現は原文でもよくわからないし じゃあどうすればいいんだ? A:無視
Doubutu←Honyurui←Inu ←Neko ←Chorui ←Suzume ←Karasu このようなクラス階層のオブジェクトをポリモフィズムする場合... std::vector<Doubutu*> doubutu_; と保持して、HonyuruiやChoruiに純粋仮想と定義されたメンバ関数を呼び出す時はダウンキャストする。 ダウンキャストするぐらいなら最初から、 std::vector<Honyurui*> honyurui_; std::vector<Chorui*> chorui_; と保持する。 どちらがいいのでしょうか?
そもそも継承するような種類のものだろうか。
606 :
604 :2007/10/31(水) 12:38:09
>>605 動物に例えたのがまずかったですかね。
HonyuruiとChoruiに共通の部分(仮想関数)がある場合、その部分を別のインターフェイス(Doubutu)として定義し、
継承することによって、HonyuruiやChoruiをDoubutuとして振舞う事も可能になり、便利だと思ったんですけど、
この多重継承事態がまずいですか?
いや別に多重継承じゃないだろそれ。
>>604 キャストしないほうが安全。いいか悪いかは自分で選べ。
>>604 好きにすれば…としか。
ダウンキャストするなら、dynamic_cast 使えよ。
610 :
デフォルトの名無しさん :2007/10/31(水) 17:23:46
マルチプラットフォームでGPLなどの制限がないフリーのC++コンパイラを探していますが、ありますか? GCCはGPLがあってだめでした。 BCCはWin32しかコンパイラがなさそうでだめでした。 よろしくお願いします。
export実装がんばれ。
613 :
604 :2007/10/31(水) 18:35:22
>>608 ,609
ありがとうございます。
どちらかが悪い方法というわけではないんですね。
>>598 ...のところは何か省略してる?
testは、「char型の要素数3の配列への参照を返す関数」。
違ってたらすまん。
>>610 GCCのライセンスって、コンパイルしてできた出力には
GPLがかからないなんて例外事項が付いていなかったっけ?
>>598 char 返し引数に ... を取る関数ポインタの3つの配列の宣言。
char (&test[3](...)) そう言うならこれは?
>>598 >char (&test(...))[3]
引数が...で、要素数3のchar配列への参照を返す、test関数……かな
>>617 >char (&test[3](...))
それってコンパイル通るのか?
分からん
>>615 ふと思ったんだが、そういう例外事項がないと、
GPLなプログラムによって生成されたコンテンツはGPLになるのか?
たとえばエディタとかペイントソフトとか画像処理とか。
http://kmaebashi.com/programmer/pointer.html Cだけど、これは参考になるはず。
598はこうなる(614で既出)。
test is function returning reference to array of char
testはcharの配列への参照を返す関数
>>617 test is array of function returning reference to char
charへの参照を返す関数の配列
関数の配列だから、普通の変数としては存在できそうにないな。
>>619 それは derived work をどう解釈するかという形而上学的論争になるんじゃない?
エディタやペイントソフト程度なら、生成されたコンテンツは派生物にはならないと思うが、
emacs が生成した dump なんかは派生物になるだろうし。
緩める側への例外規定があれば、この論争を避けることができる。
623 :
598 :2007/10/31(水) 22:41:55
>>>char (&test(...))[3]
これboostスレに合ったんだよね
普通関数ポインタ/リファレンスならなら
char (*test[3])(...)とか、char (&test)(...)だよな・・・?とか思って助けてもらおうとおもった。
>>617 の
char (&test[3])(...)は通らなかった。
この関数を呼んでる場面もsizeof( test(NULL) )みたいにsizeofに掛けてたから、
>>618 の言う通り要素数3のchar配列参照を返すっぽい。
こんな書き方始めてしったよ・・・
テンプレートクラスについて質問があります。 テンプレートクラス側のメソッドから、 (返り値がテンプレート参照のメソッド) 不正な値を表すnullのような返り値を返したいのですが その際の「nullのような返り値」をどう定義したものか困っております。 漠然と、const staticで定義した定数の参照を返すか?と考えているのですが 詰めきれていません。 いいやり方はないものでしょうか? 宜しくお願いします。
横からだが、 もはやどんな関数ポインタが出ようが理解できるという自信があったのに、 char (&test(...))[3] は理解できなかった。 charへのキャストか? それでoperator & ()をオーバーロードしているのかも、じゃ[3]はなんだ? とか思ってしまった。 まさか配列への参照を返す関数だったとは。 typedef char (&test(...))[3] ; typedef char ret_type[3] ; typedef ret_type & same_type(...) ; int main() { std::cout << typeid(test).name() << std::endl ; std::cout << typeid(same_type).name() << std::endl ; std::cout << boost::is_same<test, same_type>::value << std::endl ; } うーん、人間コンパイラへの道は遠い。
>>624 ポインタじゃ駄目なの?
>>625 char (&test(...))[3]みたいに出されると、
咄嗟に変数だと思っちゃうからねえ
>>626 関数ポインタを引数に取る関数を、typedef使わないでってのは前に見たことがあったんだけど。
>>625 &をいったん*に置き換えて考えてみたら、分かりやすかったんじゃない?
>>626 今回はテンプレートの練習がてらに組んでる物なので、
テンプレートらしい解決法があればそちらを取りたい次第です
>>629 その問題ってテンプレートは関係なくて、参照型を返すメソッドで
null相当の値を返したい、というのとはどこか違うの?
>>624 ポインタをあたかも参照のように使えるラッパを書くとか。
で、is_valid()みたいなメンバ関数を付け加えるとか、
あるいは例外を投げるとか。
そもそも、例外投げていいような状況なら、ラッパなんて要らないがw
>>631 型が決まっていればそれに対しての不正な値をひとつ決めればOKだと思うのですが、
テンプレで複数の型を扱う必要がある場合にどうするか、で悩んでます。
>>632 少し考えてはみたのですが、
そのテンプレがクラスのみではなく、char,int等の型も扱う場合に対処できるのでしょうか?
あと、基本例外はなしで考えてます。
精々printfぐらいで
boost::optional的なモノを自作
>>624 ポインタを使うのが妥当
不正な値を返すかどうかは実行時に決まるので
テンプレートでできることはない
テンプレートで解決できるのはコンパイル時の問題
typeid(type).name() で出力される文字列はそのままコンパイライライライライライライライライライライライライライラに通してエラー無くコンパイルできる事が保証されているんでしょうか?
>>634 boostは触ったことがなかったのですが、
かなり参考になりそうです。
>>635 > 不正な値を返すかどうかは実行時に決まるので
> テンプレートでできることはない
> テンプレートで解決できるのはコンパイル時の問題
なるほど、わかりやすいレスありがとうございます。
テンプレで全部まかなうっていうのは無理がありそうですね。
とりあえず、
>>634 氏のおっしゃるように、boost::optionalを目指して何か作ってみようと思います。
皆さん、相談にのっていただいてありがとうございました。
>>636 なにも保障されていない。
NULL終端されてるシングルバイト文字列か、あるいはマルチバイト文字列かもしれない。
とりあえず人間が読んで、どんな型なのか分かる文字列であることが期待されているだけ。
>>639 type_info::name()はconst char *を返すことが決まっているから、
その型にあったコーディングさえしていれば、コンパイルはできるんじゃない?
(文字列の内容をどう扱うか、どう表示させるかはともかく。)
636が言う、コンパイラに通すの意味が良く分からんが。
>624 「テンプレートらしく」ということなら、不正通知をポリシーに切り出して、組替え可能にするんじゃない? そうすれば「例外」「ヌルポインタ」「ヌルオブジェクト」「その他」を好きなように切り替えられるようになるし。
まず、配列への参照ってのが普段あんまり使わんな・・・
ポインタだと無理だけど、参照だとテンプレートで配列のサイズが特定できる。 あまり使う場面ないけど
Boost.Rangeでは、ところどころに使っていそう。
boostにreference_holderとかあったような これとコンテナテンプレート使えば参照のコンテンが作れる
>>640 コピペして貼り付けてコンパイル
VC8 でやってみて void (__thiscall type::func)(void) の様なものが現れた時にそれをメンバ関数ポインタの型だと思ってコンパイルに通しても
駄目でしあt
あれ、何故か出来ない。 typedef int (&foo(...))[3] ; typedef int (&bar(int))[3] ; //コンパイルエラー //typedef boost::function_traits<foo>::result_type ret ; typedef boost::function_traits<bar>::result_type ret ; std::cout << typeid(ret).name() << std::endl ; // int [3] typedef boost::extent< ret > size ; std::cout << size::value << std::endl ; // なぜか0
こんなのとかか? template<typename T, std::size_t N> inline std::size_t numberof(T (&)[N]) {return N;}
>>649 その場合retは参照型になるようだ
参照型やポインタの場合boost::extentは0になるのは正しい動作の筈
対策としてはremove_referenceで参照を取り除いてやること
boost::remove_reference<boost::function_traits<bar>::result_type>::type ret
余裕があったらsvn headのboost::function_typesも使ってやってくだしあ
653 :
649 :2007/11/01(木) 16:23:32
>>651 いや、それは真っ先に思いついたので既に試した。
それでも0が表示される。
VC8なんだが何故だろう。
template<std::size_t N> int &ar(int *array)[N]{ return *array; }
655 :
649 :2007/11/01(木) 16:27:30
うげ、remove_referenceという、メタ関数を「呼び出す」のを忘れていたorz
左辺値、右辺値がよくわかりません! 特にウヘンチサンショウっていう奴。 C++に限ったことじゃない?
左辺値=変数 右辺値=値
659 :
デフォルトの名無しさん :2007/11/01(木) 19:21:38
>>658 const値は?
代入可能な左辺値と単に左辺値と言った場合の違いは?
左辺値は実体がある=メモリを食ってる=アドレスを得ることが可能。 右辺値はそれ以外の全て。 定数であることとは関係ない。 例えば、関数は左辺値。
>>654 やりたいのはこういうこと?
#include <iostream>
//#include <boost/mpl/identity.hpp>
template<std::size_t N, typename T>
T (&ar(T* array))[N]
//typename boost::mpl::identity<T (&)[N]>::type ar(T* array)と書くほうがまだ分かりやすいと思う
{
return reinterpret_cast<T (&)[N]>(*array);
}
const int N = 1024 * 1024;
class hoge
{
public:
~hoge()
{
std::cout << "~hoge" << std::endl;
}
};
int main()
{
typedef hoge my_array_t[N];
my_array_t& a = ar<N>(new my_array_t);
delete[] &a[0];
}
662 :
デフォルトの名無しさん :2007/11/01(木) 19:54:30
>>660 一時オブジェクトもメモリを食ってるけど。
配列型も左辺値だけど変更可能な左辺値ではないよね。
int a[ ] の場合aも左辺値
代入構文の左辺になれるものとかw
俺は適当に
>>663 の様に考えてた
厳密な定義を考えた事ないや
>>662 一時オブジェクトは生成の省略が許されているから、
必ずメモリを食うとは限らない。
っていうか必ず食ったら嫌すぎる。
よって右辺値扱いで正解。
でもなぜかアドレスが取れてしまう不思議 それともVC7.1がウンコなだけだろうか
gccなんてラベルのアドレスも
>>660 関数が左辺値ってどういうこと?
C++に関数という値はないんじゃない?
>>669 関数が左辺値かどうかは知らないが、
少なくとも、アドレス演算子や暗黙の変換で、関数からは関数へのポインタを得ることが可能。
>>662 のように配列と同じく関数は変更不能な左辺値なのかもしれない。
>>667 ウンコ。でも警告レベルを上げれば警告になったはず。
もちろん関数へのポインタはあるよ
それはポインタだから左辺値にもなるし右辺値にもなる
でも
>>660 には関数が値だと書いてあるのでどういうことだろうと
プログラミング言語の話をするときには関数自体と関数へのポインタは
明確に区別するべきだと思うし
まあ、言葉のあやのような気もするけど
関数へのポインタ型とは別に、関数型があるという点で、 C/C++には、そういう意味での関数があると俺は思っている。 関数型のリテラルが書けないとこをつかれたら痛いけど。
>>671 そこでいう関数は、関数名のことかな。
int a; という変数があるとして、変数名aを左辺に書けばそのオブジェクトを表すし、右辺として評価すればその値は変数の内容。
同様に、関数名を評価した値は関数のアドレスだけど、関数名自身は左辺値になる。まあ代入はできないけど。
>>671 まぎらわしいが、「左辺値」とは「値」のことではい「式」のことだ。
オブジェクト参照を生成する式とか、結果としてアドレスを割り出せる形になる式のことだ。
やっべC++暦2年だけど今の流れサッパリわかんね インターネッツで修行してくる
typoった はい → ない 「関数そのもの」と「関数コール」と「関数ポインタ」と「関数名」って どれも違うことなんだけど難しいねえ
677 :
671 :2007/11/01(木) 23:37:20
ああそうか 関数へのポインタ fp があるということは *fp は関数への参照、つまり左辺値なんだね なるほど、わかりました
そう考えると関数定義ってコンパイラから見ると const staticなポインタ変数に初期値を与えてる感じなのかな
>>657 が右辺値参照と言っているが、
それ自体は、右辺値で初期化できる参照型の1種であるというだけ。
従来の参照型はもちろん左辺値参照にあたる。
左辺値参照の初期化は左辺値でなければならず、
右辺値参照の初期化は右辺値(左辺値→右辺値変換はだめ)でなければならない。
(というとかなり語弊がありまくりだけど気にしない)
何が右辺値で何が左辺値かはここまで散々議論されてきたので上のほうを見ろ。
右辺値はどうせすぐに消えるのだから、
消える前に中身をぶっ壊してもいいだろというのが右辺値参照導入の動機。
時と場合によって、バカ正直な深いコピーをする必要がなくなる分、高速化に繋がるというわけ。
> 右辺値参照の初期化は右辺値(左辺値→右辺値変換はだめ)でなければならない。 なんだ、すげえ真っ当な仕組みなんだな。 もっとトンデモな仕様想像してたよ俺。
仕事で初めてC++でWindowsアプリを作ることになりました 内容的にはWEBアプリでこれまでやっていたことを、 クライアントアプリに移すような作業で、製作環境はVisualC++2005になります そこでお尋ねしたいのですが、C++を使用する場合に、 今の流行として、CLI、MFC、標準ライブラリとSTL、 これらのうち、どれを使用するのが適当なのでしょうか?
具体的な内容がわからんとなんとも言えない
なんでもありのバーリトゥードがC++の醍醐味
元がWEBアプリならhtaという選択肢はなし? スレ違いだけど
戻り値が正しくない演算子多重定義だけど(メイヤーズ本) T operator+(const T& lhs, const T& rhs) ; の場合、 T t1, t2, t3; t1 + t2 = t3 ; が可能になる。t1 + t2 は一時オブジェクトすなわち右辺値を生成するのに 代入可能なのが気持ち悪い。
戻り値を const T にするのではダメ?
ご回答、ありがとうございます
>>682 あまり詳しい内容はアレなんですが、何かを登録するシステムで、
画面数が10くらいで、セレクトボックスとテキストボックスがあって、
検索と登録を行うみたいな感じです
クライアントアプリにしてUIリッチにしてオペレータの作業時間を短縮したいそうです
主にドラッグ&ドロップで登録するオブジェクトをぽんぽん追加したいようで
>>683 なんでもアリ過ぎて、腕を取りにいくべきかパウンドで攻めるべきか、
マウントポジション取ったまま悩んでいます
>>684 htaは初耳でした。少し調べてみます
いや、お前ら、
>>681 はどのくらい役に立つかとか、そういうことを聞いてはいないぞ。
「今の流行」を聞いているんだ。
さて、そうだなぁ、MFCなんて昔はやった過去の遺物だろ。
確かに便利ではあるんだが、実装が古臭い。
もちろん、昔はまともなC++コンパイラがなかったから仕方ないんだが。
標準ライブラリとはおそらくはCのことだと思うが、これなんか古すぎて、
ほとんどのものが、いまどきは使用を推奨されないな。
だからVCにはセキュリティを考慮したバージョンが存在するわけで。
STLも、かなり荒削りなんだよね。C++の規格制定のギリギリになんとか作ったわけで、
考慮が足りない部分とか、そもそも未完成なものとかもある。
CLIだが、なんか微妙だよね。
わざわざC#を覚える必要がなくなれたC++の文法で使えるぐらいの利点しか。
あれ、今の流行のライブラリは見つからないな。
ATL/WTLが最近の流行。ただしマイブームに過ぎないけど。
ATL, WTLをboostと組みあわせて使うのがなかなか無間地獄っぽくて楽しいかも
>>688 標準ライブラリとはiostreamとかのことを言いたかったのでは?
それならそれで標準C++にとっては標準ライブラリ⊃STLだが。
いずれにせよ、GUIとは関係ない内容で、
681の挙げた他の選択肢とは、排他的なものではない。
692 :
デフォルトの名無しさん :2007/11/02(金) 00:38:14
なあ。組み込みでCやってきてて、C++使うことになって、勉強始めたんだが。 STL使おうとしてる。 んで、まずは配列の代わりにvector使うのが良いと聞いて、使おうとしてるんだが。 vectorの要素は、メモリ上に連続で並んでいることがわかって 一安心(効率のいいmemcpy使って一気に書き換えられるし)。 だが。push_back()するたびに、メモリの動的確保するってどうなんよ? 目を疑ったわけだが。vectorが使用するメモリ領域を上位で指定するとかして、 動的確保が発生しないようにする方法ってないんかね。
つvector<T>::reserve(std::size_t)
>>692 >動的確保が発生しないようにする方法ってないんかね。
あるよ。
std::vectorのメンバ関数をひととおり眺めてみれば?
>>691 Windowsアプリといっているだけで、なにもGUIのライブラリに限定しているわけじゃないだろ。
GUIのライブラリも重要だが、それ以外にもやることはあるだろ。
>>692 まあ、普通はメモリが足りなくなったら、
現在のサイズ1.5倍とか2倍とか確保して、
毎回メモリ確保しなくてもいいように実装するんだけどな。
商用ならQtにすれば?
698 :
デフォルトの名無しさん :2007/11/02(金) 00:55:05
>>698 resize(), capacity()についても調べてみると幸せになれるよ。
reserveはcapacityを増やすだけでsizeは変わらない
701 :
デフォルトの名無しさん :2007/11/02(金) 01:05:25
>>700 ありがとう!
ちなみに、STLのリストやらキューやらで、要素を追加すると
同じようにメモリの確保が発生するのかな??
resize 実際にsizeが変更される reserve これで指定したサイズまではメモリ確保がされない だと思う
703 :
デフォルトの名無しさん :2007/11/02(金) 01:06:53
それと、vectorやらlistやqueueで、要素を追加するときに、 allocが発生しない、かつメモリコピーも発生しないように することってできますか?
704 :
デフォルトの名無しさん :2007/11/02(金) 01:08:08
>>702 ありがとう!
703の追記ですが、上位で指定した領域をそのままリストにつなぐという
意味です。vectorだとコピーせざるを得ないですが。
出遅れた('ー`) Object Poolとかでググると幸せになれるかもしれない。
>>703 listやqueueにはvector::reserve相当の関数はないから、
自前でアロケータを書けばいいのかも。
707 :
デフォルトの名無しさん :2007/11/02(金) 01:20:53
>>705 Object Pool検索しましたが、Javaのしかでてきません!
>>706 自前でアロケータ書いて、ごちゃごちゃやるくらいなら、
独自高速版STLもどき作ったほうが、幸せになれるような
気がするなぁ・・・。
>>704 list についてはあらかじめ作っておいた別の list から splice() でつなぐことができる。
メモリ確保についてはタイミングが変わるだけなんだけどね。
>>707 標準のSTL自体がそれなりにチューニングして実装されているだろうから
まずはそれで本当に遅いのかを確認したほうが良いのでは?
がんばって独自版を実装してみたものの実は不要だった、なんて
不幸せになるような気がするなぁ…。
>>706 手軽に済ませたいならboost::poolがあるよ
711 :
デフォルトの名無しさん :2007/11/02(金) 01:32:46
>>708 おぉ、シリマセンデシタ。ありがとうございます。
>>709 allocしない、かつコピーを最小限の機能限定STL(自動的にvectorを伸張しない)
とかだったら、アプリによっては数倍の速度になるんじゃないかなぁ。
リストもキューも、本質的には単なるポインタの付け替えなわけだし。
それを渡された要素分、allocしてコピーしてたら速度の違いは歴然
じゃないかな。組み込みでは。
ていうか、あなたの使うSTLのallocatorの実装はpoolを使ってないの? 大抵の実装がsetやlist等の必然的に細切れになるコンテナ用に poolを使ったallocatorを用意していたと思うんだけど
>>711 「じゃないかな」なんてつくようなら、まずは何も考えずに使ってからにしたほうがいいよ。
処理系実装者を一度ぐらい信じてやってもいいでしょ。
allocator をカスタマイズしたり、自作の vector や list を正しく作るのはほんとうに
大変なんだよ。
714 :
デフォルトの名無しさん :2007/11/02(金) 02:48:09
>>712 ,713
allocの処理負荷を軽減できるというのはわかるけど。
メモリコピーは、そうやっても減らないわけだし。
アプリ処理の2〜3割を、メモリコピーが占めることが
Cですらザラにあるわけで。
あのー、setやlistは、vectorみたいにデータが移動しないことが要件に含まれているんですけど
>>714 コピーの処理時間が問題になっているのがわかってから考えるんだ。
さらに言うと、問題になっている箇所以外は標準コンテナのままでいい。
偉い人も言っている。 "Premature optimization is the root of all evil" と。
ほんとに頭悪くてごめん。 右辺値参照が理解できん。
>>717 これでどう?
// 既存の(左辺値参照用)コピーコンストラクタ
vector::vector(vector const& other)
{
allocate(other.size());
// コピーうぜー。けど other は const& だからしょうがないんだぜ。
copy(other.begin(), other.end());
}
// 右辺値参照用コピーコンストラクタ
vector::vector(vector&& other)
{
// other つぶしていいんならメモリ確保もコピーもいらねー。うはwwww
other.swap(*this);
}
>>718 const 参照は右辺値を参照できるけど、左辺値は参照できない。
vector const& otherのほうが右辺値参照ではないの?
>>702 reserveはメモリ確保はされるけど初期化はされない
ということじゃないか?
resizeはメモリ確保されて初期化もされるから要素数も変更される
>>718 これは便利!と思ったけど調べてみたら、これできるのC++0xからなのね。
>>719 そこらへんやオーバーロード解決のルールも変更されて、右辺値を引数にした場合は
右辺値参照用のほうが優先されるんだろ。
CHAR_BIT は最低 8 ビットで char が符号付か符号無しかは処理系定義だから 一般的に std::ostream の put() は 0 から 127 までしか書き込めませんか? 0 から 255 まで書き込むには std::ostream<unsigned char> を使うのでしょうか?
>>723 何がしたいのかわからん。
移植性を優先するなら std::ostream に int を出し入れするのがいいんじゃないの?
>>724 すみません。すでにフォーマットが確定したバイナリデータを書き込むときのはなしです。
フォーマットでは1バイトが8ビット符号無し整数です。
>>725 typedef unsigned char uint8;
といったようにtypedefしておき、処理系によってこの定義を変える
>>723 std::ostream<char>は必ずしも8bit cleanではないのではないかってこと?
規格上どうだか、俺は知らないなあ。
charが符号付きであっても、↓が動かないような環境は、見たことが無いけど
#include <iostream>
int main()
{
const char *s = "こんにちは、世界\n";
char c;
while (c = *s++)
std::cout.put(c);
}
728 :
727 :2007/11/02(金) 13:23:45
std::basic_ostream<char>だな、すまん
s の型が std::ostream<char> で char が表現できる範囲が -128 から 127 のとき s.put( 200 ); を実行すると 200 がどういう数値変換されるかは処理系定義 だと思っています。 128 以上はすべて 0 に変換される処理系もあるかもしれません。
>>725 C++ の規格にストリーム出入力の規定はなくて C のライブラリの上に被さってる。
C の規格によるとストリームは character の順序つき列だとされている。
character が char を指すとして、 CHAR_BIT が 8 でない環境で 8 ビット符号なし整数
というバイナリデータを書き出すこと自体が不可能だろう。たぶん。
で CHAR_BIT が 8 だとして符号有り無しの話だけど、 unsigned char の変数を
char* で指して読み出した値を put() すればいいよ。 C/C++ の (signed/unsigned) char* は
任意のバイト列を指すことができるとされているからね。整数変換を通してしまうと
>729 の言うように処理系定義でどうなるかわからない。
unsigned char のオブジェクトを signed char へのポインタを通して アクセスしたときはどのような動作になるんでしょうか。 負の整数を2の補数以外で表現する処理系では unsigned char の 255 が signed char の 0 として取得されるようなことはないでしょうか?
>>718 vector::vector( vector const &other ){
array_ptr = other.GetArrayPtr();
}
って右辺値参照用コピーコンストラクタと同じ感じじゃないの?
dir0/file0.cxxの中で #include <dir1/file1.h> #include "dir2/file2.h" としたとき、および、dir2/file2.hの中で #include "dir3/file3.h" としたとき、それぞれincludeされるファイルの探索範囲・順序は、標準では決められてないのでしょうか? また、主要コンパイラでの探索範囲・順序などご存じありませんか? mingw gcc 4.3.2では <> → includeパス "dir2/file2.h" → dir0/dir2/file2.h file2.h中で"dir3/file3.h" → dir0/dir3/file3.h
>>733 (a) #include <...>は、実装依存の一連の場所(*1)から探す。
(b) #include "..."は、まず実装依存の一連の場所(*2)から探し、その後(a)と同様にして実装依存の場所から探す。
古いCだと、(2)でまず探すのが元ソースのディレクトリになっていた。
C++でもそういう実装が多いと思うけど、決まっているわけじゃない。
ディレクトリの考え自体が実装依存だから、それ以上のことは決まっていないみたい。
>>719 今でもconst参照は左辺値を参照できるぞ、右辺値「も」参照できるというだけで。
提案では、722の言うとおり718のコードで右辺値を渡すと
const左辺値参照よりも右辺値参照を優先して解決される。
>>735 勘違いしてた。
非const参照では右辺値を参照できないと言いたかった。
vector&& otherの&が二個あるのが右辺値参照を表してると思っていいの?
初めて見る構文だから
>>736 そういうこと、&&が右辺値参照を意味する。
C++0xでもconstな左辺値参照は相変わらず右辺値を参照することも可能になっていて、
だから、既存の右辺値参照を考慮していないプログラムの互換性も保てるとされている。
>>737 なるほど
どんどん仕様は拡張されてるわけね
まだまだおいつかないわ
>>734 ありがとうございます
VC++やBorland C++ではmingwと違った感じになるか、ご存じでしょうか?
boostライブラリでは、一部は"boost/〜/〜.hpp"みたいにincludeしてることもあるようですから
国際標準で定まってなくても、デファクトなやり方があるのかなと期待しつつ。
void func(const int &v){ &v; } func(0); これって規格上通るの?
>>739 VC++、BCC、GCCなどといったパソコンで動くコンパイラだと、
734の(*1)にあたる場所は、コンパイラオプションや環境変数で指定したディレクトリで、
(*2)はソースファイルのあるディレクトリと思っていて構わない。
>>740 もちろん問題ない。
funcを呼ぶ側にとっては一時的な右辺値でも、
funcの中の人にとってはfunc内を実行している間ずっと存在し続ける左辺値(constだけど)。
>732 それによって初期化された vector が破棄されるときと、other が破棄されるときを考えてみよう。
>>742 これをint*にキャストしても規格上通る?
void func(const int &v){ const_cast<int*>(&v); } ならいいと思われる
実際に中身を書き換えなければ、constのないポインタ型へ変換したり、 そこから参照剥ししたりしても規格上問題ないはず。
747 :
デフォルトの名無しさん :2007/11/03(土) 17:51:17
char* buffer にCreateFileなどでファイルの文字列を一気に読んで それをstrtok_sで分割し、とっておきたいとします。 char* hoge = strtok_s(NULL,delim,&nexttoken); char* hage = strtok_s(NULL,delim,&nexttoken); int sage = atoi(strtok_s(NULL,delim,&nexttoken)); そして、読み込み&分割が終わった後に delete[] buffer と、後始末をすると、int sageなどはコピーされてるので消えませんが、 hoge hageに関してはポインタなので一緒に消えてしまいます。 コピーをとっておく場合はどうやって書いたらいいんでしょうか? ちなみに、 char hoge[256]; strcpy(hoge,strtok_s(NULL,delim,&nexttoken)); とか char hoge[256]; sprintf(hoge,strtok_s(NULL,delim,&nexttoken)); などとやってみたんですが、内容がフフフフの連続のようになってしまいました。 正しくはどうやって書いたらいいですか?
なぜstrtok_sは使うのにstrcpyなんだ。 strtokよりよっぽど重要だぞ。 第一それ、バッファオーバーフローするだろ。
テンプレート関数についてです。 テンプレート関数はオブジェクトファイルにする時点でテンプレートの部分が実体化(?)している必要がありますが、 もしテンプレート関数を使用するファイルを個々にオブジェクトファイルにしてから結合したい場合、 テンプレートクラスの場合は template MyClass<int>; のようにすれば解決できるようですが、テンプレート関数の場合はどのように宣言すればよいのでしょうか?
751 :
デフォルトの名無しさん :2007/11/03(土) 18:38:20
>>748 そこって本質ですか?
strtokでもらうのは最初のbufferの中でデリミタに区切られたところのポインタですよね?
当然、後片付けでbufferをdeleteしてしまえば、
そのhoge hageの指し示している先の内容も消されてしまうというのは理解できます。
一方、int sageはatoiでコピーをもらってるので消えません。
要するに文字列の「コピー」をもらいたいんですが、書き方が分かりません。
>>750 ん?同じことができるでしょ?
やってみたなら、どうやったのかとエラーメッセージをどうぞ。
753 :
747 :2007/11/03(土) 18:58:48
class Holder{ public: int kazu; char* moji; void print(){ printf("整数 = %d, 文字列 = %s \n",kazu,moji); } }; void main(){ HANDLE file = CreateFile( "test.txt",GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); DWORD size = GetFileSize(file,NULL);//ファイルサイズ char* buffer = new char[size+1]; buffer[size]='\0'; DWORD read_size;//バッファに一気読み ReadFile(file, buffer, size, &read_size, NULL); CloseHandle(file);//ファイルクローズ char delim[] = ","; char *nexttoken; Holder holder; holder.kazu = atoi(strtok_s(buffer,delim,&nexttoken)); holder.moji = (strtok_s(NULL,delim,&nexttoken)); delete[] buffer;//←deleteしなければうまく動く holder.print(); }
>>751 strtokが失敗しているんじゃないか?
C++の質問でも回答でもないけど
自分で答えは分かってるじゃない delete[] buffer;//←deleteしなければうまく動く holder.print() が参照する先が有効でないといけないだけ
char *s = strtok_s(NULL,delim,&nexttoken); header.moji = new char[strlen(s) + 1]; strcpy(header.moji, s); delete[] buffer; holder.print(); delete[] holder.moji; }
>>750 明示的特殊化の話?
それともexportの話?
758 :
デフォルトの名無しさん :2007/11/03(土) 19:08:13
>>755 はい。ですから参照する先を取っておくんじゃなくて
内容をコピーしておくにはどうしたらいいんでしょうか。
>>758 初心者スレに帰ってください。おねがいですから。
>>758 必要な文字数を計算した後、strncpy。
\0が無いのでstrcpyは駄目。
761 :
デフォルトの名無しさん :2007/11/03(土) 19:21:35
>>756 できたみたいです。ありがとうございました。
>>759 死ね役立たず。
人の足引っ張って楽しいかゴミクズ。
今すぐ死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。v死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
マルチな上にスレ違いの質問で粘ったあげく、これかよ
まぁ、あれだ。平和になってよかったじゃないか。
764 :
デフォルトの名無しさん :2007/11/03(土) 19:24:54
>>761 死ね役立たず。
人の足引っ張って楽しいかゴミクズ。
今すぐ死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。v死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
765 :
750 :2007/11/03(土) 19:25:04
>>752 >>757 exportの方です。
そもそも、宣言の仕方がはっきりと分からないのですが。。
ヘッダと.ccファイルを別けているので、.ccファイル内で
template (返り値) (クラス名)::(テンプレート関数名)<(テンプレートに適応したい型)>;
でいいのでしょうか?
template Gtk::SpinButton* PController::newParameter<double>;
>>765 export 関係あるか?
関数テンプレートの明示的特殊化なら引数リストも書かないと駄目だと思うよ。
あと、「いいのでしょうか?」って聞く前に自分で試してほしい。
767 :
766 :2007/11/03(土) 19:28:58
明示的特殊化じゃなくて明示的実体化だね。ごめん。
exportってテンプレートの定義をヘッダーではなくソースに書く方式だけど ヘッダー //sample.h template<class T> int func(T a); ソース //sample.cpp #include "sample.h" export template<class T> int func(T a) { //定義 } 利用するソース #include "sample.h" void widget() { //fを呼び出す処理など } てな感じになるんでは?
769 :
デフォルトの名無しさん :2007/11/03(土) 19:43:34
>>762 マルチ?ちゃんと断ってるだろ。
しかもスレ違いってC++はCも含むだろ。
シネよ基地外。
>>765 メンバ関数のことかな?
template <class T> Widget { };
template class Widget<int> //クラステンプレートの明示的具現化の宣言
template void Widget<int>::f(int); //メンバ関数A<T>::f()の明示的具現化の宣言
みたいになるかな
template (返り値) (クラス名)::(テンプレート関数名)(パラメータリスト);
かな
あと、関数テンプレートの場合、引数演繹に頼らないで明示的に
パラメータの型を指定するのは呼び出し時じゃね?
771 :
770 :2007/11/03(土) 19:52:37
以下訂正 //メンバ関数A<T>::f()の明示的具現化の宣言 × //メンバ関数Widget<T>::f()の明示的具現化の宣言 ○
772 :
デフォルトの名無しさん :2007/11/03(土) 19:52:59
含むというのはスーパーセットのことですか^^;
>>769 だったらCのスレなんかいらないだろカス
774 :
デフォルトの名無しさん :2007/11/03(土) 20:21:36
>>773 Cのスレで「C++にしか含まれない」文法の質問をしたら
スレ違いというのは妥当だが
C++のスレで「Cにも含まれる」文法の質問したからって
スレ違いってことはないだろうよ。
>>773 C使いのC限定の質問にC++で返答するわけにはいかんだろ。
よってCスレは必要。カスはお前な。
776 :
750 :2007/11/03(土) 20:47:19
>768
GCCのg++はexportに対応していないようなので使えませんでした。
>>766 聞き方が良くなかったようです。。
聞く前には当然自分で試行錯誤しています。実は今日一日中試行錯誤しています。。
>>770 クラスは普通のクラスだったので、
template void MyClass::method( double* );
のようにしたらエラーなくオブジェクトファイルが出来ました。
最終的に、
>>770 でいわれた通りの宣言で明示的実体化したら、
オブジェクトファイル内に実体化されたテンプレート関数が作成されていました。( nm -C で確認 )
何とかこの問題は乗りきれそうです。みなさんありがとうございました。
777 :
デフォルトの名無しさん :2007/11/03(土) 20:53:38
流れ読まずに言うけどさ
>>775 はC++をつかっているが、Cの範囲の質問したんだろ?
じゃあそれはCの質問でCスレいってこいやカスが
779 :
デフォルトの名無しさん :2007/11/03(土) 21:27:10
>>777 >>774 を100回くらい声だして読んだら。
>>778 全部お前の勝手な匙加減じゃねーかw
C++はCの文法を含む。事実はこれだけ。
CスレでC++の質問をするのは無理があるが
C++スレで”Cにも”含まれる文法の質問をしたところで問題はない。
まだやってんのかよ
781 :
デフォルトの名無しさん :2007/11/03(土) 21:34:20
>>777 みたいなアホが
勝手な自分ルールを押し付けてそれが一般化したら迷惑だからな。
言うことはきちんと言っておかんと。
たまに自分の答えられない質問が出てくると 意味不明な論拠で必死にその質問にいちゃもんつけて排除しようとする回答者っているよな。 自分のプライドを傷つけられたと思うのかなんなのか。
783 :
777 :2007/11/03(土) 22:05:14
ごめんよ 俺が悪かったよ だから議論おわってくらさい><
だが断る
>>782 まぁ、確かに「たまに」そういう回答者も現れるけど、
残りの大部分は馬鹿な質問者が逆ギレしてるだけのケースで、
今回も後者のパターンだよ。
786 :
デフォルトの名無しさん :2007/11/03(土) 22:58:49
>>785 逆ギレの意味くらい理解してから使えよ。
787 :
デフォルトの名無しさん :2007/11/04(日) 00:33:50
そうだな、回答者が一方的に発狂してるだけだもんな
788 :
デフォルトの名無しさん :2007/11/04(日) 02:15:04
わざわざ利用者のほうでスレの使い分けしている意味を台無しにしようとがんばっている池沼がいるようなので記念カキコ
789 :
デフォルトの名無しさん :2007/11/04(日) 02:57:31
能無し回答者(いや回答できないから正確には回答者じゃないや、自称回答者かw)が 頭の出来の悪さをズバリ指摘されて発狂しまくり、超ウケるwww
もう触っちゃだめですよ。
ageてる奴は同一人物
問題ない派: 文法的観点 「strtok()はC++でも使えるでしょう><」 スレ違い派: 流儀的観点 「strtok()なんてC++では使いません><」
もう触るなっての
boost::stringtokでも使えww
とりあえず777から794まであぼーんしますた
そう、能無しのアホにとっては自分に都合の悪いレスはあぼーんするしかない
>>792 いや使うだろ?
つうか使ってるんだが。
じゃあ何使うんだ?
普通に聞きたい。
string で find_first_of() と substr() のループ、かな?
strtokのほうが楽じゃん
でも引数に副作用が出るのがキモイし、スレッド安全性とかも問題になることがあるだろう。
つ boost::tokenizer つ boost::spirit つ std::stringstream つ std::getline
regexとxpressiveもな
803 :
792 :2007/11/04(日) 12:24:16
俺の場合は
>>801-802 辺りで解決する。
まあ、俺が言いたかったのは、C++使いって
better C な使い方する人とか
Cっぽい書き方毛嫌いする人とか (←俺はココ)
どっちの書き方もする雑食な人とか
色々いるよねってことなんだ。strtok()自体がどうこうじゃなくて。
継承元の親クラスの引数付きのコンストラクタと同じ機能を子クラスにも実装したいとき、 子クラスでも同じようにコンストラクタを実装・宣言しなければいけませんか? class BASE { int num public: BASE(int) } BASE::BASE(int a) { num=a; } class SUB : public BASE { int num; //←これを省略したい public: SUB(int) //←これを省略したい } SUB::SUB(int b) //←これを省略したい { num=b; }
そのソースだとコンパイル通らんだろ。 class SUB : public BASE { public: SUB(int); } SUB::SUB(int b) :BASE(b) { } 省略は無理。
>>805 あれ?似たようなプログラムではなぜか通りました。ただし、親クラスの変数宣言の部分はprotected:に変えて、子クラスの変数宣言部は削除しました。。
>SUB::SUB(int b)
> :BASE(b)
こうすればよかったわけですね。
非常に助かりました。
ありがとうございましたm(_ _)m
>>806 デフォルト引数を使って基底クラスのデフォルトコンストラクタ呼び出しにすれば
派生クラスの初期化リストから省略できる
class BASE
{
int num;
public:
BASE(int = 0);
};
BASE::BASE(int a)
{
num=a;
}
class SUB : public BASE
{
public:
};
>>807 ありがとうございます。
その場合、
SUB element(10); //numには10がセットされる
という初期化はできず、
SUB elemetnt; //numには0がセットされる
という使用方法のみになりますか?
なるね
>>809 了解です。
アドバイスありがとうございました.
template<typename T> void templateFunc(int a){} template<typename T, typename U> struct templateClass{ templateClass(){ struct D{ T first; U second; }; templateFunc<D>(0); } }; void test(){ templateClass<int, int> tc; } これがVC++2005ではコンパイル成功するんですけど Fedora7付属のg++ 4.1.2だと test.cpp: In constructor ‘templateClass<T, U>::templateClass() [with T = int, U = int]’: test.cpp:17: instantiated from here test.cpp:12: error: no matching function for call to ‘templateFunc(int)’ とエラーになってしまいます。struct Dを関数内じゃなくてtemplateClass内に移動すると、コンパイルは通ります。 これは何が間違ってるのでしょうか? (g++4.2を試そうとしたんですがうまくインストールできませんでした。)
14.3.1 Template type arguments 2 A type without linkage (3.5) shall not be used as a template-argument for a template type-parameter. [ Example: template <class T> class X { /* ... */ }; void f() { struct S { /* ... */ }; X<S> x3; // error: local type used as template-argument X<S*> x4; // error: pointer to local type used as template-argument } -- end example ] [ Note: a template type argument may be an incomplete type (3.9). -- end note ]
>>811 それはVC++2005が間違っています
関数スコープ内で定義されたクラスはテンプレートの引数としては使用できません
次の標準では可能になるように提案は出ていますが
いまはg++の挙動が正しいです
814 :
811 :2007/11/04(日) 16:27:45
>>812-813 あー、そうでしたか
g++のエラーメッセージもうちょっと分かりやすいと助かるんですけどねー
>>813 横やり質問ですみませんが、具体的にコードのどの部分が文法違反でしょうか?
void test(){
templateClass<int, int> tc;
}
はOKじゃないんですか?
>templateFunc<D>(0); ここがだめ ローカルな型をテンプレート引数に使おうとしている
>>816 なるほど、リンケージを持たない型はダメってことですね
例えば
struct Widget { }; //構造体スコープにないのでローカルな型ではない
template<typename T, typename U>
struct templateClass{
templateClass(){
struct D{
T first;
U second;
};
templateFunc<Widget>(0); //変更
}
};
とかなら文法的にOKということですね。
>>817 死ね役立たず。
人の足引っ張って楽しいかゴミクズ。
今すぐ死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。v死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。死ね。
?
??
????
????????
????????????????
????????????????????????????????
????????????????????????????????????????????????????????????????
化けてんじゃねーか ちゃんと文字コード意識汁!
?
>>818 に隠されたメッセージを解読したぞ!
まずは「v死ね。」。これはVシネを表すと考えられる。
そして「ね。」。つまり「死がない」。
つまり!
>>818 は、しがないVシネマニアなんだよ!なんだってー!おめがおめが!おめが!
だめだコレつまんねえな。一応書き込みしとくけど。
流れぶった切って質問です。 クラス内クラスって、そのクラスの属するクラスへのアクセスってどうなるの? privateにもアクセスできるのは正解? VC8だとこんなのも通ったんだけど…… class test { std::string test_; public: struct test2 { void operator()(test& value) { std::cout << value.test_ << std::endl; }; }; public: test(std::string const& value) : test_(value) {}; }; int main() { test t("test"); test::test2 t2; t2(t); };
>>830 どう考えても正解だろ
アクセス指定子ってクラス外部に対する指定なんだぜ?
struct A { struct B { private: int i; }; struct C { int func(B& b) { return b.i; } }; }; クラス内クラス同士のアクセスってどうだったっけ? このへん曖昧で、いつかちゃんと理解しとこうと思ってるんだけど。
どうもこうも プライベートとパブリックの考え方そのまんまだろ 現実と対して変わらん。 我が家のプライベートな所有物には俺も兄貴も弟もアクセスできる。 でも兄貴のプライベートを俺がアクセスすることはできない。
フレンドシップの考え方とか プライバシー・パブリシティの考え方とか ちょっと欧米的だよな、クラスって
そーいやC++98とC++03の違いを良く知らないことに気が付いた。 まあいいか、C++09で全部覚えなおせば
837 :
830 :2007/11/04(日) 23:13:20
そうだったのか……ありがとう。 C++STD 9.7.1 The nested class is in the scope of its enclosing class. つうことね。
確かその辺、bcc5.5.1と5.6.4で挙動が違ったの覚えてる
839 :
830 :2007/11/04(日) 23:15:41
サンクス >835 1998とごっちゃになっていたのか…… >836 C++0x準拠の実装が出て来るの、いつになるのかね?
>832 それはNGだと思う。 namespaceスコープと同じ挙動になるんじゃない?
自分は14882:2003を持ってるけど
class E {
int x;
class B { };
class I {
B b; // error: E::B is private
int y;
void f(E* p, int i)
{
p->x = i; // error: E::x is private
}
};
int g(I* p)
{
return p->y; // error: I::y is private
}
};
こうなってる。つまり
>>830 はNG
見辛くてごめん
842 :
835 :2007/11/04(日) 23:54:13
>>841 あれ?
ごめん。 2003 の改定には間に合ってなかったみたい。
>841 サンクス。11.8.1ですな。VC++8.0は間違いですな。 取り囲んでいるクラスにfriend追加しとくか。
844 :
デフォルトの名無しさん :2007/11/05(月) 00:43:36
#include <iostream> namespace hoge { template<class T> struct base { template<class R> base& operator|(base<R>& r) { std::cout << "base::operator" << std::endl; return *this; } }; struct tinko_type : base<tinko_type> {} tinko; struct manko_type : base<manko_type> {} manko; template<class L, class R> base<L>& operator|(base<L>& l, base<R>& r) { std::cout << "hoge::operator |" << std::endl; return l; } } // namespace hoge template<class L, class R> L& operator|(L& l, R& r) { std::cout << "::operator |" << std::endl; return l; } int main(int ac, char** av) { hoge::tinko | hoge::manko; return 0; } 以上のプログラムのコンパイルには成功したのですが、実行結果に納得がいきません 漏れとしては hoge::base::operator| もしくは hoge::operator| が呼び出されると思ってたですよ そしたら ::operator | が呼び出されてるですよ いったい禿はなにを考えてるですか????? VC++2005EEとg++3.4.4(cygwin)で確認しました
845 :
デフォルトの名無しさん :2007/11/05(月) 01:09:54
「BBS が止まっています」…(+ФyФ)?そうですか…
>>844 厳密なルールは確認してないけど、派生クラスから基底クラスへの変換が要る
hoge::base::operator| や hoge::operator| よりも、まったく変換の要らない ::operator | が
優先されるのはそんなにおかしなことじゃないと思う。
うろ覚えだが、たしか普通のLookupができなかった場合だけ、 Koenig Lookup、もといADLが行われるんじゃなかったかな。 しかも修飾してると働かないとかいうルールもあった気がする。
void F( string & ){} を F( string( "test" ) ); // fail string s( "test" ); F( s ); // OK なぜ?
コンパイルエラーくらい見ればいいのに。
>>848 void F( string ){} か void F( const string & ){} にすれば大丈夫
一時オブジェクトを非const参照には渡せない
非const参照は左辺値で初期化しなければいけない
>>849 これって、わかりにくいエラーメッセージが出てもおかしくない気がする。
でも、この程度でそんなことは免罪符にならないけどな。
class C { explicit operator string() const; }; このexplicit指定が許されるようになるらしい。
(string)ってつけなきゃエラーか。 だったらtoStringでいいじゃねえか・・・
例えば、自作の文字列クラスを作る場合に、 mystr str1="abc"; mystr str2="def"; printmystr(str1+str2); // (str1+str2).print();とか実装するもの? のような使い方をしたいと思います。 演算子のオーバーロードはこんな感じになると思うのですが、 mystr& operator+(mystr& lhs,mystr& rhs) { mystr* temp=new mystr; temp.add(lhs); temp.add(rhs); return *temp; } この場合、newしたオブジェクトはどこかでdeleteされるんでしょうか?
スミマセン。temp.add じゃなくて temp->add ですね。
いいや、勝手にdeleteされたりはしない。自分でしなきゃだめ。 普通は mystr operator+(const mystr& lhs,const mystr& rhs) { mystr temp; temp.add(lhs); temp.add(rhs); return temp; } のようにする。
860 :
857 :2007/11/06(火) 14:26:37
>>859 それだと関数抜けた瞬間にtempのデストラクタが働いて、
呼び出し元で、
str3=str1+str2とか、
printmystr(str1+str2)とかができなくならないですか?
mystr のコピーコンストラクタが正しく書かれていれば、ならない。 temp のデストラクタが動く前にコピーコンストラクタが起動して、operator+の呼び出し元にtempがコピーされる。
862 :
857 :2007/11/06(火) 14:53:05
>>861 あ、そういう風になってるんですね。
謎が解決しました。ありがとうございます。
863 :
857 :2007/11/06(火) 15:25:30
何度もスミマセン。 上記の場合だとstr1、str2にそれぞれ1万文字入っていたとして、 (1)str1からtempに1万文字コピー (2)str2からtempの続きに1万文字コピー(計2万文字) (3)コピーコンストラクタで呼び出し元に2万文字コピー (4)tempがデストラクタで消える となるので、 ポインタ渡しと比べて、(3)の分だけ一時メモリとコピーの時間がかかるんですよね?
いやいや、ムーブセマンティクスの出番だ。まだだけど。
return mystr(lhs.add(rhs)); とか出来るんだっけ?
二項+の戻り値は参照にスンなボケ、といってたのは、 Effective C++だっけ?moreの方だっけ?
無印Effectiveの方だね。 mystr str = str1 + str2 + st3 + str4; なんかだとコピーコンストラクタの呼び出し(=全文字列のコピー)が何度も呼ばれることになる。 mystr str = str1; str.add(str2); str.add(str3); str.add(str4); の方が無駄なコピーが発生せずに同じ結果が得られる。 +で繋げるのは直感的でわかりやすいんだけど、 いっそのことoperator+等の二項演算子は実装しない方がいいかと。
>>868 つexpression template
先ずは測定せよ。話はそれからだ。
872 :
デフォルトの名無しさん :2007/11/06(火) 23:19:44
VC++EEなのですがstaticでconstなiとかjがないことされちゃいます>< (でもoperator<<には渡せる・・・ #include <string> #include <iostream> struct hoge { template<class T> hoge(const T) {} }; struct hage { }; static const int i = 1; struct poge { static const int j = 2; static const hoge h1(i); // error C2061: 構文エラー : 識別子 'i' static const hoge h2(j); // error C2061: 構文エラー : 識別子 'j' static const hoge h3(hage()); }; int main(int ac, char** av) { std::cout << i << std::endl; std::cout << poge::j << std::endl; poge pooo; return 0; }
> static const hoge h1(i); // error C2061: 構文エラー : 識別子 'i' > static const hoge h2(j); // error C2061: 構文エラー : 識別子 'j' > static const hoge h3(hage()); これはいったいどういう動作を期待しているんだ? ちょっと説明してもらえまいか
874 :
872 :2007/11/06(火) 23:41:57
hogeのコンストラクタが引数の型をintとかhageとかで呼び出されることを期待しています
>>872 > static const hoge h1(i); // error C2061: 構文エラー : 識別子 'i'
> static const hoge h2(j); // error C2061: 構文エラー : 識別子 'j'
これは多分 hoge 型の変数の宣言、定義を意図しているんだろうけど
コンパイラからは戻り値の型が const hoge で static なメンバ関数の
宣言に見えている
エラーメッセージにはそんなこと書いてなかった?
876 :
872 :2007/11/06(火) 23:53:17
あー なるほど static const hoge h1(int(i)); static const hoge h1(int(j)); にしたらコンパイルできました エラーメッセージはコメントのだけでした ありがとうございます
ディレクトリを作成する関数はありますか?
APIにはあるがC++標準にはない。
基底クラスBaseと派生クラスDerive1,Derive2,Derive3,... があったとして派生クラスのポインタ(関数ポインタのように)を取得して Base* ClassTable[] = {Derive1のポインタ,Derive2のポインタ,...}; Base* p = new ClassTable[0](); というようなことをしたいのですが もし可能ならどうしたらいいでしょうか
関数ポインタでいいじゃん Base *createDerive1() { return new Derive1(); } Base *createDerive2() { return new Derive2(); } ... Base *(*classTable[])() = { createDerive1, createDerive2, ... }; Base *p = classTable[0]();
>>872-876 クラスの static メンバ変数宣言は、整数型に限って = で初期化子をつけることが
できるだけ。普通に初期化できる変数定義とは違う。クラス型を初期化することは
できなくて、当然コンストラクタも使えない。
>>875 メンバ関数の宣言ならカッコ内は型付の引数リストじゃないといけない。
そうじゃないからコンパイルエラーになってる。
>>876 その変更を加えると、 int(i) が int 型で仮引数名 i の引数になる(余計な
括弧は無視される)ので static なメンバ関数の宣言とみなされてコンパイルが通る。
h3 が最初からコンパイルできてるのもこの理由。
それだと 派生クラスを追加するたびに createDeriveXをつくり classTableにそれを登録しないといけませんよね 追加する際の作業をなるべく減らしたかったのですが 構造体やクラス自身のポインタはやはり得られないようですね 例示いただいたものを踏まえつつ別の案を考えてみます どうもありがとうございました
>>879 なんか似たような話をこないだ見たような気がするが。
template<typename T>
Base* new_as_Base() { return new T; }
Base* (*(ClassTable[]))() = {&new_as_Base<Derived1>, &new_as_Base<Derived2>};
Base* p = ClassTable[1]();
こういう時に、テンプレートって便利だな、と思う
modern C++ designでもっと強力なのを見た気がする
>>881 int(i) が int 型で仮引数名 i の引数になる
へぇーそうなんだ 知らなかった 文法エラーではないの?
>(余計な括弧は無視される) と書いてあるだろう
>>887 キャストにも見えるんだけど、関数の仮引数のところでは無視されるってこと?
>>887 余計な括弧が無視されたら inti になってしまうよ
>>889 仮引数の括弧は無視されるみたい
Effective STLかな?の最も奇妙な解析で見た
メイヤーズ先生も知らなかったらしい
>>890 return(0) は return0 にならないよね
>>891 その本持ってるので見てみる まだ読んでないんだ
>>892 たしかに
ということは仮引数にint(i)とあった場合、括弧が無視された結果
は int i と解釈されるということだね
BCCで確認した。勉強になりました。
>>892 そりゃreturn(ってトークンがないからな
だから字句解析時にreturnと(ってなる
/ニYニヽ /( ゚ )( ゚ )ヽ /::::⌒`´⌒::::\ でっていうwwwwwwww | ,-)___(-、| | l |-┬-| l | \ `ー'´ /
> Base* (*(ClassTable[]))() = { これは、また・・・
int i = 0; int *pi = &i; *pi; //これって式(expression??)?
値が出てくるし、式じゃなかろうか
セミコロンが付いてたら文だろう
*pi が式。 *pi; が文。
継承とstatic変数について質問です。 class Base { static int x; }; class C : public Base {} class D : public Base {} とすると、変数Base::xは派生したすべてのクラスから共通の実体が参照されます。 このとき、派生クラスごとに独立のstatic変数を与えたいのですが、 そのようなことを行う方法はありますでしょうか?
>>902 派生クラスごとにstatic変数を定義する
CRTP
>>904 ありがとうございます。
テンプレートでクラスごとに実体化するのはなかなかよさそうだったので、これでいってみます。
906 :
デフォルトの名無しさん :2007/11/08(木) 22:02:59
最近C++はじめたのだが。 あるオブジェクトをリスト管理しようとしてます。んで、そのオブジェクトは 別のオブジェクトが参照しているバッファ領域みたいなのを保持してる。 だから、そのバッファ領域のアドレスは変えたくない。 STLって、コピー前提のつくりだから、結局Cで使ってたリスト操作ライブラリ 引っ張ってきて使ってる。だっせえなあ、とか思いながら。 なんかいい方法ない?
>>906 std::vectorならcapacityを超えない限りアドレス変更されない
std::listならそれぞれのオブジェクトのアドレスは変更されない
オブジェクトを指すポインタをSTLコンテナに入れればいい。 もちろん、shared_ptrか何かを併用。
909 :
デフォルトの名無しさん :2007/11/08(木) 22:43:03
LNK2001: 外部シンボル ""public: virtual void __thiscall CWnd::DoDataExchange(class CDataExchange *)" (?DoDataExchange@CWnd@@UAEXPAVCDataExchange@@@Z)" は未解決です。 Visual Studio 2005でMFCのアプリケーションをコンパイルすると 上のようなエラーがいっぱいでるのです。 これはどうやって回避すればいいのでしょうか?
スレ違いだろ。Visual C++スレ行き
912 :
デフォルトの名無しさん :2007/11/08(木) 22:59:14
>>907 ウソウツ。
0x22ee94
0x22ee94
0x22ee94
0x4f0680
0x4f0690
0x4f06a0
void
insert()
{
int i = 0;
cout << &i << endl;
mylist.push_back(i);
}
int
main()
{
insert();
insert();
insert();
list<int>::iterator itr;
for (itr = mylist.begin(); itr != mylist.end(); itr++) {
cout << &*itr << endl;
}
return 0;
}
913 :
デフォルトの名無しさん :2007/11/08(木) 23:02:10
>>912 、、、、なにしてんの? もしかして検証してるつもり?
915 :
デフォルトの名無しさん :2007/11/09(金) 00:51:00
>>914 検証もクソも、STLのソースがメモリ確保して、コピーしてんだよ。
だから、auto変数を登録してもメモリ確保して、コピーされてんだよ。
チネ
なにをとんちんかんな事を
917 :
デフォルトの名無しさん :2007/11/09(金) 01:00:54
>>916 なんも知らないなら、ハジメカラソウイエヨ
>>915 お前が何を検証したいのか良く分からん。
>だから、auto変数を登録してもメモリ確保して、コピーされてんだよ。
auto変数の登録って何だ?
mylist.push_back(i) は i の値をvectorに追加してるんだろう。
iの値を入れた器のアドレスと、i自身のアドレスが異なるのは当たり前だ。
もしかしてauto変数のアドレスを取得して登録でもしたいのか。
まさか、そんなことをしたいと考えるとは思えないが。
補足。 「iの値を入れた器」はvector上でiの値を入れた器のこと。
920 :
デフォルトの名無しさん :2007/11/09(金) 01:15:45
>>918 。。。。。。。。。。。。。。。。。
vectorに追加してるわけじゃないし、vectorだったら
n番目の要素のアドレスが、&myvector[n]と一致していることは、
保証されている。まずはそんくらいしっとけ、
STLがcopy-in/copy-outであることと、内部バッファの拡充に伴う要素の移動とがごっちゃになってると思うんだ。
copy-in/copy-outであることが問題になるなら
>>908 のようにポインタでも格納しとけばいいと思う。
>>912 で両者のアドレスが一致するようなことがあったら、それこそ病的な挙動だろ
922 :
デフォルトの名無しさん :2007/11/09(金) 01:31:38
>>921 >
>>912 で両者のアドレスが一致するようなことがあったら、それこそ病的な挙動だろ
当たり前のことを理解できない、
>>918 がいるから説明してるわけで。
923 :
デフォルトの名無しさん :2007/11/09(金) 01:33:39
本題とはそれたが、本題は >std::listならそれぞれのオブジェクトのアドレスは変更されない これが、ウソダッテコトダケダ
>>923 「それぞれのオブジェクト」は「リスト内の要素」を指してたと思うんだ。
ここは激しく議論のすれ違っているインターネッツですね お互いに問題にしていることが違っているまま議論したら食い違って当たり前だろう
>>918 はlistとvectorを勘違いしてるけど、それ以外は妥当だろう。
>>923 が
>std::listならそれぞれのオブジェクトのアドレスは変更されない
の意味を勘違いしているだけのように見える。
>>921 の後半にだけ反応しているけど、最初の2行はちゃんと読んだの?
927 :
デフォルトの名無しさん :2007/11/09(金) 01:48:45
>>924 だから、リストに渡した要素をそのまま保持したりはしないんだって。
リストに渡した要素は、コピーが生成されてリストに保持される。
だからリスト内の要素のアドレスは、とうぜん渡したオブジェクトの
アドレスとは*異なる*。んで、本来は検証もクソもないんだわ。
ソースがそうなってるから。
突っ込もうと思ったけどやめた
929 :
デフォルトの名無しさん :2007/11/09(金) 02:04:19
次スレは今建ってるやつで決まり?なんかテンプレがいろいろ抜けてるみたいだけど。
>>924 おれもそう思う
listの場合追加、削除しても他の要素の反復子に影響はないから
次スレいくらなんでも早すぎでしょう なんらかの悪意があるんじゃないのか
933 :
デフォルトの名無しさん :2007/11/09(金) 20:02:09
なあ、C++最近はじめたのだが、STLなどの標準ライブラリの リファレンスってどこで見れるの?書籍でもWebでもよいのだけど。 「C++標準ライブラリチュートリアル&リファレンス (単行本) 」 がよさそうかなと思ったけど、絶版本で29,800円とかプレミアム ついてるし。
マクソのVisual Studio .NETタダ版を取ってくればSTLのマニュアルが見られる(英語)
MSDNライブラリをダウンロードしたりオンラインで見たりとか。 あとは検索性が難だが、JIS X 3014がJISCのWebサイトから見れる。
939 :
デフォルトの名無しさん :2007/11/09(金) 22:56:01
なあ、下のクラスを-Wall -W -Weffc++でコンパイルすると、 なんかうるさい警告が山ほど出るけど、なんでだろ? /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/allocator.h: In instantiation of `std::allocator<MyClass*>': /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:79: instantiated from `std::_Vector_base<MyClass*, std::allocator<MyClass*> >::_Vector_impl' /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:110: instantiated from `std::_Vector_base<MyClass*, std::allocator<MyClass*> >' /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:142: instantiated from `std::vector<MyClass*, std::allocator<MyClass*> >' main.cpp:52: instantiated from here class MyClass { public: MyClass() {}; virtual ~MyClass() {}; }; vector<MyClass*> myvec; int main() { MyClass *p; p = new MyClass(); myvec.push_back(p); return 0; }
940 :
デフォルトの名無しさん :2007/11/09(金) 23:18:00
スレチガイだったかもシレンが。。。 上記の警告を-Weffec++有効にしたままで抑制する方法ってあるんかな。
よくわからないけど、STLはEffectiveC++スタイルでコーディングされていないってことなんじゃないの?
942 :
912 :2007/11/09(金) 23:53:17
>>915 >>907 は確かに言葉が足りないと思うが、
安価先のレスを読めば意図を理解できるだろう。
それに比べて君は、君が馬鹿にしている
>>906 より言葉が足りない。
もう少し、人のいわんとすることを理解しようとする努力と、
人に伝えるための努力が必要だろう。
まぁ、お前こそとっととチネがほんねだけれども。
>>940 システムヘッダファイルからは警告を出さない、っていうオプションがあったような気がする
945 :
デフォルトの名無しさん :2007/11/10(土) 19:41:45
#include <iostream>
template< int N >
class class1
{
public:
void print()
{
std::cout<<"test"<<std::endl;
}
};
template< int N >
class class2 :class1<N>
{
};
int main()
{
class2<42> obj;
obj.print(); //ここでコンパイルエラー
return 0;
}
'class1<42>::print()' はアクセスできないとコンパイラに怒られます。
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19 と似たようなエラーであることは分かったので、
obj.class1<42>::print();とか
(class1<42>)(&obj)->print();とか試してみましたが、やはり怒られます。
どう解決すればよいのか教えていただければ幸いです。
>>945 あなたが必要なのは
メンバ変数ですか?
それともテンプレートですか?
>>946 すみません、そうでした。
しばらくjavaしかやってなかったものですっかりpublic継承忘れてました。
>>947 一応テンプレートです。
void data_get(void** data); こんなCの関数があって、これは俺が作ったものではないので変更できません。 typedef struct foo{ int a; }foo; こんな構造体があって、Cなら foo *f; data_get(&f); こんな風に使います。 C++で今までVisual C++ 2005 で開発してこの関数を使うとき foo* f; data_get(reinterpret_cast<void**>(&f)); とやっていて、動作も特に問題が無かったのですが、g++4.1でコンパイルしたところ warning: dereferencing type-punned pointer will break strict-aliasing rules と怒られました。 一応この警告の意味とコードが標準に準拠してないことは理解したつもりですが それでは、data_get関数をC++から安全に使うにはどのようにしたらいいでしょうか? foo* f; void** tmp = reinterpret_cast<void**>(&f); data_get(tmp); としてもも警告が出てしまいます。 void* tmp; data_get(&tmp); foo* f = reinterpret_cast<foo*>(tmp); これだと警告が出ないのですが、大丈夫でしょうか。
>>949 void* tmp;
data_get(&tmp);
foo* f = static_cast<foo*>(tmp);
の方がいいんじゃない
>>949 reinterpret_cast は良くないね。最後のやつを static_cast に変えるのが最善かな。
>>949 C++なんだから、こっちで多重定義してしまえばいい。
inline foo_data_get(foo*& data)
{
void *p;
data_get(&p);
data = static_cast<foo*>(p);
}
953 :
949 :2007/11/12(月) 00:32:02
ありがとうございます、
>>950 か
>>952 で行こうと思います。
ところで、void*からのキャストはreinterpret_castもstatic_castも同じだと思ってたんですが
違うんですか?
>>953 reinterpret_cast は実装依存。 static_cast は foo* → void* への暗黙の変換の逆変換。
どっちも同じになる実装がほとんどだろうけどね。
暗黙の変換を明示的に行うのがstatic_castだってeffective C++に書いてあった
>>955 それだけではないけどね
void* -> T* の暗黙の変換はないけど
これもstatic_castの仕事の一つ
test.cxxというファイル名だと、 __FILE__がtest.cxxになりますが、 #define test.cxx と同等のことを__FILE__を使ってできませんか?
>>957 識別氏にピリオドを含むことはできません。定義するマクロ名にマクロ展開の結果は使えません。
959 :
デフォルトの名無しさん :2007/11/12(月) 22:55:33
>>949 g++ -fno-strict-aliasing じゃだめ?
>>949 C++もCと同じだと思うけど、
汎用(void)のポインタへのポインタ型というのは規格上ないはず。
void func(void **);
int *p;
func((void **)&p);
こういうコードは移植性がなく動作は未定義。
正しくは、
void *vp = p;
f(&vp);
p = vp;
なので自分で書いてるとおりvoidポインタを介在させればよい。
foo *f;
void *tmp = f;
data_get(&tmp);
f = static_cast<foo*>(tmp);
でいいんでは?
>>960 void**という型がないわけではない。
ただ、T**――Tはvoid以外の任意の型(あー、一応関数型も除く)――
とvoid**との間の変換が定義されていないだけ。
962 :
デフォルトの名無しさん :2007/11/13(火) 03:39:21
グローバル変数の定義順序について質問させてください。 --- values.cpp --- int values[] = { 5, 1, 2, 4, ... }; --- values.h --- extern int values[]; --- table.cpp --- #include "values.h" int table[] = { values[0], values[1], values[2], ... }; こんな風に、異なる翻訳単位に2つのグローバル変数 values[] と table[] があって、table[] の初期化が values[] に 依存しているときに、コンパイラはこの依存関係(?)をちゃんと 検出してグローバル変数の定義順序を決めてくれるもんなんでしょうか? 詳しい方おられましたら、よろしくお願いします。
定義した順に初期化される。 table.cppは int table[]... の前に extern int values[]; を展開する。
964 :
962 :2007/11/13(火) 03:44:24
すみません、このサンプルで御願いします…。 --- values.cpp --- int values[] = { 5, 1, 2, 4, ... }; int get_value(int i) { return values[i]; } --- values.h --- int get_value(int); --- table.cpp --- #include "values.h" int table[] = { get_values(0), get_values(1), get_value(2), ... };
x定義した順に初期化される。 o宣言した順に
自分でコンパイルしろよカス
967 :
デフォルトの名無しさん :2007/11/13(火) 03:59:33
宣言した順ということは、どちらの翻訳単位が先に翻訳されるか によって変わるということでしょうか。 手元のコンパイラ BorlandC++BuilderX でどちらも試してみましたが、 警告もエラーもなく期待通りに初期化されるようなので、良く分かりません。 table[] の初期化が values[] の初期化より先に行われるようなコンパイラが あるとすれば、問題が起こるかもと思ったのですが。
>>964 その場合 values は定数式で初期化されているので静的初期化になります。
table は定数式じゃないので動的初期化になります。非ローカルオブジェクトの
初期化は静的初期化が先で動的初期化が後なので、その例だと問題は起こり
ません。
静的初期化には特に順番というものがありません。動的初期化については
同じ翻訳単位内での順番は定義順と決まっていますが、翻訳単位をまたぐと
順番が定まらなくなりますので、その場合に問題が起こる可能性があります。
969 :
949 :2007/11/13(火) 08:20:18
>>959 それやったら負けかなと思ってる。
「最適化しても良い」って決まりですし。
>>960-961 ふむふむ、
そういえなvoid**はvoid*とは違って全然汎用ではないですね
>>969 そりゃそうだ、void **はvoid *へのポインタに過ぎない。
>>966 実行速度を計測するのと違って、自分の環境でたまたまうまくいけば
それで疑問が晴れる、というものではないから、それは見当違いの反応だよ。
>>961 >>969 汎用(void)はおかしかった。void**がないわけではなく
”汎用として使えるポインタへのポインタ型はない”
と言いたかった。ここでいう汎用とはあるT型から
の変換とT型への変換ができるということ。
(不完全型へのポインタなので変換できない)
詳しくはCプログラミングFAQ
973 :
デフォルトの名無しさん :2007/11/13(火) 10:25:43
教えてください。 void *vp; があったとして *vpのようにデリファレンスすることはできませんが void** vpp; があったとして、これを*vppのようにデリファレンスするのはOK ですよね?(*vppはただのポインタで結果はvoid*となるので)
974 :
973 :2007/11/13(火) 10:27:03
訂正 (*vppはただのポインタで結果はvoid*となるので) × (vppはただのポインタで*vppの結果はvoid*となるので) ○
975 :
973 :2007/11/13(火) 10:40:19
念のため確認させて欲しいのですが void MyMemoryAlloc(void **vpp, size_t n) { . . 詳細は省略 . *vpp = malloc(n * sizeof(T)); //確保したメモリへのポインタ } T *p; void *vp = p; MyMemoryAlloc(&vp, 10); p = vp; というのはOKですよね?というかよくありますよね?
>>973 おk
だけど
>>975 T *p;
MyMemoryAlloc(&p, 10);
これでよくね?
ただし、TがPOD型のみ有効。
is_podは現行のC++ではあまり使えないらしいし怖いのぅ
978 :
973 :2007/11/13(火) 11:45:20
>>976 ご説明ありがとうございます。
T *p;
MyMemoryAlloc(&p, 10);
としてしまうと、
>>961 さんご指摘のように
T** から void**への暗黙の変換が
できないですよね?
(POD型というのが分からなかったのですが。)
>>968 ありがとうございます。勉強になりました。
>>962 のサンプルの場合も、table[] の初期化子 (values[0] など)は
定数式ではない(配列の要素は const であっても定数式にならないん
でしたよね) ので、やはり values が table より先に(静的)初期化される、
と考えて良いんですね。
>>978 あまり深く考えずに、
template<typename T> T * vp_assign( T * & lhs, void * rhs){
return lhs = static_cast<T *>(rhs);
}
template<typename T> T * vpp_assign( T ** lhs, void ** rhs) {
return vp_assign(*lhs, *rhs);
}
とか作って、それを使えばいいじゃまいか
982 :
981 :2007/11/14(水) 02:37:59
盛大にアンカーミスった。 379 じゃなくて
>>979 ね。
>>975 p = vp はコンパイルできない。 static_cast が必要。
>>976 void** の引数に T** は渡せない。
>>980 意味が分からないから、たぶんやめたほうがいい。