C++に関する質問やら話題やらはこちらへどうぞ。 ただし質問の前にはFAQに一通り目を通してください。 IDE (VC++など)などの使い方の質問はその開発環境のスレに お願いします。
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
7 :
デフォルトの名無しさん :2008/01/11(金) 19:00:39
復活か?
Prototype パターンに関する質問 派生させた、インスタンスの消滅(delete)は何処でやったらいい? 基底のデスクトラクタは、Effective C++ 新訂3版、宜しく virtualで宣言してるんだけど?
C++ Primer 4/E 買った奴いる? 内容はどうだった?
>>8 俺はstd::auto_ptrに突っ込んでいるが。
>>8 です
とりあえず
std::auto_ptr
boost::shared_ptr
は、なしで宜しくオナガイシマス
同等のクラスを作れ
おもっくそ真面目に作りたきゃ Modern C++ Design でも読めばいいが、 適当でいいなら適当なソース読め。
>>Modern C++ Designは持ってるが、読破できん >>適当でいいなら適当なソース読め。 どこにある?
boostなら落としてこい。 auto_ptrならコンパイラが持ってるかも知れん。検索しろ。 開発環境書かなきゃディレクトリなんてわかるか。
>>11 std::tr1::shared_ptrという抜け穴w
Loki のやつを使うという手も
>>8 だが
LokiはModern C++ Designに載ってるライブラリだろうが
なもん判るか、ぼけ
ってゆうか、予想はしてたが、Prototype パターンで、派生させた、
インスタンスを消滅させるのって、やっかいなんだな
読めと言ってる訳じゃねー
21 :
デフォルトの名無しさん :2008/01/11(金) 21:28:03
最大50桁の数字を2つ入力して その和と積と差を求めるプログラムを作りたいんだけど、 50桁も入力できない!!! 20桁もできない どうすれば入力できますか?
>>19 べつにPrototypeに限らん。
生成パターンで生成させたオブジェクトは皆同じ。
元々JavaとかC#に向いた手法だよな。
多倍長演算でググれ
>>21 入力を文字列として読み取り、ひと桁ずつを配列に入れる。
あとはお前が筆算をやる要領でひと桁ずつ下の桁から加算する。
10を超えたら次の桁(=次の配列)に桁上げする。
単純だけど、こんなんでも一応実現できる。
>>19 >>22 へ
個人的な意見だが、ポインタ使って、ヒープにメモリ確保するのって
後始末が煩雑だから、嫌なんだよね、静的にインスタンスが、作れないものかな・・・
27 :
デフォルトの名無しさん :2008/01/11(金) 22:16:52
>>25 宿題スレ行きました
出来れば助けてください!笑
>>29 ありがとうございます!!(ノ_・。)
28 :
デフォルトの名無しさん :2008/01/11(金) 22:34:59
↑上の
29じゃなくて
>>24 のまちがいでした。。
あと、できればプログラム詳しく教えてほしいんですが(ノ_・。)
配列にいれて足していくってどうやればいいですか???
>>23 ぐぐります!!
>>28 マルチしてるのでどっちか取り下げないか?
助けてやろうにもどっちで助ければいい?
30 :
デフォルトの名無しさん :2008/01/11(金) 23:20:49
じゃあ向こうのスレでお願いします!!
31 :
デフォルトの名無しさん :2008/01/11(金) 23:23:23
マルチごめんなさい(ノ_・。)
More Effective C++ 新訂3版のテクニックという章に class NLComponent { virtual NLComponent * clone() const = 0 ; // クローンメソッド }; 基底クラスに、純仮想関数を宣言して、派生クラスでインスタンスを生成する方法が 載っているんだけど、一例で、ディスク上に保存されている、オブジェクトを std::istream strを引数にとるコンストラクタで渡してやってるんだけど これって、なんかおかしい気がする、理由は、コンストラクタで例外が起きたらどうなるんだ? どう思うよモマイラ
>>33 おいおい、自分で書いておいて却下するなよ。
VC++ 2005を使っています。 テキストファイルから文字列を読み込んでいるのですが、CStdioFileなどを使った読み込みですと、1行ずつ読み込むしかありません。 これを、1行ではなく指定の区切り文字まで読み込む、というのをやりたいのです。 具体的に言うと、「。」がくるまで読み込みをやりたいと思っています。 今日は晴れです。明日も晴れです。 という文章を読み込む場合、最初の読み込み時では 今日は晴れです。 が読み込まれ、次の読み込みで 明日も晴れです。 が読み込まれるようにしたいと考えています。 何か標準のライブラリでこのようなものはないでしょうか? よろしくお願いします。
1文字ずつ読み込んで、望みの区切り文字列が現れたところで止める。
>>35 getline(basic_istreamのメンバもグローバル関数のほうも)では、
\nに代わって区切る文字を指定できる。
ただし、元が改行文字を取り除く仕様なので、
当然指定した区切り文字は削除される。
std::wifstream is("hoge.txt");
is.imbue(std::locale("japanese"));
std::wstring s1, s2;
std::getline(is, s1, L'。');
std::getline(is, s2, L'。');
//s1 == L"今日は晴れです"
//s2 == L"明日も晴れです"
38 :
35 :2008/01/14(月) 01:58:54
>>37 どうも、ありがとうございます。それを使ってみたいと思います。
39 :
デフォルトの名無しさん :2008/01/14(月) 21:44:28
Emacs にも Visual C++ の IntelliSense のような 入力支援機能を実現する Emacs Lisp プログラムが 用意されているのでしょうか? 単純なキーワード色づけは今も使っているのですが, もっと詳細な情報を得たいと思っています.
40 :
デフォルトの名無しさん :2008/01/14(月) 23:51:44
C++及びオブジェクト指向初学者です(C++入門本一読程度) 。いくつかの クラスオブジェクト(CObjxx)を任意数包含する クラス(CTestxx)を複数生成 したいと考えています。 class CObjA {...}; // 既存クラス(修正不可) ・・・ class CObjD {...}; // 既存クラス(修正不可) class CTestA { private: CObjA m_objA; CObjB m_objB; }; class CTestB { private: CObjB m_objB; CObjC m_objC; }; ・・・ class CTestF { private: CObjA m_objA; CObjC m_objC; }; int main() { CTestA testA; ・・・ } 現在、このような実装で検討していますが、この方法だと各CTestxx毎に CObjxxに対するアクセサを 用意してあげる必要があり、かつ似たような 巨大なクラスCTestxxが出来上がってしまい、 スマートな実装ではない気が しています。。。 上記のようなケースは どのように実装するのが適切なのでしょうか。 ご教授をお願いします。
んー、それは言語系スレじゃなくてツール系スレに行くべきかな。
>>41 は
>>39 へのレス
>>40 抽象度が高すぎてなんともいえないな…。
CTestXXはラッパークラスなんかね?
それとも唯のコンテナか…エスパーに任せる。
>>40 各Obj毎のアクセサクラス作って多重継承してみたら?
class CObjAAccessors {
public: objA用アクセサ;
protected: CObjA m_objA;
};
class CObjBAccessors {
public: objB用アクセサ;
protected CObjB m_objB;
};
class CObjCAccessors {
public: objC用アクセサ;
protected: CObjC m_objC;
};
class CTestA: public CObjAAccessors, public CObjBAccessors{};
class CTestB: public CObjBAccessors, public CObjCAccessors{};
...
class CTestF: public CObjAAccessors, public CObjCAccessors{};
44 :
デフォルトの名無しさん :2008/01/15(火) 00:02:24
ある基底クラスと派生クラス群があって 格派生クラス群は固有タイプのパラメータ(intやdouble[2]とか)を持っているとする 開始関数Begin()を呼ぶ前にそれぞれ独自のパラメータを SetParameter(ParameterType[], int paramSize)で渡したい たとえば Derive1::PARAM param1[] = {3}; // int Derive2::PARAM param2[] = {0.9, 0.8}; // double[2] Derive1->SetParameter(param1, 1); Derive2->SetParameter(param2, 2); Derive1->Begin(); Derive2->Begin(); という感じ 現在これをテンプレートで実現してて (続く)
class Base{ void** param_; virtual bool Begin() = 0; public: Base() : param_(NULL){} template <class T> bool CreateParameter(T[], int); template <class T> void DeleteParameter(); template <class T> T GetParameter(int) const; }; template <class T> bool Base::CreateParameter(T param[], int n) { if(param_) return false; param_ = reinterpret_cast<void**>(new T*[n]); for(int i=0; i<n; i++) param_[i] = new T(param[i]); return true; } template <class T> void Base::DeleteParameter(){ delete[] reinterpret_cast<T**>(param_); param_ = NULL; } template <class T> T Base::GetParameter(int n) const{ return *(static_cast<T*>(param_[n])); } (続く)
47 :
40 :2008/01/15(火) 00:55:05
早々のご回答ありがとうございます。
>>42 初学ゆえ説明足らずで申し訳ありません。
CTestxxはCObjxxの機能を有するという形で実装したいと考えています。
CObjxxとCTestxxの間にラッパクラスを挟むべきか、それともよりよい
実装方法があるのか、そもそもCObjxxは包含すべきものなのか、
というところを悩んでいます。なんかうまく説明できなくてすみません。。。
>>43 なるほど。この方法だとCTestxxはCObjxxの機能を有しつつ、必要な部分だけを
公開できそうです。貴重なご意見ありがとうございます。
48 :
デフォルトの名無しさん :2008/01/15(火) 02:16:35
gccでSJISファイルのコンパイルでうまくいかないので、ご教授いただけたらと思います。 > cat a.c #include "stdio.h" #define AAA(a) BBB(#a) void BBB(char *str) { printf("%s\n", str); } int main() { AAA(あ"い"); BBB("あ\"い\""); } > gcc --input-charset=cp932 --exec-charset=cp932 a.c > a.out あ"磚 あ"い" AAAの方とBBBの方で両方同じ結果が得られそうなのですが、 AAAの方でうまくいっていないのを解決したいと思っています。 ここでは標準出力していますが、内部文字コードはSJISのまま解決したいと思っています。 よろしくお願いいたします。
49 :
デフォルトの名無しさん :2008/01/15(火) 08:34:52
>>41 >>44 THX
ちょ,名前だけでもw
といってもすれ違いの気もするから Emacs スレに行きます
>>48 --input-charsetじゃなくて-finput-charsetだった希ガス
つーかすれ違い
51 :
48 :2008/01/15(火) 23:53:54
>>50 ありがとうございます。
--input-charsetは-finput-charに展開されていたと思うので確か同じことだと思います。
GCCスレに同じ質問投げてきます。失礼しました。
52 :
デフォルトの名無しさん :2008/01/16(水) 16:52:57
下記のようにboost::arrayで代入演算子が定義されている型Tの2次元配列を で作りたいのですが、BOOST_PPとtemlateで一般化できないでしょうか? 自分でも考えたのですが脳みそが沸騰しそうでした。 struct Row : public boost::array<T, XSIZE> { Row(T x0, T x1,..., T xXSIZE_minus1) : boost::array<T, XSIZE>() {at(0) = x00; at(1) = x01;... at(XSIZE - 1) = xXSIZE_minus1; }; const boost::array<Row, YSIZE> plane = { Row(xx, xx, ... , xx), ... Row(xx, xx, ... , xx) };
53 :
52 :2008/01/16(水) 16:56:53
追記 const boost::array<Row, YSIZE> plane は手書きで初期化します。一般化したいのはRowだけです
教えてください Borland社のフリーのコンパイラを使用してるのですが #defineをmakefileでのコンパイラ時に宣言するときはどのような記述がいるのでしょうか?
57 :
デフォルトの名無しさん :2008/01/17(木) 17:56:37
さてさて初心者が通りますよ。 今日から勉強しようと今、Visual C++ 2008 Express Editionをインストール中。 ここまでOKです。
>>58 お前すごいな! VC2008をインスコしたのか
おれは、コンピラーすらインスコしてないよ
コンピラーぐらい、OSにおまけで付けて欲しいよな
最近の,NET Frameworkインストール済みなWindowsだと C#とかVB.NETのコンピラーがおまけで付いていますよ、と。
62 :
デフォルトの名無しさん :2008/01/18(金) 10:03:24
金毘羅ー
65 :
デフォルトの名無しさん :2008/01/19(土) 18:29:00
C++好きですか?
Cのスーパーセットらしい →普通 クラスを使えると便利 →やや好き 難解な文法というか落とし穴にハマる →嫌いになる(この辺で多言語に浮気) テンプレートがわかってくる →再び好きになる STLに感動する →好きになる bind1stとかvalarrayに不満がでてくる →再びちょっと嫌いになる boostがわかってくる →また好きになる
TMPができるようになる →何でもいいので何か自作のライブラリを作りたくなる boostに追記/修正したくなる →何かを作る事よりもC++を書くこと自体が楽しくなる 既存のコンパイラに嫌気を射し C++コンパイラを自分で作りたくなる →ちょっと飽きてくる 巨大なプログラムを作成中に過去に自分の書いたコードが読めなくなる →PCを窓から投げ捨てたくなる
68 :
引っ越してきました :2008/01/19(土) 20:17:46
VCスレからC++の問題ということで 追い出されて来ました。 クラスの中で+演算子を定義したいのですが、 newして、それをreturnの中で使いたいときに deleteできないで困っています。 どうしたらよいでしょうか。 ・簡単に言えば文字列の足し算です ・当方初心者です friend Mojiretsu operator+=(const Mojiretsu& moji1, const Mojiretsu& moji2) { // +演算子 int tmp_nagasa = moji1.nagasa + moji2.nagasa ; char* tmp_moji = new char[tmp_nagasa+1]; mojicpy(tmp_moji,moji1.s); mojicat(tmp_moji,moji2.s); return Mojiretsu(tmp_moji); } やりたいことはわかってもらえるとは思うのですが、 もっと楽にできるよとかもあったら教えてください。
いろいろとおかしいなw
Mojiretsu mojiretsu(tmp_moji); delete[] tmp_moji; return mojiretsu; でどう?
>>68 newしないでMojiretuを定義してそれをreturnすれば?
Effective C++でもnewはするなと書いてあったぞ。
72 :
68 :2008/01/19(土) 20:45:00
>>70 どうもです。
なるほど、コンストラクタを呼び出す、と。
実験の結果、ちゃんと動いています。
(まあ、もとのやつでも動いているようには
見えるのですが)
73 :
68 :2008/01/19(土) 20:46:44
>>71 どうもです。
少々時間ください。初心者のため
理解するのに時間がかかりますので。
例外安全・・・についてはまだ触れない方がいいか 混乱しそうだし
>>68 なんぜ+=なのに、moji1がconstなんだ?
Mojiretsu s1("abc"), s2("def");
s1 += s2;
これでs1 == "abcdef"にならないとおかしいだろ。
76 :
68 :2008/01/19(土) 20:55:56
訂正です。 ごめんなさい。 +=でなく、+です。
77 :
68 :2008/01/19(土) 20:58:58
>>71 やっぱりわかりません。
もう少しヒントください。
あと、Effective C++のどの辺でしょうか。
そのうち読もうと買ってはあります。
78 :
68 :2008/01/19(土) 21:00:50
>>74 とらいすろーきゃっち、でしょうか。
だいぶあとということでお願いします。
79 :
68 :2008/01/19(土) 21:07:19
>>71 どこが分からないかというと、
Mojiretuを定義するには、
(コンストラクタに)文字列(char*)を
渡す必要がありますが、その文字列自体、
strcatした後のものにしなければならず、
どうどうめぐりのようで
よく分からないのです。
勘違い、ご指摘くださいませ。
deleteは関数内で済ませてしまった方がいいだろう
Effective C++持っているなら演算子の話を是非、 と思ったらMoreのほうだった……、22。 operator +よりもoperator +=を実装しろ。 そして、operator +はこうする。 Mojiretsu operator +(const Mojiretsu& lhs, const Mojiretsu& rhs) { Mojiretsu tmp(lhs); return tmp += rhs; }
83 :
68 :2008/01/19(土) 21:16:53
>>82 どうもです。
実はMoreも持っています。
また実験してみます。
(時間がかかります)
std::vector使え
85 :
68 :2008/01/19(土) 22:00:52
>>82 ありがとうございました!
動きました!
+=を先に定義するというのは
頭いいですねえ。
頭がいいっつうか、定石だな。
87 :
68 :2008/01/19(土) 22:20:59
>>86 そういうものなんですね。
>>82 「More」の22の最初のページの一番下に
「単独演算子がfriendである必要はまったくない」と
あり82でもfriendがついてませんが、friendにしないと、
lhsが"rerere"のような場合に私のではコンパイルエラーに
なったのですが、まだ何かおかしいということでしょうか。
>>87 publicなコピーコンストラクタはあるか。
+=もメンバならやはりpublicになっている?
82のは、private/protectedなメンバに全く触っていないから
friendにする必要がないという仕掛け。
89 :
68 :2008/01/19(土) 22:32:41
>>88 たびたびありがとうございますです。
コピーコンストラクタも+=も+もその他すべての
メンバ関数はpublicになっているのですが。。。
90 :
68 :2008/01/19(土) 22:37:36
あ、もしかして、+は82そのままではなく、 privateメンバを触っていますがそのせいでしょうか。 Mojiretsu operator+(const Mojiretsu& str1, const Mojiretsu& str2) { // +演算子 String tmp_moji(str1.s); //←コンストラクタにはクラスの文字列部を渡してます tmp_moji += str2; return tmp_moji; }
91 :
68 :2008/01/19(土) 22:57:13
friendがないと、 error C2804: binary 'operator +' に引数が多すぎます。 error C2333: 'Mojiretsu::operator +' : 関数宣言のエラーです。関数の本体は無視されます っていうのも出たため、実験しましたが、 どの+でもエラーになってます。。。 friendつけている限りまったくwarningさえも出ないのですが。 すいません、時間切れです、明日の夕方、また来ます。
94 :
68 :2008/01/20(日) 00:23:56
大変おじゃまいたしました。
自己解決いたしました。
(error C2804でググって英文を読みました。
確かに読んでいる本ではコード上ちゃんと
なっていますがはっきりと言葉では
書いてないんですよねー、、、)
>>88 や、その他の方々、重ね重ねありがとうございました。
大変勉強になりました。
>>94 とりあえず次回のためには自己解決の意味を覚えとけ。
でもクラス定義内でfriend関数を定義できるのは盲点だったと思っている。
>>96 最初から知っていた俺がいる。
ただ、ADLでしかlookupできないというのは盲点だったと思っている。
>>98 そいつバカですね。Cが終わってるなら、C++では重過ぎて
実装できない組み込み機器はどうなるのか?
アセンブラはリストされてないから大丈夫じゃないか?
古いネタの揚げ足とってどうすんだよwww
>>98 > c++と区別してcなのか、それともc++込みで終わってるのか
スラドのくだらない雑談はいいから元の記事嫁よ
って元の記事もかなりくだらないな
C++のコーディング方法について質問です。 皆さんは、コーディング中にコメントアウトを使うでしょうか? 以前、仲間内でコメントアウトの是非で議論になりました。 私の知人はコメントアウトを使用する派で、私は使用しない派です。 皆さんは、コメントアウトの是非についてどう思うかお聞かせください。 なお、開発はVC++6.0、2003、2005などで行っています。 ちなみに、私がコメントアウトを否定する理由は 1.ソースが汚くなるから。 2.バックアップなら、zipか何かにまとめてプロジェクトごとバックアップしておいた方が良いから。 の二点です。 よろしくお願いします。
(コメントがしきい値以下です。)
106 :
デフォルトの名無しさん :2008/01/21(月) 20:38:50
英語圏向けblogでd.hatenaみたいにシンタックスハイライトできるblogないでしょうか?
スレタイ嫁
C++で作ればいーじゃない。
std::cerrやstd::wcerrの<<オペレータが例外を投げるケースは存在するのでしょうか? これらをcatch文の中で使っても安全なのでしょうか?
>>110 標準ができる前に既にI/Oライブラリは存在していて、後方互換性
のためデフォルトではストリームは例外を投げない仕様だと思った。
exceptionメンバー関数を使ってストリームの各種状態を例外ハンドリング
に変えることは可能。
112 :
111 :2008/01/23(水) 08:50:46
ユーザー定義型についてはoperator<<,>>で何をやるかによると思うけど。
113 :
110 :2008/01/23(水) 14:51:51
>>111 basic_ios::exceptionsの存在に初めて気付きました。
おかげですっきりいたしました。
ありがとうございます。
C++ で new されたオブジェクト(o)とクラス(CLS)が与えられたときに、 そのオブジェクトが CLS クラスのオブジェクトか判定するには どうすればできますか?
クラスをCLSと表すあたり、COMのCLSIDじゃないかとエスパーしてみる。
直接dynamic_castで済むこともあるけどな。
ただ、dynamic_cast と typeid は意味がちゃうよね。
dynamic_cast はキャスト可能な全ての型で判定が成功するけど、
typeid は(& とトップレベルの const 以外は)厳密に型が一致しないとダメ。
どっちの方がいいというのではなくて目的ごとに使い分けることになるから、
>>114 がどっちの判定がやりたいかによるね。
dynamic_castは多相型のポインタとリファレンスにしか適用できないし。
そうなるとそもそも仮想関数をうまく使えば dynamic_castも要らないだろというところまで話を広げたくなるね。
今は typeid で分岐するのが流行りなんだぜ?
dynamic_cast じゃなくて typeid が必要になる状況ってあんま想像つかない。 どういう時に使うんだ?
デバッグ用途とかコードジェネレータとか
参照への参照 int& & この表記はC++03では認められていませんが、C++0xではint&と等価なものとして 仕様が改定されることは決定済みなのでしょうか?
ドラフトには入ってたと思うよ
ただし、テンプレート引数が参照な時だけだっけ? && を素で書くと右辺値参照だったはず。
>>126 >>127 そうですか。テンプレートパラメータが既に参照の場合、
参照引数を渡すとT& &となりエラーとなるため、これを
回避することだけを目的としてるのかもしれないですね。
type functionを書くのも面倒なので是非改定
してもらいたいです。もしかすると今でもBoostでは便利
なものがあるかもしれませんが。
右辺値参照はC++03では認められていなくて、C++0xでは
正当になる予定ですよね?
あれ? 離して書くと大丈夫だったかもしれん。 うろ覚えだからドラフト読んでくり。
参照への参照なんて使うことあるの?
>>131 テンプレートでこねこねしていると、うっかり参照への参照という型が生まれることがある。
そんなもの、現状ではコンパイルエラーだが、125に書いてある通り0xだと、
Tへの参照への参照型は、単にTへの参照型として扱われるようになる。
& & -> & & && -> & && & -> & && && -> &&
>>132 thx うっかり、ってことは積極的に作るものじゃないって事でOK?
&&& はwell-formedなのか気になる
ill
>>135 template<typename T1, typename T2, typename T3>
void f(T!&& x, T2&& y, T3&& y);
例えば、こんな関数にboost::refで一部の引数だけ左辺値参照にすることができる。
そんなことできて何が嬉しいって、例えばBoost.BindやBoost.Lambdaの関数呼出。
これは& &→&というより、&& &→&の説明になっているけど。
別に boost::ref などを使わなくても, 普通に左辺値を引数にすれば左辺値参照として bind されるのでは?
くわしく
以下抜粋
1. lvalues can bind to an rvalue reference.
2.
struct A {};
void h(const A&);
void h(A&&);
void g(const A&);
void g(A&&);
void f(A&& a)
{
g(a); // calls g(const A&)
h(a); // calls h(const A&)
}
Although an rvalue can bind to the "a" parameter of f(), once bound, a is now treated as an lvalue.
>>139 の言うとおりのような気がする。
そもそもboost::refをなくすための&&ですやん
いや、&&はmove semanticsのためでしょ。 boost::refはoutパラメータとして使うためにあるんだと思ってる。
144 :
139 :2008/01/25(金) 13:52:28
以下 C++0x の話で現行の言語規格とは一切関係ないです.スレ違いですいません.
>>141 あ,いえ,自分が
>>139 で指摘したかったのはたとえば
template<typename T>
void f(T &&x);
があったときに, f を左辺値で呼び出すと T が左辺値参照型で specialize されて
f のパラメタの型が左辺値参照型になる,つまり
int i;
f(i); // T = int & として f が specialization される.
// 結果 f のパラメタの型が & && -> & の decay を受けて int & と同等になる
f(42); // T = int として f が specialization される.
// 結果 f のパラメタの型が右辺値参照型 int && になる
ということです.これによって f の引数が非 const 左辺値でも const 左辺値でも右辺値でも
問題なく受けられるようになるということを指摘したかったんです.
で,上記の仕様 (引数が左辺値か右辺値かで
テンプレートパラメタ T が参照型かそうでないかの違いが生じる) から,
f の実装内部において f が左辺値で呼ばれたのか右辺値で呼ばれたのかの識別も可能となります.
この 右辺値参照・参照型の decay ルール・関数テンプレートにおける引数推論規則 の組み合わせで
the forwarding problem が完全に解けるというのが現在の提案の骨子だったかと思います.
145 :
139 :2008/01/25(金) 13:54:25
あと,実際には
>>141 さんが指摘しているように
名前が付いた右辺値参照は左辺値として扱われるので,
右辺値として渡された f の引数を f の内部で引き続き右辺値として扱うには
明示的に右辺値参照に変換してやらないといけないです.
で,このために std::forward という補助的な関数テンプレートも提案されています.
template<typename T>
T &&forward(typename identity<T>::type &&x){return x;}
template<typename T>
void f(T &&x)
{
g(forward<T>(x)); // f が右辺値で呼ばれている場合, T が非参照型になっているので
// forward の戻り値型が右辺値参照型になり,右辺値として g に渡される.
// f が左辺値で呼ばれている場合, T が参照型になっているので
// forward の戻り値型が左辺値参照型になり,左辺値として g に渡される.
}
>>143 boost::refについて、これ嘘だった。
まったく話についてけないんだが。 何が左辺値で何が右辺値なんだかもうわけわからん 右辺値で呼ぶってどういうこと?
template <class T> struct identity { typedef T type; }; template <class T> inline T&& forward(typename identity<T>::type&& t) { return t; }
>>144 f(i); // T = int & として f が specialization される.
T が int & にdeductionされるのって、パラメータが右辺値参照
のときのみのルールですよね?
Let us first consider the rvalue reference type, T &&, in more detail in the context of the C++ type system. What if T is itself a reference type? Template libraries have been known to create reference to reference types via typedefs or type manipulations. According to the proposed resolution to Core Defect Report 106 , ordinary references obey the equality T cv1 & cv2 & == T cv12 &, where cv12 is the union of cv1 and cv2. A similar reasoning can be applied to collapse two rvalue references into one: T cv1 && cv2 && == T cv12 &&. こいう文書で出てくるcv1やcv2やcv12の数字は何を意味してるんですか?
区別するため便宜的に番号を振っているだけ。 例えばcv1 = const, cv2 = volatileなら、 vc12 = const volatileだよという話をしたいがためのもの。
>>151 なるほど。unionは合成の意味ですね。てっきりキーワードもunionかと
思ってしまいました。
すいません.
>>145 で示した forward の定義は
正確には
>>148 さんの書いたとおりです.
>>147 >何が左辺値で何が右辺値なんだかもうわけわからん
戻り値の型が左辺値参照型でない関数の呼び出し構文(の結果)が右辺値で,
それ以外は全て左辺値,という理解である程度通用するかと思います.
>>149 全部把握しているわけではないので推測になりますが,恐らくそうだと思います.
後方互換性の観点から考えても,
パラメタが右辺値参照型以外の場合は従来どおりの deduction になるかと.
システムの構造体の定義をXML形式で出力したいんだけど、上手い方法があったら教えてださい。 ある構造体は中にも構造体を保持していて、その構造体は別ファイルで定義してるとか、 ifdefやら二重に定義されてるマクロやらで手動でやろうとするともうワケワカメです
>>153 The next step is to modify the argument deduction to retain information
about the "rvalueness" of the argument: when deducing against a template
parameter of the form A1 &&, deduce A1 as a reference type when the
argument is an lvalue, and a non-reference type otherwise. According to
our T cv1 & cv2 && == T cv12 & rule, this effectively means that the
type of the argument will be A1 & when the argument is an lvalue, and A1
&& otherwise.
どうやら右辺値参照パラメータに対する特別なdeduction ruleみたいですね。
独自ネームスペースを持つ外部ライブラリを幾つか利用して大きなプログラムを書くようになったら #include "hoge1.h" …… #include "hogeN.h" #include "mylib1.h" …… #include "mylibN.h" #include <lib1.h> …… #include <libN.h> namespace current_namespace { using ns1::hoge1; …… using ns1::hogeN; …… using nsN::hoge1; …… using nsN::hogeN; …… な感じで各ファイルの先頭が埋め尽くされるようになりました。 皆さん、どのように解決しているのでしょうか?
全てのヘッダを include するヘッダを作って、ソースコードの先頭で #include "all.h" とする。
リコンパイルで半泣きコースだな
リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ? VC++2005の #pragma once を使ってる場合ですら200ファイルほどのプロジェクトでリビルド時間が半減したんだけど。
precompiled headerになるようにしときゃいいだろ。
>>159 よく分からんけど、
#pragma once
よりも、
#ifndef XXXXXXX
#define XXXXXXX
////
#endif
の方がビルド時間が短くなるの?
163 :
くお :2008/01/26(土) 00:49:00
c++でエクセル用のアドインを作るやり方を教えてください。 よろしくお願いします。
>>162 #ifndef XXXXXXX
#define XXXXXXX
#include "myhoge.h"
#endif XXXXXXX
とやって include 行を読み飛ばす方法。
myhoge.h にアクセスする必要がない、展開後のファイルサイズが小さくなる、等の理由でビルド時間が短くなることが多い。
くおーっ!
>>157 all.h に含まれるヘッダのどれか一つでも更新されると all.h を含むファイルが全てコンパイルされる罠。
all.h をプリコンパイルヘッダにしたところで防げません。
批判もいいけど先に解決策を示そうぜ。
>>164 なるほど。それだとすると、159の
>リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ?
の理由は、ヘッダファイル使用時にやることが増えるから。かな?
いや、そっちの方が早いってのなら、合理的な理由じゃないとは思うけど
多分159に対する答えは、そんなところだと思う。
初歩的な質問で申し訳ないのですが、ヘッダファイルの中で行う以下のような 0クリアは問題ないですか?sizeof(this)は正しく計算されます? class HOGE { int a,b,c; char str[128]; void init(void) { memset( this, 0, sizeof(this) ); }; };
いえ、できれば構文的に正しいのか知りたいのですが… テストのクラスで成功しても、他のクラスでは失敗するかもしれないので。
>>172 コンパイルが通れば、構文的には正しい。
というのは置いといて、
メンバ変数をクリアしたければ、sizeof(*this)とすべき。
そして重要なのは、その方法が使えるのはPOD型だけ。
例えばHOGEに仮想関数を追加すると、動かなくなる。
構文って意味分かってんのかいな…。
>>173 詳しく有難うございます。納得できました。
>>174 「構文」は間違いでした。
>>173 のような事を表したかったのですが、
そういう場合は何と呼ぶべきですかね…
177 :
デフォルトの名無しさん :2008/01/26(土) 04:53:51
今タイピングのアルゴリズムでゲーム中に「し」を「si」と「shi」のどちらでも受け付けるとような操作を考えています。 現段階では文字列クラスを用意して双方向リンクリストを使って分岐を操作して居るんですが、どうしてもコードが複雑になってしまいます。 もう少し簡単なアルゴリズムや便利なSTLなどがあったら教えてください。 文字列クラス class characterData { private: wchar_t ch; // 単語を構成する文字 Databace* follow; // この文字に続く文字へのポインタ Databace* other; // 分岐文字へのポインタ Databace* rear; // この文字の前の文字へのポインタ public: Databace(); Databace(wchar_t, Databace*, Databace*, Databace*, unsigned char); ~Databace(); // 変数の値を設定する関数群 void setFollow(Databace*); void setOther(Databace*); void setRear(Databace*); void setCh(wchar_t); void setLevel(unsigned char); // 変数の値を返す関数群 wchar_t getCh() const; Databace* getFollow() const; Databace* getRear() const; Databace* getOther() const; }; 文字列を作るクラス class createString { private: Databace* end; // 文字列の最後の文字へのポインタ Databace* div; // 分岐文字がある場合のみendと違う場所を指す void add(const int n, ...); // n個の文字を追加する public: CStrManage(); ~CStrManage(); // elementをローマ字に変換しbaseの後ろに追加する bool convert(const wchar_t* element, Databace* base); };
178 :
デフォルトの名無しさん :2008/01/26(土) 05:00:27
追加用の関数はこうなっています void createString::add(const int n, ...) { va_list args_pointer; wchar_t* arg_wchar; size_t length; va_start(args_pointer, n); // 文字を分岐させる for(unsigned char i=0; i<n; i++) { arg_wchar = va_arg(args_pointer, wchar_t*); length = wcslen(arg_wchar); // 分岐用文字列を作成する Databace cdb; // ダミーの作成 Databace* tmp = &cdb; // 追加先の指定 Databace* rear = NULL; // 現在地の記憶 // 文字の追加 for(unsigned char s=0; s<length; s++) { Databace* data = new Databace(); if(s==0) { rear = data; } // 追加前の場所を記憶 // 文字データの設定 data->setFollow(NULL); data->setOther(NULL); data->setCh(arg_wchar[s]); data->setLevel(s + 1); if(s==0) { data->setRear(end); } // 前の文字を参照させる else { data->setRear(rear); } // 新しく作った文字列の先頭を参照させる // 文字を追加 tmp->setFollow(data); tmp = tmp->getFollow(); } // 作成した文字をデータベースに追加する if(i!=0) { div->setOther(tmp2->getFollow()); div = tmp; // 作成した文字を追加 div->setFollow(cdb.getFollow()); div = end; // 分岐後の参照先を設定 } else { div->setFollow(cdb.getFollow()); end = div = tmp; } } va_end(args_pointer); }
>>170 sizeof(this) ってポインタのサイズだと思われ
sizeof(*this) にしないとだめなんじゃね?
180 :
179 :2008/01/26(土) 05:36:04
って、すでに173で指摘されてた・・・
181 :
110 :2008/01/26(土) 06:16:08
>>177 std::listを使って一本のリストを作って、リストの各要素のオブジェクトを工夫したほうがいいよ。
リストクラス自作するにしても、これはあまりにも酷い。
せめてコンパイルが通りそうなコードを読ませてくれ。
>>175 そもそも、クラスの初期化を外部から行なってはいけません。
183 :
156 :2008/01/26(土) 11:23:55
結局、他の人はどうしてるの?
折角階層的にネームスペースを宣言しているのに、ユージング宣言し捲くるってどうなのよ。 そんなばかげたことする香具師いないからレスがつかないんじゃね?
using なんて普通は使わないよな。
>>166 all.hにはすべてのヘッダファイルではなく、外部から提供されたライブラリのヘッダだけ入れておけば
基本的に更新することはないんじゃない? (その場合、all.hというネーミングは不適切だね。)
目的を既に忘れてるな
using 宣言は使うだろ。 using しないとコードが汚くなる。 そこらじゅう ns1::ns2::hoge() とか nsN::nsM::hoge() とかばかりになるぞ。
ある程度のプロジェクトではファイルの先頭が #include や using で埋め尽くされるのは避けられないこと。 耐えろ。
>>188 おまいはヘッダファイルでも using 使って
迷惑かけるタイプか
>>190 どっからヘッダファイルで using なんて考えが出てきたんだ?
*.h と *.cpp では書くものが違うのはあたりまえだろうが。常考。
using なんて使わなくても 名前空間のエイリアス作ればいいだろ。
>>188 namespace fuga1 = hoge1::hogeA::hogeX;
namespace fuga2 = hoge2::hogeB::hogeY;
namespace fuga3 = hoge3::hogeC::hogeZ;
……
みたいな解決策もある。
using は関数増えた時に別の関数が選択される恐れがあるから怖い。 エイリアス作ろうぜ。
>>194 例は?
using 指令と違って using 宣言では名前が衝突するとコンパイルすら通りませんが?
そもそもネームスペースが上手く使われてる大規模プロジェクトって見たことないな。 パッケージ名を接頭辞に持つプロジェクトの方が上手くいってたりする。
>>195 そりゃ嘘を教えられたな。
確かにエラーになることは多いが、エラーにならない事もある。
==========
namespace Hoge { void Foo(); }
namespace HogeHoge { void Bar(); }
using Hoge::Foo;
namespace HogeHoge {
void Bar() { Foo(); } ← Hoge::Foo
}
==========
namespace Hoge { void Foo(); }
namespace HogeHoge { void Foo(); void Bar(); }
using Hoge::Foo;
namespace HogeHoge {
void Bar() { Foo(); } ← HogeHoge::Foo
}
>>193 の方法でいいんじゃない?
これなら普通は namespace の数 < 識別子の数 なので先頭部分は少し短くなる。
ただし、その代わりにコードは少し長くなる。
どっちにしろ先頭が namespace で埋め尽くされるのは変わらないが。
そだよ。エイリアスが一番マシ。 ただ、エイリアスは .cpp のグローバルでのみ作るべし。 名前空間内で作っちゃうとまたややこしい問題が生じる。
グローバルで using してたら意味ないだろ。 namespace HogeHoge { using Hoge::Foo; void Foo(); } で普通にエラーでたぞ。
namespace Hoge { void Foo(); } namespace HogeHoge{ namespace Hoge { void Foo(); } void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo } 別に間違いようはいくらでもある。
名前空間って厄介だよな。
>>202 これって防ぎようなくね?
どうすんの? これ。
>>204 ::Hoge::Foo() でアクセスできるよ。
>>205 なるほど・・・。
でも、常日頃から :: から始めないと防げないよな。
そもそも他人の名前空間と同じ名前の名前空間を 後から作るという時点で間違いだとは思うが、 開発中に後から導入したライブラリが・・・ということもあるか・・・。
ちなみにこんなのも。 namespace Fuga { void Foo(); } namespace Hoge = Fuga; namespace HogeHoge { class Hoge { public: static void Foo(); }; void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo(); }
名前空間はクラス名・関数名・変数名なんかと違って規約がなかったりするから、結構みんなテキトーにつけてたりする。 酷い話だとグループ全員が自分用の関数を mylibs に入れていた例が...
幾何学ライブラリで geom が衝突したりとかだな。
かといってJavaみたいにドメインを逆さにするのもなぁ
>エイリアスは .cpp のグローバルでのみ作るべし。 グローバルに alias 作るとヘッダが変わったときに突然コンパイルが通らなくなることあるよ。
前に関ったプロジェクトは常にフル指定?でメソッドを呼び出すべし という規約があった 基底クラスのメソッドさえも Hoge::Foo:Base:Dosomething(); 多重継承を多用していたからという事情もあるんだけど 面倒だけど、安全ではある
その面倒なのがイヤだから using を使いたい、alias を使いたいってんだと思うが。 ぐるっと一周してきた感じだな。
グローバルにエイリアス量産するぐらいなら名前空間内で using 宣言した方がいいと思う・・・
しかしだな、エイリアスと別の名前空間が衝突することもあってだな・・・。
無限下降スパイラル
218 :
177 :2008/01/26(土) 19:12:06
>>181 すいません、文字列クラスがcharacterDataではなくDatabaceでした。
>std::listを使って一本のリストを作って
listやmapを使うことも考えたんですが、リスト化した後のタイプの分岐判定のアルゴリズムが思いつかず断念しました。
なのでその辺のアルゴリズムのアドバイスも出してくれると助かります。
>コンパイルが通りそうなコード
コンパイルも通って動作確認もしてあるので正常に動作しているとは思います。
ただ、これだけ乱雑になると可読性に欠けてバグの温床になりそうなのでアイディアを聞きたいと思った次第です。
>>175 遅レスだけど、
そういう場合は鼻から悪魔がでますか?って聞けばいいよ。
//xxx.cpp namespace { namespace ns = long::longlong::longlonglong::ns; } void F1() { ns::Foo(); }
template <typename T> //primary template class Test { public: enum { Result = 1 }; }; template <typename T> //T const に対する partial specialization class Test<T const> { public: enum { Result = 2 }; }; template<typename T> void f(T t) { cout << Test<T>::Result << endl; } int main() { int i = 1; f(i); // @ --> 1が表示される int const j = 1; f(j); // A --> 1が表示される }
222 :
221 :2008/01/27(日) 13:22:31
221です。続きです。
>>221 のtype functionについて疑問があります。
main関数内のAの呼び出しでは、渡している引数の型は確かに int const の
はずですが、結果はprimary templateが呼び出されます。Aでは T が
int const に deduction されて、T const に対する partial specialization
が呼ばれ、結果が2 になると思ったのですが、そうはなりませんでした。
明示的に f<int const>(j); とすれば 2 が表示されます。
何故 A の呼び出しで T が int const に deduction されないのでしょうか?
223 :
221 :2008/01/27(日) 13:54:47
int const val; のように変数valを定義した場合、valの型にconstは含まれるのでしょうか? int const& ref; の場合は、refの型は int const& となりconstは含まれますよね?
int const val; と const int val; は等価。 val の型に const は含まれる。
>>222 パラメータリストのconst修飾は関数の型としては無視される、
ということからだろうと思われる
たとえばvoid f(int);とvoid f(int const)の型は全く同一になる
f<int const>(j); とすれば 2 が表示されることに保証があるのか
俺は知らない
226 :
221 :2008/01/27(日) 16:45:57
レスありがとうございます。
>>224 >int const val; と const int val; は等価。
それは知ってます。
やはり型の一部ですよね。
>>225 >たとえばvoid f(int);とvoid f(int const)の型は全く同一になる
value functionに関するそのルールは知っています。
このプログラムはvalue functionではなく、type functionなので
引数のdeductionの問題になると思います。f<int const>(j); は
明示的に型を指定しているのでpartial specializationが使用
されることは間違いないです。ただ、constが型の一部であるにも
関わらず、int const型のテンプレート引数である j を渡しても
specializationが使用されていないのが理解できません。
結果を見る限り、const修飾子が無視されてint引数として扱われてること
になりますが、これはテンプレートの標準における正しい仕様なのでしょ
うか?
VC++ 2008 と g++ v4 ともに同じ結果でした。
そもそも const int を int な引数の関数に渡せるしね。 規格でどうか知りたいなら、規格を読むのが一番だ。
228 :
221 :2008/01/27(日) 17:09:22
>>227 それはvalue functionのパラメータ及び引数のルールであって、
テンプレートのtype parameterのdeductionはまた別の問題のよ
うに思います。もう少し規格を見てみます。
229 :
221 :2008/01/27(日) 17:12:18
>>227 >>228 は撤回します。
確かにそれが理由のような気がします。
そうすると、const int と T を比べると T が intに
deductionされるのも頷けます。
>>226 >partial specializationが使用 されることは間違いないです
ああそりゃそうか
>これはテンプレートの標準における正しい仕様なのでしょうか?
14.8.2 -3-にあった
手元にドラフトがあるのでそれで調べてみたが、14.8.2.1 p2 にそれらしきものが。 14.8.2.1 Deducing template arguments from a function call If A is a cv-qualified type, the top level cv-qualifiers of A's type are ignored for type deduction.
>>226 type function とか value function とか、何の方言?
意味がわからない。
最新のドラフトを見ると怖いことが書いてあった [ Note: f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type. .end note ]
>>234 まあ明示的に指定する分には違っててもいいんじゃね?
236 :
221 :2008/01/27(日) 17:34:09
>>230 >>231 >>232 >>233 >>234 >>235 みなさんレスありがとうございます。
>>231 まさにそれかと思います。同じことがJosuttisのC++ Templateにも
書いてありました。
こういう事情のようでです。
template<typename T> void f(T);
template<typename T> void g(T&);
int const ci = 123;
f(ci); // T is int
g(ci); // T is int const
すっきりしました。
int const& の const はトップレベルの const じゃないからそうなるわな。なるほど。
238 :
221 :2008/01/27(日) 17:47:45
>>233 詳しいことは知りませんが、
現段階で標準で規定された言葉ではないと思います。
テンプレートの本に書かれていました。
value functionはいわゆる通常の関数を指します。
パラメータがtype、引数が値。
type functionとは、通常クラステンプレートで
実現されるものらしいです。
パラメータがテンプレートパラメータ、引数がtype。
struct Widget{};
Test<Widget>::Result;
>>221 のTestクラステンプレートの場合、Widgetが引数で
type functionの戻り値がTest<Widget>::Resultと考え
ると通常の関数のように関数とみなせるというもだと
理解してます。
>>238 「テンプレートの本」ってどれだ?
普通に「関数」と「クラステンプレート」って言ったほうがいいと思うよ。
意味の違いを正しく表している呼び名だとは思えないからね。
後者は「(テンプレート)メタ関数」とか呼ばれるもののような気もするなぁ。
240 :
221 :2008/01/27(日) 18:36:02
>>239 ここでいうtype functionとは
最近の言葉で表せばメタ関数でしょうね。
Boost::mplなどの最近のメタプログラミングで
使われていますが。
本はC++ Template The Complete Guideです。
著者は標準化委員会の現メンバーでもあり
信用できないものではないと思います。
通常の関数と対比して、コンパイル時に型を引数
とする”関数”という概念的に上手い言葉だと感じ
ているので自分はなるほどと思いました。
>>240 メタ関数でいいならそう言ったほうがいいでしょ。
わざわざ廃れた用語を使い続ける理由もない。
meta function == type function 別に正式な名前じゃないけど、 type functionってのはそこそこみる表現だから覚えておいてもいいと思うよ
>>241 別に廃れてるわけではないよ。
概念を表した言葉だから。
適当なオブジェクトのポインタが与えられたとき、そのオブジェクトのクラスがある特定の 名前と引数のタイプを持ったメンバ関数を持つときに限りその関数を呼んで処理したい のですが、C++ で可能でしょうか? あ、オブジェクトは必ずしも共通のスーパークラスを持たないとします。要はそういう 場合でも仮想関数的なことをしたいというか... その特定のメソッドをもつ別クラスを作って、それを全てのオブジェクトで多重継承、 というのも考えているのですが、ちょっとダサいかな? と思って。あとソースのないクラス では無理ですよね(今のところはソースのあるクラスだけでいいんですが)。 そもそもこんなことを考える事自体ナンセンス、と言われるとアレなんですがw
ポインタの型がテンプレート引数で与えられているならば、可能
>>245 嘘だろ。怪しいからソースを晒してください。
>245が言いたいのは「コンパイル時にクラスが確定できる」場合だろ。
249 :
245 :2008/01/29(火) 13:41:34
おかしいな。VC9だとhas_xxxが通らない。 自分で書いてみても、やはり通らない。 こんな風にSFINAEを使ってやればできるはずなんだけど。 struct BjarneStroustrup { void hage() ; } ; struct Others { void fusafusa() ; } ; template < typename T > struct has_hage { struct Yes { char a[1] ; } ; struct No { char a[2] ; } ; template < typename Y > static Yes test(typename Y::hage const *) ; template < typename Y > static No test(...) ; static bool const value = ( sizeof( test<T>(0) ) == 1 ) ; } ; BOOST_STATIC_ASSERT(( has_hage<BjarneStroustrup>::value )) ; BOOST_STATIC_ASSERT(( has_hage<Others>::value )) ;
250 :
245 :2008/01/29(火) 13:42:58
最後の一行間違ってるけど気にしないで
template < typename Y > static Yes test(typename Y::hage const *) ; はおかしくないか? マッチしなかったぞ。 やるなら template < typename Y > static Yes test(void (Y::*)(void)); か? でも、これじゃあ関数名の一致の評価はムリだな。 何か仕組みが必要か。
struct BjarneStroustrup { void hage(){cout << "hage" << endl; } }; struct Others { void fusafusa(){cout << "fusafusa" << endl;} };
template <typename T> struct has_hage { typedef char One; typedef struct { char a[2]; } Two; template < typename Y > static One test(void (Y::*)(void)); template < typename Y > static Two test(...); enum { value = sizeof(test<T>(0)) == 1 }; } ; template <typename T> void func(T) { cout << "too bad" << endl; } template <> void func(BjarneStroustrup* p) { p->hage(); } template <typename T> void call(T* t) { if(has_hage<T>::value) func(t); }
int main() { BjarneStroustrup b; call(&b); Others o; call(&o); }
struct BjarneStroustrup { typedef void HAGE; void hage() const {cout << "hage" << endl; } }; こういう風に typedef 定義して(擬似的な名前一致) template < typename Y > static One test(typename Y::HAGE *); じゃだめかいな。
これじゃあシグニチャが合わないか。
ちょっと変更 struct HAGE{}; struct BjarneStroustrup { template <typename T> void hage(); template <> void hage<HAGE>() {cout << "hage" << endl; } }; template <typename T> struct has_hage { ・・・・・ template < typename Y > static Two test(...); ・・・・・ } ; template <> void func(BjarneStroustrup* p) { p->hage<HAGE>(); }
こっちだった。 template <typename T> struct has_hage { ・・・・ template < typename Y > static One test(void (Y::*)(HAGE)); ・・・・ } ;
このスレって頭悪い奴多いね
そもそもプログラミングしてる時点でアレだしな
ググったらこんなのが出てきた。
http://www.gamedev.net/community/forums/topic.asp?topic_id=435173 これを基に少し改造してみた。BjarneStroustrupとOthersは
>>249 の定義を使用。
#include <iostream>
#include <boost/mpl/bool.hpp>
//#include <boost/type_traits.hpp>
struct SFINAE {
typedef char one;
typedef struct { char c[2]; } two;
};
template<typename T>
class has_hage_impl {
template<void (T::*)()> struct Wrap {};
template<typename U>
static SFINAE::one Determine(Wrap<&U::Hage>* w);
template<typename U>
static SFINAE::two Determine(...);
public:
static const bool value = sizeof(Determine<T>(0)) == sizeof(SFINAE::one);
};
template<typename T>
struct has_hage : boost::mpl::bool_<has_hage_impl<T>::value> {};
//boost::integral_constant<bool, has_hage_impl<T>::value>も可
int main() {
std::cout << std::boolalpha
<< has_hage<BjarneStroustrup>::value << '\n'
<< has_hage<Others>::value << std::endl;
}
クラステンプレートのテンプレイート引数をバインドしたいと思っています。 考えたのは template <class T1, class T2> class A {...}; template <class T1> class AInt { public: typedef A<T1, int> type; }; このような方法ですが、AInt<Hoge>::typeとしないといけないところに不満が残ります。 typedef A<T1, int> template <class T1> AInt; こんな感じで完全にバインドしてしまう方法はないでしょうか?
265 :
デフォルトの名無しさん :2008/01/29(火) 18:33:14
0,1,2,3,4 から 2個取り出すときの全組み合わせ 3個 4個 5個(は1通りだけど) を文字列(stringでもcharでも)として吐き出すプログラムを 書きたいんですがアイディアだけでもいただけないでしょうか?
>>264 今のC++にはない。0xに乞うご期待。
その方法が嫌なら、使える場合が限られるけど継承するか、
template <class T1>
class AInt : public A<T1, int> {};
あとはプリプロセッサマクロで何とかするか。
268 :
デフォルトの名無しさん :2008/01/29(火) 18:47:21
や、宿題じゃないんですが自分でプログラムかいててハタと迷ったので・・ スレチならすいません
>>265 なにが固定でなにが引数になるか書いてくれないと答えようがないぜ。
270 :
264 :2008/01/29(火) 19:03:55
>>267 そうなんですか。
ありがとうございました。
271 :
268 :2008/01/29(火) 19:03:59
すいませんネットから拾ったプログラムを改変したら多分出来ました。 #include <stdio.h> int main(int argc ,char *argv[]){ int a=0,b=0,c=0,d=0; for (a=0;a<=4;a++){ for (b=0;b<=4;b++){if(b==a || a>b)continue; for (c=0;c<=4;c++){if(c==a || c==b || b > c)continue; for (d=0;d<=4;d++){ if(d==a||d==b||d==c||c>d)continue; cout <<a<<b<<c<<endl; } } } } return 0; }
スレ違いだな。 ここは見ての通り、C++の規格書を暗記している奴が、 C++の文法で、Bjarne Stroustrupがハゲているかどうか、 コンパイル時に判定するスレだ。 ソースコードが実用的かどうかは、どうでもいい奴らなんだよ。 重要なのは規格違反かどうかということだけだ。 まあ、大方のスレ住人もハゲてるんだけどな。
ゆとり教育のカリキュラムには順列・組み合わせとかないの?
274 :
268 :2008/01/29(火) 19:08:50
>272 thx 俺はケツ毛までフッサフサです。
277 :
245 :2008/01/29(火) 20:05:40
>>261 お、それだとVC9でもBOOST_STATIC_ASSERTが通った。
でもおかしいな、確か昔、C++ Templatesで読んで、実際に自分で試してみて、
スゲーと感動した記憶があるんだけど。
たしかVC7だったかな。
あとBoostのhas_xxxって、これ関数じゃないんだね。知らなかった。
278 :
デフォルトの名無しさん :2008/01/29(火) 20:17:41
VC++6.0で開発してます。 CHttpFile::SendRequestEx() にて、 CInternetException以外の例外が発生するケースが稀にあるようなんですが、原因が特定できず悩んでいます。 そもそもCInternetException* の例外以外がスローされることってあるんでしょうか? どっかのサイトでは、CFileExceptionもスローされると書いてあったんですが・・・。 どなたか、このような経験が方いらっしゃいましたら御教授下さい。
スレ違い。
オナニーレスばっかりだな
しこしこ
ズルムケ
それは鈴木ムネオの秘書だろ
>>280 さー?
>>244 が静的な多様性でいいのかどうか分からないからなんとも。
しかし動的な多様性がほしいとすると、引っかかることも。
「ポインタで与えられる」、しかし共通のベースクラスがあるわけではないってことは、void *型で渡すんだろうか。
それだと特定のメンバ関数云々よりも、そもそもオブジェクトのクラスの型は何だってことになるし。
動的な多様性がほしい、
しかし、既存のコードはいじりたくないので、共通のベースクラスに純粋仮想関数は使えないというのなら、
例えばBoost.Anyに使われているType Erasureのテクニックが使えるかもしれない。
あの単純すぎるテクニックを使えば、かなり変態的なことができる。
287 :
デフォルトの名無しさん :2008/01/29(火) 22:36:43
あるクラスを継承しているクラス群のみを対象にメモリ割り当てをカスタマイズしたいです class Base{} class Derived1 : public Base{} class Derived2 : public Base{} そこでこれらクラス群の内、最も大きいサイズのクラスを基準に配列を静的に用意、 Base、Derived1、Derived2をnewする時に使いたいと思ってます struct AllocUnit{ char[???] buf;} ←ここのバッファのサイズを静的に求めたい static AllocUnit[MAX_UNIT] memory; //sizeof(AllocUnit)*MAX_UNIT分のバッファを静的に確保 ???の部分を求める方法がわかりません MPLを使えばできそうな感じなんですが・・・ 言い換えると、任意の数のクラスの内、サイズが最大のものをコンパイル時に取得する方法はないか? という事です↓こんなイメージ char[max_size<Base,derived1,derived2>] buf;
>>264 俺はそういう時、
template <class T1, class T2>
class A { ... public: typedef A<T1, T2> this_t; };
として、バインドするクラスは
template<class T1>
class AInt : public typedef A<T1, int>{};
のようにpublicで継承する。
そしてクラスを記述する時はどんなものにしろ必ず
A::this_t;
AInt::this_t;
と最後に::this_tとつける気持ち悪い習慣を身に着けている。
もしくは、 #define hogehoge(class) class::this_t のようなマクロを使うとか、いろいろ手はあるけど
結局どれもいたちごっこかうへへへへへへへへへh
>>287 こんなのでどう
template <typename A, typename B> struct max_size { enum{ value = sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) }; };
template <typename A, typename B> struct max_size_chain { enum{ value = A::value > sizeof(B) ? A::value : sizeof(B) }; };
template <typename A, typename B, typename C> struct max_size3: max_size_chain<max_size<A, B>, C>{};
template <typename A, typename B, typename C, typename D> struct max_size4: max_size_chain<max_size3<A, B, C>, D>{};
template <typename A, typename B, typename C, typename D, typename E> struct max_size5: max_size_chain<max_size4<A, B, C, D>, E>{};
char buf[max_size5<char, int, short, long, void*>::value];
boost mpl if_cとかとsizeof使えばいい
template <size_t x, size_t y> struct size_t_max { static const size_t value = x > y ? x : y; } struct AllocUnit { static const size_t size = size_t_max<sizeof Derived1, sizeof Derived2>::value; char buf[size]; } 基底クラスより派生クラスの方がサイズ大きいの分かってるから 2つの比較だけでいいべ。
ミスって途中送信してる・・・。 こっちが本物。 #include <iostream> struct Base { int x; }; struct Derived1 : public Base { int n; }; struct Derived2 : public Base { int n, m; }; template <size_t x, size_t y> struct size_t_max { static const size_t value = x > y ? x : y; }; struct AllocUnit { static const size_t size = size_t_max<sizeof (Derived1), sizeof (Derived2)>::value; char buf[size]; }; int main(){ std::cout << AllocUnit::size << std::endl; } 基底クラスより派生クラスの方がサイズ大きいの分かってるから 2つの比較だけでいいべ。
293 :
244 :2008/01/29(火) 23:09:34
皆さんどうもありがとうございます。
なるほど、テンプレートの特殊化を利用って感じですか? こんな風に使えるんですね。
が、しかし、
>>285 >「ポインタで与えられる」、しかし共通のベースクラスがあるわけではないってことは、void *型で渡すんだろうか。
ビンゴでございます。テンプレートの場合変数の型で挙動が変化してるわけですよね。
自分は Objective-C も使うことがあるので今回のような疑問を持ったのですが。
>しかし、既存のコードはいじりたくないので、共通のベースクラスに純粋仮想関数は使えないというのなら、
とりあえず多重継承で共通のベースクラスを足すことをを検討しています。
>例えばBoost.Anyに使われているType Erasureのテクニックが使えるかもしれない。
そうですか、参照してみます。
294 :
244 :2008/01/29(火) 23:15:51
あ、あれ、でもvoid *で渡さなくてもいいかな? ちょっと考えてみます。 でもやっぱ多重継承の方が自然かなあ。
295 :
287 :2008/01/29(火) 23:16:19
>>289 ありがとうございます。参考にします
>>292 なるほど。確かにsizeof(Base)<=sizeof(Derived)ですもんね
よく考えたらgreater<T1,T2>的なモノを用意して、それを連ねていくだけでよかったんですね
しかし派生クラスの数が増えるたびにmax_sizeの引数増加版を定義するのが面倒・・
可変引数のtemplateがあればなぁ・・・
>>287 template<typename T1, typename T2, typename T3>
struct MaxSize {
typedef typename if_c<(sizeof(T1) > sizeof(T2)),
typename if_c<(sizeof(T1) > sizeof(T3)),T1, typename if_c<(sizeof(T2) > sizeof(T3)),T2,T3>::type>::type,
typename if_c<(sizeof(T2) > sizeof(T3)), T2, T3>::type >::type SizeT;
static const size_t sz = sizeof(SizeT);
};
マクロをゴニョゴニョすれば DEFINE_MAX_SIZE(3, 100); で max_size3〜max_size100 まで定義、みたいなこともできそうだが、 実用的には生成プログラム書いた方が楽だと思う。
298 :
デフォルトの名無しさん :2008/01/30(水) 14:46:54
C++で継続(continuation)、あるいはそれっぽいことができるライブラリや、 C++で継続に関するページがあれば教えてください。
まずお前の継続に関する経験について聞こうか? 全くC/C++以外の経験が無いとかいうレベルだとかなり大変だぞ。
300 :
デフォルトの名無しさん :2008/01/30(水) 16:21:20
>>299 rubyでcallccを知り、その関連ページで勉強した程度しか知識がありません。
やりたいことは、まさにrubyのcallccで実行できるようなことです。
「なんでも継続」は読んだ? (Cの)setjmp/longjmpは理解してる?
302 :
298 :2008/01/30(水) 16:40:15
>>301 「なんでも継続」のページ、良さそうですね。
まずここから始めてみます。
setjmp/longjmpは、Unix C上がりなので知ってます。使った記憶は1回しかありませんが…。
>>298 Boost.Coroutine
Hamigaki C++ Libraries
Hamigakiってなんかのギャグかと思って調べたらほんとにあるんだな…。
なんか最近はスーパーマリオみたいなのつくってなかったっけ
BoostにLokiのタイプリストみたいなものってありありますか?
cons list?
>>306 Boost.MPLのmpl::vector等
やめんか
C++的に配列はどんなものでも<vector>ライブラリを使うべきなんでしょうか?
>>317 そんなことはないけど、 ruby や python みたいな言語を触ってる人から見て
配列といって当てはまるのは std::vector でしょうね。組み込みの配列はいろいろ
歴史的な問題も残ったままだし。
>>317 サイズが完全に決まってるなら
巨大でさえなければ、
組み込みの配列を使った方が効率がいい。
320 :
デフォルトの名無しさん :2008/02/01(金) 07:53:11
tr1::array早く来い来い。
普通の配列ならスタックに蓄えられるとか、newすればヒープから領域を取ってくるとか、 配列を扱うならそこら辺の知識もあってほしいな。
alloca()
まぁ、スタックに蓄えられるとか、newすればヒープから領域を取ってくるとか 規格には書いてないけどな
new はフリーストアから領域を取ってくるんです!
mallocはヒープから領域を取ってくるんです!
stroustrupはどこから毛を取ってくるんです!?
>>326 お前らがnewするたび、stroustrupから領域を割り当てられているのに
ちゃんとdeleteしない奴が多いから…。
そろそろstd::bad_allocが飛んでくるぞ。
stroustrup「virtual hair hair() = 0 はただのインタフェース! 実際のインスタンスはもっとふさふさなの! バヤには見えないんだよーだバーヤバーヤ!」
散々ネタに去れてるのにstroustrupのAAってなんでないんだろう。 俺が作ってやる。
毛量保存の法則 頭髪の少い場合、顎髭や胸毛、ギャランドゥなどで補い、最終的な毛量は一定
ハゲで体毛も薄い人間は 代わりに心臓に毛が生えまくってるとか
333 :
デフォルトの名無しさん :2008/02/06(水) 04:31:06
http://www.research.att.com/~bs/bs_faq2.html#delete-zero > C++ explicitly allows an implementation of delete to zero out an lvalue operand
これ訳すと
「C++ は delete の実装が左辺値である対象をゼロにすることを明示的に許している」
ってことだよね?
int* p = new int;
delete p;
delete した時点で p == 0 になるような実装もアリってこと?
規格見てもそんなことしていいなんて記述は見当たらなかった。
それとも、ただの読み違い?
そうだよ。 auto_ptrあたりなんかはそれを頼りに実装してる
食い違ってるような
許しているだけなのにそれを頼りにしちゃいかんのでは。
便利のようでそうでもないかな。変な副作用はなさそうだから気にしないでおこう。
cmake( crossplatform make) 使ってる人ってあんまりいないんですか? みんな普通にMakefile直接書いてるの? Windows 上にVirtual Machineでlinuxいれてlinuxとwindowsいったりきたりして開発が 以外と便利と思ったのだけど
Makefileを作ってくれるツールがあったような気がするが、誰か名前教えて
automake
void Register(T* p); // newされたばかりの所有権フリーのポインタを受け取りたい boost::scoped_ptr<T> ptr(new T); Register(ptr.get()); // セマンティックエラーだがコンパイルは通ってしまう この問題を解決するために、Registerの引数をshared_ptrにしていたのですが、 ポインタを共有するわけではないのに、shared_ptrはオーバースペックではないかと気になりました。 うまい方法はないですか?
>>341 要するに Register 関数に所有権を移動させたいのよね? なら
void Register(std::auto_ptr<T> p);
にすれば解決するような気がする
343 :
341 :2008/02/07(木) 10:43:54
>>342 レスthx。
Register(std::auto_ptr<T>(new T));
という書き方ができないのは諦めるしかないですかね。
>>343 そういう書き方は普通にできるよ?
# もちろん T が何か具体的な型になっているとして
345 :
341 :2008/02/07(木) 12:25:13
std::auto_ptr<T> func() ; void f() { std::auto_ptr<T> p = func() ; } こんなこともできるだよ。 別のクラスをひとつ中継させてるだよ。
コピーコンストラクタが非constなのは当たり前でしょ。 コンストラクタなんだから。
非constな参照引数に一時オブジェクトは渡すのは規格ではダメだよね。 auto_ptrのコピーコンストラクタって非constな参照を受け取るよね。 ということは void Register(std::auto_ptr<T> p); Register(std::auto_ptr<T>(new T)); みたいな書き方はダメなんじゃないか?
349 :
341 :2008/02/07(木) 13:30:47
>>346 ああ、戻り値も一時オブジェクトでしたね。
そう思うと一時オブジェクトがコピーできるように作ってあって当然に感じます。
auto_ptr_refというクラスで解決してるわけですね。
>>347 よく読んでください><
どうもありがとうございました。
>>349 そうだね。
実際、一時オブジェクトから生成するときは
通常のコピーコンストラクタは使われないね。
auto_ptr_ref経由で変換→変換で
最終的には
auto_ptr(auto_ptr_ref<T> rhs) throw()
: ap(rhs.yp) {
}
というコンストラクタで生成される。
char *ptr = (char*)new int[0xFF]; delete[] ptr; 実際に delete[] する型は違いますが、確保したメモリは全て開放されますか?
>>351 >In the second alternative (delete array)
>if the dynamic type of the object to be deleted differs from its static type,
>the behavior is undefined.
ってことだから、未定義動作じゃないかね
未定義動作だろ
すまん、誤爆しちゃったんだが元々こっちに書くつもりだったんで聞きたい。
http://pc11.2ch.net/test/read.cgi/tech/1202141921/128 //------------------------------------//
メモリが解放されてるかどうか確認する方法ってなんかあるかな?
void a( void* p ) {
if( rand() %2 ) delete p;
}
void main () {
char*pc = new char[100];
a(pc);
// pcが解放されてなかったら解放
if( soreppoino( pc ) ) delete pc;
}
みたいな。
//------------------------------------//
まぁ普通はしねーけど、MFC使ってるアプリがDRV_CLOSE送る前に
メモリ解放しちゃうっぽいから判定しなきゃいかんくなってさ。
結局はアプリ終了中か否かで判定したんだけど、まあそれはいいんだ。
聞きたいのはこういうのってあるかな?ってこと。やっぱないかな?
でもそうなるとVC6のメモリウィンドウの「??」ってどう判定してんのかが分からん。
誰かここら辺知ってる人いたらおせーてくだせい。
標準には無い。 環境依存ならスレ違い。
MFCに解放されないようなメモリ確保の手段を使えばいい。
>>354 向こうの133に的確な答えが書いてあるじゃないか。そういうことができるクラスを作ればいいんだよ。
なんかもの凄く間違った方向に突っ走ってるような。
コンストラクタ内で、thisポインタを他のクラスに渡すことについて質問です。 コンストラクタは、オブジェクトを安全に使うための準備であると考えると、 thisポインタを他のクラスに渡すことは、安全に使うための準備が完了してないオブジェクトのメンバ関数を呼び出す手段を与えることになり、 危険ではないかと思うのですが、この方法は一般的に使われているのでしょうか?
thisポインタを渡したクラスがコンストラクタが終了する前にthisの中身(つまり、コンストラクト中のオブジェクト)を変更/参照したりしないのなら問題ねーだろ。
361 :
359 :2008/02/08(金) 15:37:24
>>360 ありです。
渡す側は、渡す相手が変更/参照しないかを、
もらう側は、変更/参照しないことの保障を、気をつければOKですか。
362 :
デフォルトの名無しさん :2008/02/08(金) 17:04:33
template限定子とやらを初めて知ったんですが、 どういうケースで必要なのかいまいちわかりません
template限定子を書かなければエラーになる時
>>362 依存名.???<....>
依存名->???<....>
のような場合に最初のangle bracketsはless than operatorなのか
templateの始まりなのかをコンパイラに知らせる必要がある。
依存名.template ???<....>
依存名->template ???<....>
>>359 VCだと警告が出る。しかし便利。よく考えて使う。
>>362 ,364
でも「プログラミング言語C++」中の限定子が必要な例をVC8に
食わせると限定子が無くても通る、というか限定子を付けると
エラーという(w
VS2008 では知らないけど。
>>366 テンプレートに関してコンパイラベンダー固有の問題
があることは常識。そんなもんは勝手に調べろってこった。
コンパイラによって切り替わるマクロを定義して対処するのは常識。 同様の目的で使われる typename も同様。
MSが糞なのは常識
VC8 でも通らなかったっけ?
BOOST_WORKAROUND(BOOST_MSVC,... で埋め尽くされているBoost
スコットメイヤーズはBON JOVIに似ている
日本人はC++標準化委員会に入れないの?
374 :
362 :2008/02/08(金) 20:45:14
>>364 おぉなるほど!
コンパイラの気持ちにならないといけないんですね
typenameとかもそうですね
template 限定子はポリシーを入れ子にするときとか使うよね。
fatal error LNK1104:コンパイラは、ファイルd3d9.libを開けません とでてしまいビルドできません 手動でリンカにd3d9.libを設定しましたが無理でした どなたか助けて
378 :
376 :2008/02/09(土) 00:18:21
他で聞いてきます
エスパーすると、cppとかのソースファイルが置いてある所にd3d9.libを置け
いいのかそれで?
Visual C++で使える任意精度数値計算ライブラリはありませんか? もしくは、Linux用に書かれた(?)ライブラリをVisual C++で使うための 一般的な手順・方法というのはあるのでしょうか。 任意精度数値計算ライブラリとして apflot, gmp 等を使えばよいらしいことまでは分かったのですが インストールの手順で configure、nmake 等のLinux系の単語が頻出し困惑しています。 こういうものはVisual C++では使えないのでしょうか。
383 :
381 :2008/02/09(土) 12:17:06
>一般的な手順というものはない これが分かっただけでも、よかったです。 お早い返答ありがとうございました。
Linux系にカテゴライズされたnmakeにちょっとだけ同情した
int i = 0; int* void F() const{ return &i; } が通らないんだけども、 Fの中じゃ何も変更してないのに、ポインタを返すものにはconst付けられないの?
>>385 途中の void はなんだ?
あと const 付きの関数はクラスの非 static メンバとしてしか宣言できないよ。
ごめんなさい。適当に端折りすぎました。 struct S{ int i; int* F() const { return &i; } }; S Sobj; Sobj.F(); が通らないんです。 const int* から int*に変換できないとかで。
const付き関数の中では、メンバ変数に全てconstがつくと思えばいい。 constオブジェクトからメンバ変数を非constで参照できたらまずいだろ。 試してないけど、workaroundは以下。 const int * F() const { return &i; } int F() const { return i; } mutable int i;
>>387 Sobj.F();の呼び出しによりメンバー関数int* F() const;は
は以下のようにコンパイルされようとする。
//pseudo code
int* F(const S * const this) //result in compile error
{
return (&(this->i));
}
thisは constオブジェクトへのポインタゆえにthis->iの型は
const int となり、その結果 &(this->i) の型は const int*
となる。関数の戻り値は初期化のsemanticsであり、
int*をconst int*で初期化することはできないからコンパイルエラー。
constの有無で多重定義可能だから、こういうこともできる。 int* F() { return &i; } int const* F() const { return &i; } std::vector::operator []なんかがこういうことをやっている。
似たような関数を2つ定義することになるから 片方はキャストを駆使してもう片方を呼ぶようにしましょうってフサフサが言ってた。 tp://www.aristeia.com/images/sdm-big.jpg
数少ないconst_castの出番
サンクスです。
つーかすげーな、、、
>>389 みたいなことはどうやったら解るの?
コンパイラでも一度書かないと無理かな。
規格書を読むとか
コンパイラコンパイラつくりゃそりゃかなり勉強になるだろな。
でもその前に絶対
>>395 だな
>>394 どう動いてるのかを普段から考えてればいいのさ。
1年も続けてれば大体の事は分かるようになる。
関数オーバーロードはコンパイラの気持ちにならないと難しいね
自分で実装するならどうするか、とか。
あれくらい規格書にあたらなくても、ちょっとましな本を読めば書いてあると思う。
確かに考えればわかるけど、自信もって答えれるレベルまではなれない・・・ 確信が持てるレベルまで行くには、やっぱ規格まで手を出さないといけないんじゃない?
10数年くらい前は内部モデルを詳細に解説した書籍が 結構あった(ほとんど洋書)んだけど最近はめっきり無いね。 残念なことだ。
オレもADL位はちょっとわかるけど、その副作用とか人に説明できるレベルには理解してないな・・・
//type.1 vector<BigSizeClass> GetHoge(){ vector< BigSizeClass> tmp; // 非同期の要求を処理した結果を、いろいろtmpに追加 return tmp; } を vector<BigSizeClass> result = GetHoge(); と使うのと、 //type.2 void GetHoge( vector<BigSizeClass> &tmp ){ //tmpに色々追加 } を vector<BigSizeClass> result; GetHoge( result ); と使うの、どっちがいい? 一応、2番を使ってるんだけど、 なんか戻り値を使わず、参照を引数で渡して結果を得るのがC++じゃないなぁというか、気持ち悪いって思っちゃう。
>>406 わざわざ BigSizeClass なんて書いてるんだから結論は出てるんだろ?
参照引数に結果を詰めるなんて C++ (98~2003) ではよくあること。
あと、 2 の関数を使って 1 の関数が実装できるから、効率が許すときだけ
1 の方を使うのもアリかもね。
>>406 type1でいいんじゃない?
コードでパフォーマンスを見積もるなら、
BigSizeClassのコピーコスト、
GetHoge()の呼び出し頻度、
vectorの要素数
くらいないとわからんよ。
構造体を継承したクラスは可能なんでしょうか? typedef struct _test { int count; } test; class extest : public test { public: extest(int i) { count = i; }; virtual ~extest() {}; int getCount() { return count; } }; int main(int argc, char* argv[]) { extest ext(10); printf("getCount:%d\n", ext.getCount()); return 0; } VC++2003では動作するのですが、C++仕様として合ってるかどうかが 不安で…。
>>409 継承すること自体には問題ない。
ただし new extest(...) で生成したオブジェクトを test* を使って delete は
できないことに注意。このため private 継承にしてもいいなら、そっちのほうが安全。
あと、その例の構造体名 _test は予約名になるから、素直に struct test にしておくこと。
>ただし new extest(...) で生成したオブジェクトを test* を使って delete は >できないことに注意 ??なんで? 例のtest構造体なら仮想デストラクタもいらないし・・・
>>411 5.3.5 Delete p3 より
"if the static type of the operand is different from its dynamic type, the
static type shall be a base class of the operand's dynamic type and the static type shall have a virtual
destructor or the behavior is undefined."
>>412 _test に仮想デストラクタ持たせれば済む話だと思う。
>409-410 だと struct なのが問題の原因に見えるけど、 本当は test が virtual なデストラクタを持ってないのが原因ってことか。
1. _test に仮想デストラクタを作る 2. _test を private あるいは protected 継承する この2通りだな。 というか、構造体にする必要もないと思うのだが。
416 :
409 :2008/02/11(月) 20:11:30
>410-415 test構造体に仮想デストラクタを入れると、newした場合も _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)というエラーは出なくなりました。 ただ、継承したい構造体が他のC言語ライブラリが提供するものなので、 継承ではなく包含の方向で考えていきたいと思います。 どうもありがとうございました。
ついでに言うとグローバル名前空間内で _ が先頭につく識別語は 処理系用の予約語だから、_test じゃなくて test_ にしとけ。
>>416 包含がアリなら private 継承も考えたほうがいいかもね。
_BLOCK_TYPE_IS_VALID の assert は問題の未定義動作を捕まえて
くれてるのかな?
まあ、包含でいいなら包含でいいと思う。 無理に継承しなくても。
メイヤーズが言ってたis implemented in terms of関係か。 継承せざるを得ない場合をのぞいては、包含のほうが良いと言ってたな。
421 :
416 :2008/02/11(月) 21:17:01
>>417 なるほど、了解しました。
>>418 すいません、private継承で動作確認した時に delete (test*)pext; のように
して同様のアサートが出てたんですが、 delete static_cast<test*>(pext);
とすることでコンパイル時チェックがかかるようになりました。
ただ、C言語ライブラリ側で構造体をmalloc/freeで確保/破棄するように
なっていて、継承を用いた場合、クラスと構造体双方のインスタンスの
生存期間の管理が複雑になりそうに思えたこともありましたので…。
_BLOCK_TYPE_IS_VALIDのassertはやはり仮想デストラクタが未定義と
いうことを示しているようです。
>417-420
あらためて、ありがとうございました。
private 継承で test* にキャストできるか?
まあ、それはそうだけど。
>>409 class extest : public test
{
private:
test* ptr;
...
にしたほうがいいんじゃないか?
426 :
425 :2008/02/12(火) 08:34:14
継承が残ってた
>425
>>409 class extest
{
private:
test* ptr;
...
にしたほうがいいんじゃないか?
仮想関数が無ければ継承する意味は無いだろう
>>427 protectedメンバーにアクセスする状況もある。
それを言うなら「継承以外の選択肢があれば、無理に継承する必要はない」だな
boost::noncopyable
>>406 ちょっと遅レスだけど、俺も前に同じこと悩んだ。
それで考えたのがmove semanticsっぽい感じでtype.1のコピーコストを無くす方法
template<class T> class move_val {
T v;
public:
move_val(){}
move_val(move_val<T>& o){ swap(v,*o); }
move_val(T& o){ swap(v,o); }
void operator=(move_val<T>& o){ swap(v,*o); }
void operator=(T& o){ swap(v,o); }
T& operator*(){ return v; }
};
move_val<vector<BigSizeClass> > f1(){
vector<BigSizeClass> v;
v.push_back(BigSizeClass());
v.push_back(BigSizeClass());
return v;
}
void f2(){
move_val<vector<BigSizeClass> > v1 = f1();
move_val<vector<BigSizeClass> > v2 = v1;
cout <<"v1:"<<(*v1).size()<<" v2:"<<(*v2).size()<< endl;
}
テンプレートを使ってでかいメモリ領域を効率よく移動させるためのラッパークラス
>>433 経緯から。
vector<BigSize> v1;
//vに要素追加
//v2=v1 は v2=f1()と基本的には同じ。
//ここでv1の中身まるごとコピーされる。
//コピー重杉氏ね。
//でもv2がこの先生きのこればv1はいらない
vector<BigSize> v2 = v1;
//swapすればおk
vector<BigSize> v2;
swap(v2,v1);
//毎回swap書くの面倒だしv2=v1みたいに書きたい。
//なのでコピーコンストラクタ・代入演算子で
//勝手にswapするテンプレートを用意
void f2(){
//f1()で作られたvとv1がswapされる
//vは空になる
move_val<vector<BigSize> > v1 = f1();
//v1とv2がswapされる
//v1は空になる
move_val<vector<BigSize> > v2 = v1;
//最終的にf1()内で確保されたメモリはv2が責任を持つ
cout <<"v1:"<<(*v1).size()<<" v2:"<<(*v2).size()<< endl;
} //v2死亡、f1()内で作られた要素が破棄されメモリも解放
436 :
435 :2008/02/13(水) 12:07:33
補足。 非const参照引数だと一時オブジェクトを受け取れなかったりするけど VC++だとコンパイル通るので↑では気にしてない。 ちゃんとC++するならauto_ptr_refみたいな proxyを経由させないといけない。
Mojoったらいいのに。
それなんてMOJOって書こうとしたら先に書かれてた
復習をかねて、Mojo っぽく書いてみた。 template <typename T> class Vector; template <typename T> class TemporaryVector { public: explicit TemporaryVector(Vector<T>& v) : v_(&v) {} Vector<T>& get() { return *v_; } private: Vector<T>* v_; }; template <typename T> class Vector : public std::vector<T> { public: Vector() {} Vector(TemporaryVector<T> tmp) { std::swap(*this, tmp.get()); } operator TemporaryVector<T> () { return TemporaryVector<T>(*this); } }; TemporaryVector<BigClass> f1() { Vector<BigClass> v; v.push_back(BigClass()); return v; } int main() { Vector<BigClass> v = f1(); std::cout << v.size() << std::endl; }
コンテナ自体も型パラメータ化して、 vectorに限定しない形で書いてもらえると嬉しい・・・
>>441 Mojoっての知らないからお願いしてみたけど、
考えてみたら超簡単だったw
スマン。
ところで、実行してみたんだけど、これどこかバグってない?
f1の戻り受け取りでコピーコンストラクタ動いちゃうのと、
その際、デストラクタ後のインスタンスが参照されるんだけど・・・。
f1の戻り値のローカルなVector<BigClass>オブジェクトを explicit TemporaryVector(Vector<T>& v) : v_(&v) {} で変換するときに、もうゴミになってるポインタを設定 してるとか?
Modern C++ Designだが、2章のCompileTimeCheckerを使った マクロでいきなりコンパイル通らなくて、やる気を削がれるんだけど。 みんなどうした?
本が出版された当時はsizeofに関数呼び出しをパラメータに 渡せたのか?
struct One { char x ; } ; struct Two { char x[2] ; } ; One f(int) ; Two f(...) ; void v() { std::cout << sizeof( f(hoge) ) << std::endl ; } こういうやつか?
>>446 いや、それは戻り値に評価されるから合法だと思うんだ。よくやるよね。
そうではなくて、コンストラクタの呼び出しをsizeofの引数に渡してる
んだよね。こういうやつ。
template<bool> struct CompileTimeChecker {
CompileTimeChecker(...);
};
template<> struct CompileTimeChecker<false> {
};
//macro definition
#define STATIC_CHECK(expr, msg) \
{ \
class ERROR_##msg{}; \
(void)sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg()))); \
}
sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg())));
が怒られる。
で、こういう風に使う。 template<typename To, typename From> To safe_reinterpret_cast(From from) { STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow) return reinterpret_cast<To>(from); } int _tmain(int argc, _TCHAR* argv[]) { int i = 0; int* somePointer = &i; char c = safe_reinterpret_cast<char>(somePointer); return 0; }
449 :
デフォルトの名無しさん :2008/02/13(水) 19:02:37
streambufを複数のストリームで共有することは可能ですか? 本来ストリームを操作することを想定していない関数の中で 書式を設定してメッセージを出力したいのですが、 copyfmtで書式の情報を退避するのも例外対策などを考えると面倒なので、 次のように書きたいのです。 #ifdef DEBUG std::ostream(std::cerr.rdbuf()) << "f(x)=" << std::setprecision(6) << f(x) << std::endl; #endif
>>449 tight couplingのことでしょ?
(ストリームバッファの共有)
できるよ。
ostream prec6_cerr(cerr.rdbuf());
prec6_cerr.precision(6);
prec6_cerr << "f(x)=" << f(x) << endl;
これでcerrとprec6_cerrは同じバッファを共有するけど
フォーマットはstreambufではなくostreamに設定される
から別個のフォーマット扱えるとオモタ。
>>447 これって違法なのかねえ。
よく分かんないや。
とりあえず、
sizeof(CompileTimeChecker<(expr) != 0>((ERROR_##msg())));
を
sizeof((CompileTimeChecker<(expr) != 0>)((ERROR_##msg())));
にすればいけるね。
関数風キャストから C 風キャストに変更しただけだが。
>>432 の方法でtype.1のコピーコスト消えるの?
>>451 thx。なるほど。
>これって違法なのかねえ
Comeauでもハッキリとコンパイルエラーになるんだよね。
static_castで行くことにする。
(void)sizeof(static_cast<CompileTimeChecker<(expr) != 0> >((ERROR_##msg())));
あと、何故sizeofの結果をvoidへキャストする必要があるかだけど、
もしキャストしないとComeauでは警告が出る。何でvoidへキャスト
すると警告が消えるんだろう?
キャストを省略した場合は以下の警告。
"ComeauTest.c", line 15: warning: expression has no effect
STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow)
^
まあ、でもよくこんなこと考え付くわ。面白いけど使いどころあるかな。
0; とかいう式と似たようなもんだから、 void でキャストして明示的に値を捨てないと 警告出すコンパイラもある。
>>449 boostのio_state_savers使うのがオススメ
>>454 なるほど。
voidへのキャストって値を捨てるという意味になるのか。
void*はよく見るけど、生のvoidってあまり見ない。
しつこくてすまんが、明示的に値を捨てるという使い方も
voidの機能の一つなんですか?
C++ではあまり見掛けないけど古いCのコードにはよくある。
>>456 うい。例えば
#define STATIC_ASSERT(expr) ((int(*)[(expr) ? 1 : -1])0)
こういうタイプの静的アサーションマクロがあったとすると、
int (*p)[1] = STATIC_ASSERT(true);
みたいにしてその値を使えてしまう。
そこで、
#define STATIC_ASSERT(expr) ((void)(int(*)[(expr) ? 1 : -1])0)
と void にキャストすると、そういうことができなくなる。
>>457 printf の戻り値を void でキャストして捨てないと
コードチェックに引っかかることがあるというアレか。
>>457 今考えると、
洒落たテクニックの部類に入りますかね。
>>458 確かに、exprがtrueでヌルポインタ定数0を配列へのポインタ
(int(*)[1])0
に変換できると、今の場合は型が一致するから代入できてしまう。
そこで、voidが不完全型でvoid型変数は定義できないし、どんな型
とも代入互換性が無いことを利用してエラーにすると。
ありがとうございました。よく分かりました。
461 :
デフォルトの名無しさん :2008/02/14(木) 00:36:45
>>459 そういえば
sprintf(buf,…);
len = strlen(buf);
というコードを書くバカが多いよな。
案外最初に習得する関数だと、manとか見ないんだよな。 特にprintf系は機能多すぎだし、読むのメンドウで。
MOJOとMove Constructorって別物?
同じじゃね? どっちにしろC++09で右辺値参照入れば用済みさ。
Boost.Moveを頑張って使ったが コンパイラの最適化で十分らしく何の効果もなかった
どう使ったのかkwsk
>>452 struct BigSizeClass {
int n;
BigSizeClass(int arg_n):n(arg_n){
cout << "BigSizeClass("<<n<<" : "<<this<<")" << endl;
}
BigSizeClass(const BigSizeClass& o):n(o.n){
cout << "copy BigSizeClass("<<n<<" : "<<this<<")" << endl;
}
void operator=(const BigSizeClass& o){
n=o.n; cout << "operator=("<<n<<" : "<<this<<")" << endl;
}
~BigSizeClass(){ cout << "~BigSizeClass("<<n<<" : "<<this<<")" << endl; }
};
のようにしてトレースすれば分かる、最後のpush_back以降に
BigSizeClassのコンストラクタや代入は発生しない。
vectorのswapはポインタとサイズの交換なので要素や要素数に関係無くすぐ終る。
ちなみに
>>465 の言う通り、v1 = f1();のような所は
戻り値の最適化で、普通にvector直に使っても余計なコピーが消えたりするケースもある。
※v1に直にpush_backしてるみたいになる。
std::unique_ptrとstd::moveが待ち遠しい。
コンテナの選択に困りました。 ・ポリモフィズムしたい ・挿入/削除が高頻度 ・何種類かのソートが高頻度 理想はboost::ptr_containerを使ったboost::multi_indexだと思うんですが、どうやらありません。 どのコンテナを使うべきだと思いますか?
>>469 コンテナの具体的な用途に絞れば ptr_container が担当する部分を自分で書くのは
あまり難しくないだろうから、ポインタを要素型にした multi_index かな。
471 :
デフォルトの名無しさん :2008/02/14(木) 08:42:25
>>469 std::vectorでじゅうぶんだろ
472 :
469 :2008/02/14(木) 09:46:52
レスthx
>>470 ptr_containerを使えないのは残念ですが、その方法になってしまいますか。
>>471 vectorを使うなら、ptr_vectorを使いたいです。
>>469 ソートが高頻度という要件で multi_index は要らんだろ。
何種類かのキーによるアクセスが高頻度ということなら欲しくなるけど。
multi_index が要らないなら ptr_list かな。 >470 と同じ理由で std::list で
十分とも言えるそうだけど。
474 :
469 :2008/02/14(木) 10:27:06
>>473 "何種類かのソート"と書いたのは、std::sortに渡す関数オブジェクトが何種類かあるという意味です(連想配列ならキー)。
std::vectorやstd::listで十分というのは、
ptr_containerを使うよりstdのコンテナを使うメリット(というよりptr_containerのデメリット?)が何かあるんでしょうか?
>>474 std::sort
だったらランダムアクセスイテレータを持つコンテナに
限定されてしまわないかい?
476 :
469 :2008/02/14(木) 11:00:26
>>475 std::sortを絶対に使わないとダメというわけではなくて、std::sortを使えるコンテナにstd::sortを使った場合の話です。
listならメンバ関数のsortを使えばいいし、mapなら(複数のキーでアクセスしたいので)multi_indexですね。
std::vectorみたいにランダムアクセスできて、かつメモリ領域が連続していなくてもいいコンテナってありますか? 要するに要素本体はどこか別のところに保持しておいて、それへのアクセス用ポインタをstd::vectorに突っ込んであるというような。
「要するに」の前後で要件が異なってるような気もするけど、 どちらを探してるの?
2行目はともかく、1行目はstd::dequeでいいよな。
2行目ならboost::ptr_vectorかな。
2つ併せて、boost::ptr_deque じゃない?
wchar_t* Replace(wchar_t* src, wchar_t* before, wchar_t* after){ size_t src_length = wcslen(src); //元文字列の長さ size_t before_length = wcslen(before); //検索文字列の長さ if(src_length < before_length || before == L"" || before == after) return src; size_t after_length = wcslen(after); //置換文字列の長さ int shift = after_length - before_length; //置換による移動数 wchar_t *start = src; //検索開始位置 wchar_t *hit; //見つかった位置 int match; //マッチ回数 //マッチ回数を求める for(match = 0; (hit = wcsstr(start, before)) != NULL; match++) start = hit + before_length; if(match == 0) return src; //長くなる分だけメモリを確保 if(shift > 0){ wchar_t *tmp; if((tmp = (wchar_t *)realloc(src, (src_length + shift * match + 1) * sizeof(wchar_t))) != NULL) src = tmp; else return src; } //置換部 start = src; for(int i = 0; i < match; i++){ hit = wcsstr(start, before); wmemmove(hit + after_length, hit + before_length, wcslen(hit) - before_length + 1); wmemmove(hit, after, after_length); //置換 start = hit + after_length; //次の検索開始位置 } return src; }
非MFC環境下で文字列の置換を行えるようにするために
wchar_t型の、(原文, 検索ワード, 変換ワード)を指定すると
まず原文中に検索ワードが何回出てくるかを調べ
置換後に文字列が長くなる場合はその分メモリを追加確保し
その後検索ヒット回数だけ置換を行うという
>>482 の関数を下記のように使いたいと思い
size_t text_length = GetWindowTextLengthW(edit) + 1;
wchar_t *src = new wchar_t[text_length];
GetWindowTextW(edit, src, text_length);
SetWindowTextW(edit, Replace(src, L"a", L"aa"));
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ひとまずそれっぽく動くようにはなったのですが、いくつか質問がありまして、
1,まず第一に整合性が保たれているかという点
置換後に文字数が変わる置換や、「ソ」で文字化けする問題は大丈夫でしたが、
その他特定の場合にエラーが出る可能性はありますか?
2,原文"aaa" 検索ワード"a" 置換ワード"" とした場合
結果は""となりますが、このとき短くなる分だけ
reallocでメモリ幅を縮めたほうが良いのでしょうか?
(縮めてみようかと思ったところエラーが出たので、現在は長くなる場合しかreallocしてません)
3,VC++6.0でコンパイルしていますが、これはWin9x系でも正常に動くのでしょうか?
(Win9xでwchar_t型が一部動かないというのを見たので)
4,検索ループと置換ループを分けたのは、
reallocを一度で済ませる事で速度的に向上が見られたためなのですが、
まだ文字数が増えたときの変換が遅い気がするので
他に速度を早くする方法があれば教えてください。
よろしくお願いします。
>>483 _TマクロとSTLのstring/wstringを使って、Unicode版とMBCS版を作ればいいんじゃないか?
RVOが出てきちゃって
>>432 の方法がうまくいかん
>>485 非const参照の一時オブジェクトで怒られるとかじゃなくて、RVOで?
RVOがあってもv2=v1;には影響ないはずだけど・・・。
#include <vector>
#include <iostream>
#include <tchar.h> //_tmain
#include <conio.h> //_getch
using std::vector;
using std::cout;
using std::endl;
using std::swap;
#include
>>467 template<class T> class move_val {
T v;
public:
move_val(){}
move_val(move_val<T>& o){ swap(v,*o); }
move_val(T& o){ swap(v,o); }
void operator=(move_val<T>& o){ swap(v,*o); }
void operator=(T& o){ swap(v,o); }
T& operator*(){ return v; }
};
move_val<vector<BigSizeClass> > f1(){
vector<BigSizeClass> v;
v.reserve(2);
v.push_back(BigSizeClass(0));
v.push_back(BigSizeClass(1));
cout <<"--push end"<< endl;
return v;
}
488 :
続き :2008/02/15(金) 05:58:32
void f2(){ move_val<vector<BigSizeClass> > v1 = f1(); move_val<vector<BigSizeClass> > v2 = v1; cout <<"v1:"<<(*v1).size()<<" v2:"<<(*v2).size()<< endl; } int _tmain(int argc, _TCHAR* argv[]) { f2(); _getch(); //デバッグ実行でコンソールを残すため return 0; } 結果 BigSizeClass(0 : 0012FC6C) copy BigSizeClass(0 : 00368BA0) ~BigSizeClass(0 : 0012FC6C) BigSizeClass(1 : 0012FC78) copy BigSizeClass(1 : 00368BA4) ~BigSizeClass(1 : 0012FC78) --push end v1:0 v2:2 ~BigSizeClass(0 : 00368BA0) ~BigSizeClass(1 : 00368BA4) 一応VC++2005 Expressでのソースと実行結果を。 push end後にコピーは起こらず、v1も空になり、v2破棄で中身が破棄される。
ちょっと修正。
VC++2005 Expressだと非const参照で一時オブジェクトを受けても
コンパイル出来てしまうけど、(本当はエラーが正しい)
警告レベル4(/W4)にすれば指摘されるように出来たので、
auto_ptr_refみたいに代理経由するようにした。
>>487 のmove_valを修正
template<class T> class move_val {
... //T& operator*()まで省略
//非const参照で一時オブジェクトを受け取る対応。
template<class R> struct tmp_ref { R* p; tmp_ref(R* ap):p(ap){} };
move_val(tmp_ref<move_val<T> > r){
cout<<"ref受け取り:"<<r.p<<""<<endl; //確認用
swap(v,r.p->v);
}
void operator=(tmp_ref<move_val<T> > r){ swap(v,r.p->v); }
operator tmp_ref<move_val<T> >(){
cout<<"ref化:"<<this<<""<<endl; //確認用
return tmp_ref<move_val<T> >(this);
}
~move_val(){ cout<<"~move_val:"<<this<<""<<endl; } //確認用
};
swigってstlのvectorなどには対応してるみたいだけど boost.ublas.matrix とかは対応してるの?
491 :
483 :2008/02/15(金) 12:11:22
>>484 stringを使っていないのは、
GetWindowTextからSetWindowTextまで型変換をせずに済ませたいためです。
また、Unicode版・MBCS版と2種類作らずに、
1つのプログラムでNT系+9x系と使える方法を考えてます。
>>491 デストラクタにメモリの解放を任せるため、
それでも vector くらいは使った方がいいよ。
あるいは realloc とか使うのであれば、
自作のコンテナかスマートポインタかを作るか。
vector で受ければ、要素の挿入も自動で出来るからプログラム楽だし。
ただ、メモリを縮小することは基本的にはできないかな。
(resize でメモリ少なくしても、メモリの再確保は行われない)
もう1つバッファ作ってそこにコピーするならいけるけど。
wstring で受けた方が replace メンバ関数があるから便利だけど、
メモリの連続性は多分全てのコンパイラで保証されてるとは思うけど、
ヌルターミネータの扱いがどう実装されてるか
(常にヌルターミネータを付ける実装になっているか、
それとも c_str 実行時にヌルターミネータを付ける実装になっているか)
の問題がよく分からないので、やめといた方が無難。
あと、効率を求めるならまた他の実装もあると思う。
その他の特定の場合にエラーが出るかどうかは、
Replace の中身次第やね。これ以上は何とも言えん。
c++でreallocを使うのは止めた方がいい。 あとシステムのAPIなどはともかく、 内部の加工などで\0終端を前提として書いたり、 前提とする関数を使ったりするのも止めた方がいい。
まあ POD 型を扱う分には realloc 使っていいと思うけどね。 POD 型でも内部に内部へのポインタ持ってたらアレだけど、 それは C でも同じ事だし。
C++だと例外安全考えないといけないからね、
分かった上で使ってる人なら良いんだけど・・・。
realloc使った上で例外安全にするのは別に難しくはないけど、
reallocとかmallocとか使ってるようなCっぽいソースは
大体例外安全でない兆候だと思う。
Cで書かれたライブラリを使う(C++ → C方向のみ)とか、
独自アロケータ実装とかなら大丈夫だろうけど。
それに
>>482 を
>>483 したらrealloc分が普通にリークするし、
483のnewの後、throwする可能性のある関数呼んだら
同じくnew分がリークする。
>>492 がvectorとかスマートポインタ勧めてるのも
そういうことだと思う。
つまるところc++ではデストラクタに頼るべき。
C++はつまるところデストラクタのことだからな closeさせといてガベージコレクタがあるとか抜かす言語は笑えるな intは回収できるが巨大なファイルリソースはリークするわけだ
日本語でおk
>closeさせといてガベージコレクタがあるとか 禿げあがる程同意。 C#はusing(o1,o2,...){}があるから多少マシだけど、 forみたいにusing用のスコープ作るから スコープ違いが混じるとネストして見辛くなる。 どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。 javaのtry-finally-closeに至っては論外。 しかもcloseで例外出たらfinally内で潰さないと try内で発生したより重要な例外が消されるし・・・。
>どう考えてもc++みたいに対象の変数のスコープでDisposeした方が良いと思う。 そして言語はC++/CLIへと進化するのであった、まる
using Hoge hoge = new Hoge(); とか Hoge hoge(); とかと書かせるようにすれば良かったのにね。C# も。
502 :
デフォルトの名無しさん :2008/02/15(金) 21:28:46
>>469 比較関数が例外を投げないんだったら、比較の順序ごとに
std::set<Base *, Compare>を用意して挿入関数を注意深く書けばいい。
multisetにすると削除のとき最悪O(N)の時間がかかるから、
比較関数にポインタの比較を入れてsetで扱う。
比較関数が例外を投げる場合、同じ方法だと削除関数が
例外を投げることになって相当扱いにくくなる。
OpenBSDのtree.hみたいのを使って侵入型コンテナにするのが現実解かな。
無名名前空間ってちゃんと働く? vc8で // hoge.hpp namespace { class A { public: A() {} }; } // main.cpp #include "hoge.hpp" int main() { A a; } でmain.cppからAにアクセスできてしまうけど。 なんか理解がおかしい?
インクルードしたらアクセスできて当然だろう・・・
無名名前空間ないのクラスは同一ファイルのものからじゃないとアクセス できないってみたけど。 というかmain自体が無名名前空間で定義さてれいてAが見えるってことか?
>>505 同一ファイルじゃなくて同一コンパイル単位
インクルードしてたら同じコンパイル単位に含まれるよ
#includeの行を消して、 代わりに.hppの中身全体をその場所にコピペしてみろ。 #includeとはそういうことだろ?
>>509 要はstatic変数の代用だ
Cではグローバル変数が他のコンパイル単位とぶつからないようにstatic変数ってものがあったが、
static構造体とかstatic typedefといったものはなかった
C++では無名名前空間がそういった役割を果たす
もちろん従来のstatic変数も残ってはいるが
>>509 不正確な記事だな。著者に連絡しとくといいよ。
>>511 コンパイラはプリプロセッサの処理の後に動くから、
そういう風に考えれば同一ファイルのみと考えていいんじゃね
>>509 a.cppとb.cppがそれぞれコンパイル単位内で使うために
class Foo {
void f();
};
void Foo::f() { ... }
のように定義すると、リンクのときにFoo:f()が衝突してしまう。
typedefや構造体の定義そのものはコンパイル単位内で完結しているから、
Cの場合は関数、変数にstaticを付けるだけで衝突を防げたけど、
C++の場合普通の関数、変数の他にクラスのメンバ関数やstaticメンバ変数があるから、
それらがリンク時に衝突しないように無名名前空間が考案された。
「MOJO」ってのはただ単に一時オブジェクトを移動させるためのもので、 「swapで交換」とはまた別? ぁー理解できんorz
C/C++でプリプロセッサ命令以外でファイル単位と言ったら、 それはつまりコンパイル単位のこと。 プリプロセスとコンパイルは分けて考えないと駄目だよ。 複数のファイルを扱うのはプリプロセスとリンク。 コンパイルは(結合、加工後の)単一ファイルしか扱わない。
>>514 move semanticsの汎用的な実装方法のとして
「デフォルトコンストラクト直後のオブジェクトとswap」がある。
でもauto_ptrみたいにswapでなく、メンバをNULLにするような方法もある。
MOJOはswapで移動させるとか限らない。
・・・って感じじゃない?。俺もMOJO詳しくないけどw
× とか限らない ○ とは限らない
>>512 ,515
そんなんだから >505 みたいな勘違いするんだよ。
入門用の記事なんだから、読み手がコンパイルとプリプロセスを
分けて考えてるとも期待できないだろうし。
>>519 だから何?「ファイル」と不正確な記述にしておいたほうがいい理由でもあるの?
521 :
デフォルトの名無しさん :2008/02/16(土) 10:47:33
>>520 コンパイル単位という専門用語はあまり知られていない。
Cを知っている人の間ではファイルと呼んだ方が通りがいい。
あと、日本語では「〜単位で」が「〜ごとに」という
意味になる場合があって、
「しておいたほうがいい理由」は無い。 しかし、C言語経験者を想定してるなら 「不正確だから修正が必要」という程のことでも無いと俺は思った。 その記事はstaticとexternを引き合いに出してるし、 それらは(特にC言語で)ファイルスコープと呼ばれる上に、 モロ翻訳単位のことだから。
523 :
522 :2008/02/16(土) 10:52:15
だれも修正が必要なんて言ってないんだよ。
C/C++にはコンパイル単位って用語がある。 あまり知られてないとか、ファイルの方が通りがいいとかどうでもいい。 それ以上は自分のブログででも主張したらいい。
そうだね
「連絡しとくといいとは言ったが、修正が必要とは言ってない」 っていう、二次成長期の真ん中へんに居る子みたいな言い逃れが来ると思うよ。
>>525 ブログも2chのレスも大して変わらんよ。
「著者に連絡しとくといい」なんてレスに比べれば
個人的な主張なんてかわいいもんだろ。
というか、「どうでもいい」なんて反論?は止めた方がいいかと。
>>521 専門用語ではあってもstandardで使われているので
重要だと思う。
おれも100%知ってるわけではないけど。
翻訳単位というのはstandardに従えば必ずしも
ファイルである必要はない。たまたま現存する実装ではそうな
っているものがほとんどであるということに過ぎない。
別にヘッダをローカルファイルではなく、データベース、ネットワーク
経由で何らかのconfigurationで展開してもstandard準拠といえる。
上にも書いてる人がいるけど翻訳単位とはプリプロセス
(マクロ、ヘッダの展開etc)終了後のエンティティを指す。
リンケージの話は翻訳単位に対して行うものだと思っている。
実際このくらいは知ってないと理解が難しくなる本もある。
カーニハンやジョスティスの本にも頻繁に出てくる。
著者本人以外が「修正の必要はない」と繰り返し主張する意味がわからない。 もしかして本人なのかもしれないけど。
>>509 が明らかに勉強不足で理解不足だからだろ。
著者のせいにしたければ勝手に連絡すればいい。
別に止めんよ。
それはつまり、他人の「問題」を2chに書き込むのはおかしくないけど、 「問題の無さ」を2chに書き込むのはおかしい、ということ? 俺にはその感性のほうが意味わからないかも。 Xへの突っ込みが変なせいで、X以外の人間に突っ込まれるなんて、よくあることじゃん。 あと、「繰り返し」っていうのは多分、さりげなく「必死だな」って言いたくて書いてるんだと思うけど、 これは単に、「修正が必要だ」っていう意見の子がまず「繰り返し」書き込んでいるから、 それへの反応も複数回になって「繰り返し」になっているだけだろう。
>>532 「不正確」に対する反論がそんなに不思議?
こちらは一応根拠を示しているつもりなんだが、
それに対し、根拠も書かずに件の説明が間違っている前提なのが、
むしろ俺は不思議に思うんだけど・・・。
件の入門記事にある不正確な記述を読んで誤解した人が少なくとも 一人いたのは事実。それを著者が知れば、修正するかもしれないし >512,533 のように判断して修正しないかもしれない。それは著者の自由。 修正が必要だという主張も不要だという主張も同じぐらいに的はずれ。
>>533 509が見るサイトを間違えてる気はするよな。
普通のc++入門サイトとか見た方が良いだろうから。
ところで、ヘッダファイルのみで通じる宣言ってやりたいよなあ。
>>536 上から目線を楽しみたいのはわかったけど、ちょっと変。
「修正が必要だという主張も不要だという主張も同じぐらいに的はずれ」という箇所から察するに、
この件についてどっちでもない立場がある、という前提で言ってるんだよね?
なのに、「修正が必要だという強弁に反論した」だけで、それを「不要だという意見」に括るのはおかしいよ。
右翼の意見に反論したら即左翼かよ、みたいな。
>>535 不正確だというのに反論するなら、件の記事の「ファイル」という記述が正確だ
ということになるが、そうじゃないだろ?
ファイルと翻訳単位では確実に意味が違う。
>>540 今までの、その「不正確」への反論は全部スルーなのは何故?
>>540 で、連絡したの?
別に、連絡することは絶対に許さんぞとか、俺はスーパーハカーだから
もし連絡したらお前を社会的に抹殺してやるぞとか、そーゆーこと言ってるわけじゃないんだから
さっさとすればいいのに。
>>539 どっちでもない立場である「著者に連絡しとくといい」を、
「修正が必要だという強弁」に誤読して反論してた人が
「修正が不要だという意見」を持っていた、というお話。
「ファイルスコープ」 という言葉にも文句を言って欲しい物だな。
>>543 ああなんだ、「お話」の内容を語っていたのか。
やけに現実と異なると思った。
>>541 >525 や >531 は読んでないのか?
2 Lexical conventions p1 The text of the program is kept in units called source files in this International Standard. A source file together with all the headers and source files included via the preprocessing directive #include, less any source lines skipped by any of the conditional inclusion preprocessing directives, is called a translation unit. 翻訳単位はソースファイルであると規格に書かれている。 そして、「ソースファイル」 はまとまったプログラムのテキストであると定義されているだけで、 別に OS のファイルの定義と等しくある必要は無い。
> 翻訳単位はソースファイルであると規格に書かれている。 不正確w
この国際標準規格においては、 ある単位でまとまったプログラムのテキストのことを「ソースファイル」と呼ぶ。 #include 指令によりインクルードされる全てのヘッダとソースファイルと一緒になったソースファイルのことを「翻訳単位」と呼ぶ。 ただし、プリプロセッサ指令により除外される行は除外する。
↓こんな感じかなぁ。 プログラムのテキストはこの国際規格で「ソースファイル」と呼ばれる単位に保持される。 ひとつのソースファイルと #include を通して取り込まれるヘッダやソースファイルを すべて併せ、 #if などでスキップされる行を減じて、「翻訳単位」と呼ぶ。 JIS の訳はどうなってんだろ?
551 :
550 :2008/02/16(土) 13:01:18
うは。被った。
言葉は悪くない。
悪いのは
>>503 を生み出したゆとり教育。
金毘羅様を疑う前にまず自分を疑え。
比較検討しろ。試行錯誤しろ。すぐ2ちゃんに泣きつくな。
規格の話にまで行っちゃったなw有りだけど、入門サイトの話題だぜw 俺としては、 ・c言語経験者前提 ・ファイルスコープという言葉は一般に使われている から、件の文脈でファイル==翻訳単位と分かる。 503、509はサイトの前提には満たなかっただけ。 つまりサイトの選択ミス。 ・c++入門者用のサイト から、厳密性より分かりやすさ優先することは妥当。 と考える。 大体、cユーザーがFILEと言いつつストリームだったりするのはザラ。 翻訳単位はコンパイラにとってストリーム。
一体どう読めば翻訳単位=ソースファイルになるんだ・・ 不思議だな
翻訳単位=加工されたソースファイル
556 :
553 :2008/02/16(土) 13:28:19
補足。 俺は503が悪いとは思ってない。 学習には積み重ね、つまり順序が必要。 2chにレスして、足りない知識に指摘されたなら、その基礎を学べば良いだけ。 まぁ、試行錯誤が重要なのも間違い無いけどね。
「ファイルスコープ」は C の規格で翻訳単位全体にわたるスコープとして使われてたけど、 C++ の規格では使われなくなってるみたい。やっぱり誤解する人がいたからなんだろうね。
558 :
469 :2008/02/16(土) 13:53:47
>>502 thx
比較関数にポインタの比較を含める手法があるんですね。参考になります。
いくつかのコンテナを同期させる手間がかかってしまうのは仕方ないですか。
おはなしにならない
規格の話するのに規格以外のリファレンス持ってくるとかあり得ない
ですよね〜w マイクロソフトとBoostも、 ファイルスコープなんて単語使ってもらっちゃ困りますよねw
CFactoryTemplate g_Templates[]= { L"Dump", &CLSID_Dump, CDump::CreateInstance, NULL, &sudDump }; ↑これってCFactoryTemplateクラスの配列(要素は1個)を作ってL"Dump",&CLSDI_Dump,...をコンストラクタに渡しているってこと? ちなみにCFactoryTemplateはコンストラクタが定義されていないんですけど、こういうのアリなんでしたっけ? class CFactoryTemplate { public: const WCHAR * m_Name; const CLSID * m_ClsID; LPFNNewCOMObject m_lpfnNew; LPFNInitRoutine m_lpfnInit; const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter; BOOL IsClassID(REFCLSID rclsid) const { return (IsEqualCLSID(*m_ClsID,rclsid)); }; CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) const { CheckPointer(phr,NULL); return m_lpfnNew(pUnk, phr); }; };
>>564 Cの構造体や配列の初期化と一緒。
そういう初期化ができる型を集成体と言う。
>>566 そうなんだ。。いままで知らなかった。。
ありがと
>>565 おお、GJ。
>>557 が「やっぱり誤解する人がいたからなんだろうね」
って書いてたから、使わなくなった理由とかを探してた。
それ読んでやっと分かった。
誤解する人がいたから、ではなく、
namespaceが追加されたから、
名前空間スコープ、無名名前空間スコープ(グローバル名前空間)
という上位概念で置き換えたってわけか。
>>568 無名名前空間スコープとグローバル名前空間スコープとは違うスコープだぞ、いちおう。
規格厨消えた?
この場合、どれが規格厨?
573 :
デフォルトの名無しさん :2008/02/16(土) 21:41:48
汎整数拡張の勉強をしていて、intとunsigned intはどうなるのだろうと思い実行してみたところ、 intは予想通りの動作をしたんですがunsigned intがよく分からない動作をします。 unsigned int i = 0; unsigned int j = 0xFFFFFFFF; unsigned int k = 0xFFFFFFFE; unsigned int l = 0xFFFFFFFF; i += 0xFFFFFFFF; printf("i=%d, j=%d, k=%d, l=%d\n", i, j, ++k, +l); これが全部-1になってしまいます。 汎整数拡張とは違うと思うのですが、理由が分かりません。 どうしてこうなるのですか?
>>573 "%d"してるからだろ常考。%uとかprintfの書式調べろ。
あと0xFFFFFFFFというバイトパターンは符号付整数型だと-1を表すからだろ。
575 :
573 :2008/02/16(土) 22:21:54
ありがとうございます! %dは符号付表現だったのですね。勉強になりました。
576 :
デフォルトの名無しさん :2008/02/18(月) 03:45:36
class の変数部分だけを extern C してstruct扱いにしてcから(c++でなくて)参照できますか?
仮想関数テーブルがなければ大丈夫かもしれないが どちらにしろカプセル化を壊すからやるべきでないことだけは確かだ。 アドレスだけ受け取って、 そのアドレスを渡して処理するヘルパ関数を使うとか。
578 :
デフォルトの名無しさん :2008/02/18(月) 11:18:27
>>577 メンバ関数を呼ぶときにthisを積むことができない時点で無理。
>>578 メンバ変数をアクセスしようってのに、メンバ関数を呼べないから
ダメというのは漏れにはちょっと途中のロジックがわからない・・・
580 :
576 :2008/02/18(月) 12:47:08
python.ctypesがstructにはアクセスできるけどclassが無理みたいなので 既存のc++コードのclassにpython.ctypesからアクセスするにはどうするか 知りたかったのです。結構難しいみたいですね。 class hoge { public: char *data int size }; のdataとsizeにextern Cからアクセスしたかったのです
C++初心者です。 C++ではクラスと構造体にはデフォルトのアクセス指定が違う以外に差異は無い、と入門書で読んだのですが、ということはC++では構造体は使わないで良いということでしょうか。
そうでもない。 typedef struct cordinate{ double x,y,z; }CORDINATE; こんなのは構造体で使う。
public: と書くのも面倒だったらstruct使う。その程度。
どちらも仮想関数テーブルを持った構造体になりうる
>>576 C互換の構造体を基本クラスにすれば?
ATL/MFCのCRectとかはそうやってる。
struct C_Struct { };
class CPP_Class : public C_Struct { };
588 :
デフォルトの名無しさん :2008/02/18(月) 18:12:59
>>580 data, sizeというメンバがpublicになっている時点で、
hogeは実質ただの構造体なのでは?
コンストラクタやデストラクタを自分で特に定義していなくて、
メンバ関数もカプセル化じゃなくコードの再利用だけを目的にしているような。
だとすれば、メモリ上ではCの構造体と同じだから直接python.ctypesに渡せばOK。
ちなみに仮想関数を持っている場合はダメ。
>>586 の方法なら一応動くけど設計を見直した方がいい。
>>587 // C
struct C_Struct { };
void c_func(C_Struct*);
// C++
class CPP_Class : public C_Struct { };
CPP_Class hoge;
c_func(&hoge);
>>576 がどういう使い方するのか知らんが、C互換の部分だけ見せる事はできるぞ。
public 継承は怖いなあ。 そんなことしなくても不完全型使えばいいんじゃね。
591 :
デフォルトの名無しさん :2008/02/19(火) 00:00:40
Modern C++ Designを読破した人でお分かりになる人 がいたら教えてください。 『第4章 小規模オブジェクトの割り当て』 のP88にチャンクのブロック数をunsigned charに収まる値に 制限した理由について、もしこれをunsigned shortにした 場合、sizeof(unsigned short)よりも小さなサイズのブロック を割り当てることができなくなることが書かれていますが、 何故だか分かりません。ブロックサイズとブロック数は独立 に管理してるものなのでブロックサイズは1バイトだろうが何バイト だろうが任意に指定できるはずです。
その本は読んだことないけどエスパー回答してみる フリーブロックの管理が連結リスト方式だとすると、あるブロックが解放されたとき、そこに次の空きブロックの位置を書き込まなければならない 総ブロック数がunsigned charの最大値以下なら、空きブロックの位置を保持するのに1バイトで足りるが、 総ブロック数がそれより多いなら、空きブロックの位置を保持するにはもっと領域が必要だ 解放されたブロックのサイズが1バイトでは、そこに次の空きブロックの位置を書き込むことはできない
struct A { template<class T> struct tmp{ T *pt; tmp( T *p ){ pt = p; } }; operator struct tmp(){ return tmp<struct A>( this ); }; A( tmp<struct A> &tmp ){ ... }; }; 上の方でもでてたけど、こういうコードって何の意味があるの?
594 :
デフォルトの名無しさん :2008/02/19(火) 01:06:43
>>592 すごいです。クリアになりました。
確かに未使用ブロックの先頭には次の利用
可能なブロックのインデックスを書き込みます。このインデックスのサイズが
もし2バイト(unsigned short型)なら、ブロックサイズを最低でも2バイト確
保しなければインデックス自体を書き込めないことになりますね。
>593 >489 に //非const参照で一時オブジェクトを受け取る対応。 って書いてあるやん。 俺の理解によると、その意味で A( tmp<struct A> "&" tmp) にしちゃ駄目ぽ。 通常の非 const 参照は一時オブジェクトを受け取れないので代わりに参照の働きをする tmp_ref を自前で導入してる。 tmp_ref<A> は A& を表していて、tmp_ref<A> への変換演算子が A → A& (ただし A が一時オブジェクトでも OK)の変換に相当してると思えば OK?
場違いだったらすまん、 if文で、if (音を感知したら) do ○○ っていうプログラムを考えているんだけど その音を感知する部分で何か有効的な物ある?
struct foo{ struct foge{}; }; struct bar : foo{ struct foge{}; }; で、barの型からfogeと言う名のstructを導出する時、fooのものを選ぶかbarのものを選ぶかってどうやるんですか?
お願いだからコンパイルの通るコードを書いてくれ
通るけど?
foge ← bar のやつ foo::foge ← foo のやつ
基底クラスに宣言した型を返すタイプの演算子オーバーロードって継承先では使用できないのでしょうか? // ■ペースクラス template <typename T> class BASECLASS { protected: unsigned long val; public: BASECLASS() { val = 0; }; ~BASECLASS() {}; // 継承する型によって変化させたい T& operator =(unsigned long val32) { val = val32; return *this; } operator unsigned long() { return val; } };
>>602 続き
// ■クラスA
class ChogeA : public BASECLASS<ChogeA>
{
};
// ■クラスB
class ChogeB : public BASECLASS<ChogeB>
{
};
// ■メイン
void main()
{
ChogeA hoge1;
ChogeB hoge2;
unsigned long tmp;
tmp = hoge1; // ○コレは動く
hoge1 = hoge2 = 10; // ×コンパイルエラーの位置
}
エラーメッセージ:'Choge::operator = (unsigned long)'に一致するものが見つからない
うまいこと引き継がれていないみたいで・・・
代入演算子は継承されないとオモタ
operator =は自動的に基底クラスのものを参照するようにならないメンバの一種。 規格では、派生クラスのデフォルトので上書きされるためと説明されていたはず。 派生クラスでいちいち定義すればいいのだけど、面倒と言われればそれまで。 class ChogeA : public BASECLASS<ChogeA> { public: ChogeA& operator =(unsigned long val32) { return BASECLASS<ChogeA>::operator =(val32); } };
派生クラスで using BASECLASS<ChogeA>::operator =; って宣言すればおk あと return *this; の部分はダウンキャストが必要な気がする
607 :
デフォルトの名無しさん :2008/02/19(火) 17:23:22
>>603 今の場合、コンパイラが暗黙に定義するコピー代入演算子が
派生クラスには存在している。基底クラスとはスコープが
異なるためオーバーロードにはならず、以下のものしか
候補にならないた一致するoperator=が無いと怒られる。
ChogeA& operator=(const ChogeA&);
ちなみに危険ではあるが
T& operator =(unsigned long val32) {
val = val32;
return *static_cast<T*>(this);
}
}
};
class ChogeA : public BASECLASS<ChogeA>
{
public:
using BASECLASS<ChogeA>::operator=;
};
// ■クラスB
class ChogeB : public BASECLASS<ChogeB>
{
public:
using BASECLASS<ChogeB>::operator=;
};
として可視にすればオーバーロードのセットに入るので
これでも動くかと。
608 :
602 :2008/02/19(火) 20:01:13
>>602 継承される可能性のあるクラスはコピーコンストラクタやoperator=をprivateにするのが原則。
class Base {
public:
Base &operator=(const Base &);
};
class Derived {
public:
Derived &operator=(const Derived &);
};
void foo(Base *p, const Base *q)
{ *p = *q; }
void bar() {
Base b;
Derived d;
foo(&d, &b); // 何が起こるだろう?
}
>>609 privateにしてしまうと、派生クラスのオブジェクトの正しいコピーと代入
が行えない。(Effective C++ Item12)
せめてprotectedにすべきではないか。
>>608 最後にキャストしてるから特に危険ではなかったか。
ただ、クラスのデザインとしては。。
やはり、
>>605 のように基底クラス部分の代入は
基底クラスの代入演算子に行わせて、派生クラス部分
は派生クラスの代入演算子に行わせるのが正等かつ
可読性が良いと個人的には思う。
>>610 のメイヤーズのとおり。
>>610 ポリモーフィズムを前提にするようなクラスに対して、
コピーはまだしも代入をまっとうに定義できるケースは珍しいだろ。
継承されないクラスでもコピーや代入は出来なくて当たり前。
コピーだけが意味を持つ場合はこうする。
class Base {
protected:
Base(const Base &);
private:
Base &operator=(const Base &);
public:
virtual std::auto_ptr<Base> clone() const
{ return std::auto_ptr<Base>(new Base(*this)); }
};
>>612 漏れは「継承される可能性のある」と、「ポリモーフィズムを前提にする」は
結構違うと思う。違わないようにするべきだという立場もわかるけど。
>>612 継承される可能性のあるケースとは継承されないケース
もあるわけで、盲目的にコピー、代入を禁止するのは
柔軟性を損ねる。cloneによる深いコピーにしても
実行コストを考えると使いたくないケースは
特に組み込みではよくある。残念ながらnewは小さい
オブジェクト用のアロケータではない。
クラスの使用方法を明確に規定するのが前提だが
そうでないケースでは様々な拡張に応じられるように
しておくべきだと思う。
>>613 std::unary_functionみたいのを除けば
デストラクタがvirtualかどうかではっきり決まると思うけど。
>>614 どういうクラスを想定してるの?
子クラスのインスタンスに親クラスのインスタンスを代入した場合の動作なんて、
いちいち決めても不毛なだけだと思うけどなあ、普通は。
元のインスタンスの決まった属性だけ読み出すという処理なら割と自然だと思うけど。
class Base {
public:
explicit Base(const Base *);
void assign_basic_attributes(const Base *);
};
class Derived {
public:
explicit Derived(const Derived *);
void assign_all_attributes(const Derived *);
};
>継承される可能性のあるクラスはコピーコンストラクタやoperator=をprivate>にするのが原則。 流れからして、このレスが明後日のほうへ行ってしまってると感じた。
だからsealedを導入しろって兄ちゃんがあれほど
C++プログラマのオマエらからしてC#はどうなの?
>>618 Javaじゃん。
つーか、仮想マシンが必要な言語と比較対照にはならんでしょ。
むしろライバルはD
.NETがLinuxに移植されたらC#もありかなと思って。
つMONO
Dいいね
C#は大人しくJavaと闘ってなさい。C++とはどちらも無縁です。 Dもまた同じく。必要のある所ではC++もDもC#/Javaも必要なのは変わりないのです。
Dが必要な場所が思いつきませんw
もうOOPも手続き型も飽きたな。 関数型言語を使う仕事がしたい。
OCamlとF#の出番だな。
民間企業は面白くない。 研究室とかに篭ってシコシコ勉強がしたい。
C#やったあとにJavaをやったら、C#が後発と言うだけあってC#が素晴らしく見えた。
>>618 LINQはSTL並に面白そうだと思っているんだけど、遊んでいる暇がない。
俺の仕事で、関数型言語を覚えてまで使う理由が見当たらない。 こうぶんきなんて解析せんし、無限計算もやらん。遅延評価も 価値を持ちそうにない。なんではやってるんだ。 Dのがいい。
>>630 コンパイラはLispとかで書かれてることもあるんじゃね?
>>630 自分の知らない計算パラダイムを知ることによって世界が広がるぞ、マジで
あんたの言ってることは「2次方程式なんて実生活で使わないから
学校で勉強する意味がわからない」とかぬかすガキと似たようなもんだ
>>631 コンパイラはMLとかHaskellの方がやりやすいと思う
>>618 Windowsでしか走らない時点で興味ない。
>>633 LinuxはLispと聞いたことがある。
>>634 > Windowsでしか走らない時点で興味ない。
つMONO
>>633 実際の話、理数系が苦手だった奴って
日常会話でもアホすぎてむかつくことが多いもんなw
◯理数系が苦手だったと得意気に言う香具師
俺はそんな奴をプギャーしておこう。
○理数系が得意だったとは決して言わない香具師
>>618 昔なら「こういうのはVBで書けば5分でできるんだろうな。VBなんか使い方しらんけどpu」と
思ってたような種類のアプリをサラッと書くのに使ってる。UI 作るのが楽なので重宝してる。
おまえらの開発プラットフォームは何? 1.Windows 2.Unix系(Linux含む) 3.組み込み 4.その他 ほとんどが1,2だろうな
Unix系にはMacを含みますか?
おう、こうするよ。 1.Windows 2.Unix系(Linux含む) 3.組み込み 4.Mac 5.その他 ほとんどが1,2だろうな
組込みがターゲットの開発は、ふつうクロスだろ上皇
まあそうだけど、例えばルネサスのコンパイラとか 68kのコンパイラとかっていう程度でいいじゃん。 どっちもWindowsのツールになるが。 あまり興味ないから、質問取り消すわ。
2と3なら3が多いと思うのだが・・・どうでもないのか?
質問が二つほど。 関数宣言と関数中身は一対一とおもってたんですけど、 すでにライブラリに入っている関数中身をプロジェクト内に書くということは 問題ないのでしょうか? sprintfで書き込むのに必要な配列のサイズを知る方法ってあるのでしょうか?
C++でsprintfで書き込むのに必要なバッファの大きさを知る一般的な方法はないね。 C99だと書込先にヌルを指定すれば、戻り値でわかるようになったんだけど。 VC++の_scprintfのように独自関数を使ったり、 ヌルデバイスをfopenしてfprintfしたりという環境依存の方法か、 標準ライブラリのものを使うのを諦める。 (自分でバッファサイズが分かるものを作ったり、あるいはBoost.Formatのような既製品を使ったり)
>>649 普通はダメ。
ただし、主に移植性を重視するUNIXのプログラムで、
システムが提供するライブラリ関数と同名の関数を自分で再定義する場合はある。
例えばbasename(3)は標準化される前から多くのUNIXで提供されていて、
しかも挙動が微妙に違っていた。そこで、basenameが無かったり、
あっても標準と違っているOSではbasenameを自前で定義することがある。
そういうコードをリンクできるか、再定義した関数をリンクしたライブラリから
隠すことができるかどうかはリンカ次第。
右辺値参照が導入されたら、これまでの左辺値参照の存在意義はどうなりますか? struct X {}; X f(); X&& = f() //OK Xは右辺値参照 X obj; X&& = obj; //OK Xは左辺値参照 &&があれば、両方で使えますよね。
間違えた。 右辺値参照が導入されたら、これまでの左辺値参照の存在意義はどうなりますか? struct X {}; X f(); X&& x = f() //OK xは右辺値参照 X obj; X&& x = obj; //OK xは左辺値参照 &&があれば、両方で使えますよね。
両方で使えるのか? 区別できるからこそ(ry
RVOをさせたくない場合、どう書けばいいですか? gccが頭よすぎで、全部RVOされます
代入演算子が呼ばれたのでいいなら 初期化じゃなく代入にすればいいが、 どうしてもコピーコンストラクタが呼ばれて欲しいとなると、 一旦一時変数を作ってそれで受けて、 さらにそれをコピーするしかないのかな。 ただ、RVO に依存して挙動の変わるコードは感心しないので 何らかのチェックのために行うのでなければ、そういうことはしない方がいい。
>>649 ostringstream foo;
foo << "hoge hoge pu-";
foo.str().c_str(); <- 文字列へのポインタ
>>649 >>651 <new>のoperator new, new[], delete, delete[]は自分で定義してもよい。
ユーザが定義しなければライブラリの実装が使われるって規定がある。
>>655 呼ぶ側と呼ばれる側の翻訳単位分けてみたらどう?
RVO は翻訳単位関係ないぜよ。
処理系依存なんだし、関係無いかどうかはgccの実装次第じゃね? 翻訳単位分ければインライン化は阻害される思うし(多分)、 そしたらRVOも阻害される可能性はあるかと。 リンカが頑張ってたら駄目だろうけどね。
>>656 move semanticsしたのと、してないのを比べたいんじゃね?
コストが掛かるはずの普通の代入でも、RVO効くとコピーコスト0になるから。
>>653 多重定義したときに区別を付けるために必要。
>>653 左辺値参照と右辺値参照の区別があって一番うれしい場面は,
関数の実引数が右辺値なのか左辺値なのかを関数の定義内で
識別できるところです.例示しているコードにおいては,
右辺値参照が一時オブジェクトを束縛できることを除いて
x を右辺値参照型にで宣言しようが左辺値参照型で宣言しようが
本質的な違いが現れることは無いように思います.
>>655 試していないのでアレですけれど
struct X{ X(int i) : p_(new int(i)) {} ~X(){ delete p_; } int* p_ };
X f(bool b){
if (b) { return X(42); }
return X(43);
}
あたりだとRVOが阻害されませんか?
-O0 でも RVO するね。
667 :
デフォルトの名無しさん :2008/02/22(金) 14:46:39
そこそこ大規模なプロジェクトで,使われる例外についての 統制を取りたいと思ったとき便利な方法はないだろうか. どこかの馬鹿が int を throw するなどというバカげたことを していないということをコンパイル時に保証するのは無理? プロジェクト全体として std::runtime_error と std::logic_error から派生させたいくつかのクラスを 投げることを規約としているのだけど,馬鹿が適当な ものを投げてくるかもしれない. 結局 throw を全部見て回るしかない?
例外禁止がベスト、オプションで切っとけ
669 :
デフォルトの名無しさん :2008/02/22(金) 15:04:03
>>668 ちょ・・・それわ,無理w
マージ担当者にされてあたふたしてる.
670 :
649 :2008/02/22(金) 15:15:10
672 :
671 :2008/02/22(金) 16:10:16
って、コンパイル時のチェックにはならないんだっけかそういえば・・・
>>662 まさに言う通りのことを試したいんです。
-O0でもRVOします。
volatile int norvo(){ ... }
つ -fno-elide-constructors
>>671 無理
例外指定しても投げようと思えば何でも投げられる。
unexpected exceptionにはなるが。
C++の例外は破綻しているから使っちゃ駄目だって
破綻してないヨ。
破綻してないアル!
681 :
デフォルトの名無しさん :2008/02/22(金) 20:48:10
C++0x では例外周りでの新機能ってあるんですかね. っていっても自分でも新機能を思いつかないんだけど.
move semantics ほしいな
>>681 例外用の関数がいくつか追加されてたはず。
例えば catch(...) でも例外が取得できるようになった、とか。
>>667 そんなもんヌルポインタにアクセスしたり整数オーバーフローさせたり
無茶なキャストでコンパイラ黙らせたりしてるのと同じで、馬鹿が混ざっている
という前提ではどうしようもないもんだろ。
なんで例外だけ取り立ててどうにかしようと思うの?
main()でcatch (...)して、全開発者に同報メールを送るようにでもしておけばいいじゃんw
686 :
デフォルトの名無しさん :2008/02/23(土) 04:36:35
>>684 マージ担当の引き継ぎ事項に書いてあったから.
例外クラスに命名規則をつけておけば、 それに従っていない例外を投げている throw 式を 正規表現検索できると思う。
>>685 int main() {
try {
// main の中身
} catch(const std::runtime_error& e) {
// ここは規約通り
} catch(const std::logic_error& e) {
// ここは規約通り
} catch(...) {
// ここに飛んできたらおかしい
}
}
実際に飛んでこないと分からないがな。
>>686 そういうことなら throw と catch を検索して様子を見るぐらいで十分でしょ。
それ以上は他の未定義動作や禁じ手と同じで、完全なチェックは無理だと思うよ。
690 :
デフォルトの名無しさん :2008/02/23(土) 05:12:46
pimpl イディオムを使うとき、ポインタはどれがいいんでしょう? const std::auto_ptr<Impl> かな、と思うのですが、 boost::scoped_ptr<Impl> でもよさそうだし、 あんまり意味ないかもしれないけど boost::shared_ptr<Impl> でも。
>>690 普通は boost::scoped_ptr 。
std::auto_ptr は少し安全性が落ちる。
boost::shared_ptr は冗長。
>>686 throw を次のようにマクロで置き換える。
#ifndef NDEBUG
#define throw DEBUG_CHECK_EXCEPTION_(),
struct DEBUG_CHECK_EXCEPTION_ { };
template <typename T>
void operator,(DEBUG_CHECK_EXCEPTION_, const T& e) {
BOOST_STATIC_ASSERT((
::boost::is_same<T, ::std::runtime_error>::value ||
::boost::is_same<T, ::std::logic_error>::value ||
::boost::is_base_and_derived<T, ::std::runtime_error>::value ||
::boost::is_base_and_derived<T, ::std::logic_error>::value));
std::cout << typeid(T).name() << std::endl;
throw e;
}
#endif
これで静的にチェックできるはず。
ミスった。引数が逆だ。 #ifndef NDEBUG #define throw DEBUG_CHECK_EXCEPTION_(), struct DEBUG_CHECK_EXCEPTION_ { }; template <typename T> void operator,(DEBUG_CHECK_EXCEPTION_, const T& e) { BOOST_STATIC_ASSERT(( ::boost::is_same<T, ::std::runtime_error>::value || ::boost::is_same<T, ::std::logic_error>::value || ::boost::is_base_and_derived<::std::runtime_error, T>::value || ::boost::is_base_and_derived<::std::logic_error, T>::value)); std::cout << typeid(T).name() << std::endl; throw e; } #endif
あ、テストコードまぎれてる。 typeid のところは無視して。
>>693 <: が [ の代替表現に引っかかる。 < ::std... とスペース一個空けとかないといけない。
throw する型によってエラーが出るのは確認できた。役に立ちそうな予感はする。
ただ、 ~T() throw () {} みたいなのがコンパイルできないのがマズイ感じ。
標準ライブラリの中に throw () とか付いてる可能性を考えると、致命的かも。
696 :
デフォルトの名無しさん :2008/02/23(土) 08:08:44
>>690 COW実装したいときはshared_ptrが便利
698 :
デフォルトの名無しさん :2008/02/23(土) 11:07:20
D言語を使う場合、いいGUIツールがありますか? それがない限り、使う気になりません。 それとどんな言語でも最初は仕様がキレイなんですよね。 あのC++だって当初はキレイだったんですよ。 ところが実用的に使われ始めて呪文のような コードになってしまった。 C#もだんだん仕様が汚くなりつつあると聞いてます。 仕様がすっきりしてる言語なんて全く信用してません。
>>698 で、C++についてのどういった相談事でしょう?
D言語のことはD言語スレへ、C#のことはC#スレへお願いします
>>695 例外指定か・・・。なるほど。
throw じゃなくて THROW か何かを使わせることができるならそれが楽なんだが、
その規約を守らない人が出てくると・・・だしなあ。
Java みたいに throws ならいいのに・・・。
701 :
デフォルトの名無しさん :2008/02/23(土) 14:15:12
D の IDE なら Descent だろうかね。
>696 ふつーは、derived_class.BaseClass::Greeting()とかって書けばいいから ポインタ一個分のオーバーヘッドが無駄と言えば無駄だけど、 まー別にいいんじゃねーの。
>>696 あり得ない解決方法。
別メンバ関数(非仮想)を用意して、
そこで基底クラスの関数へ委譲すべき。
Greeting は仮想関数にした上で、ね。 あるいは、Derived の Greeting を別関数にするか。
SYSTEMCの勉強をしている、IC設計者です。 C++は初心者です。 C++で、class Signal を定義し、その中に、 string signal_name があったとき、 classを使う側で、 Signal sig1(); とだけすると、 そのsig1がsinanl_nameに自然に入るなんてことは できないのでしょうか。 コンストラクタの工夫などで。 やはり、Signal sig1("sig1"); として コンストラクタの中で渡されたstringで signal_nameを初期化する処理を書いて、 をしなければなりませんか。 同じ sig1 をいう名前を Signal sig1("sig1"); のように2回書くのがどうもなーと 思ったものですから。
>>706 コンストラクタの工夫では無理だろう
工夫する余地があるとすればプリプロセッサマクロだが・・・
#define sig1() sig1("sig1")
・・・は無理矢理すぎるか
#define DECLARE_SIGNAL(name) Signal name(#name)
で
DECLARE_SIGNAL(sig1); → Signal sig1("sig1")
に展開させるくらいじゃないかな
708 :
706 :2008/02/23(土) 18:34:24
>>707 なるほど、マクロかあ。
そういう方向で考えて見ます。
どうもありがとうございました。
709 :
デフォルトの名無しさん :2008/02/23(土) 18:41:19
fatal error C1060: ヒープの領域を使い果たしました。 テンプレートプログラミングの末路を見た。
プリプロセッサでごにょごにょすりゃ出来るけど、 何か変なことをやろうとしているような気がする。
>>709 コンパイラオプションでヒープをもっと増やせばいいだけ。
コンパイルに使うヒープを増やせるのか?
テンプレート関連のコンパイルで内部的にループにでもなったとか。 Zmで解決すれば良いけど
715 :
709 :2008/02/23(土) 21:47:56
Zm2000にしても無理だったんだ。
716 :
709 :2008/02/23(土) 21:54:15
どうやら無茶なことをしようとしていたようだ。 あきらめるわw
ちょっと質問です。VS2005、XP です。 大きさの等しい、文字列の配列と整数の配列がそれぞれあるとします。 文字列の配列を、整数の配列の値の順にソートしたいと思います。 std::sort など既存のソートアルゴリズムを使って、これを行ううまい方法はないでしょうか? 例: std::string a[] = {"aaa", "bbb", "ccc", "ddd"} int b[] = {7, 1, 5, 4} の場合、a を "bbb", "ddd", "ccc", "aaa" の順に並び替えたいと言うことです。 実際は文字列だけでなくいろいろな型を使うので、 文字列と整数をメンバとして持つ構造体を作って operator < を定義して std::sort にかける・・・というのは、少し長すぎて気が引けます。 よろしくお願いします。
>>717 構造体なんかつくらずにpairにしてvectorにでもいれて
比較関数を書いてsortさせるとか。
あるいは、いったんmapに突っ込んで取り出す。
ああー、pair を使うってのは思いつきませんでした。 pair なら比較関数をかかなくとも、first の方にキーを入れれば、std::sort でソートできますね。ありがとうございました。
>>690 auto_ptr は不完全型に使っちゃいけないことになってるから、候補からは外れると思うよ。
>>667 もしcppに細工することが出来るなら、
template <class T> inline void do_throw(const T &ex)
{ BOOST_STATIC_ASSERT((...)); throw ex; }
#ifdef NDEBUG
#define THROWS(spec)
#else
#define THROWS(spec) mycpp_throws spec
#endif
#define THROW(ex) do_throw(ex)
と定義しておいて、偽cppは本物のcppを実行してから#lineを見て
自分のプロジェクト内のコードにdo_throw以外のthrowがあったらエラーにする。
最後にmycpp_throwsをthrowに置換してコンパイラに渡せば一丁あがり。
一度これをやっておけば、コストを気にせず例外仕様をがんがん付けて
実行時の問題をデバッグすることも出来る。
>>721 たいていの実装ではそうなんだけど、規格はテンプレート引数に不完全型を使った時点で
その効果は未定義としている。
724 :
723 :2008/02/24(日) 01:15:41
あ、記載があるのは 17.4.3.6 ね。
BCC で変になってたとかいう話があったのはそれが原因か。
最新のドラフトだと個別に許可されていればおkのようだな。 多分 shared_ptr 絡みで追加されたんだと思うが。 実際、許可されてるクラスは shared_ptr, weak_ptr, enable_shared_from_this の3つだけだ。
横から補足すると、これはあくまでも標準ライブラリ側の制限なので、 scoped_ptrや自前auto_ptrなら問題ない。 ただし不完全型をdeleteしたらundefined behaviourなので (どう考えてもill-formedの間違いだと思うけど)、 自前auto_ptrを作るとしたらboost::checked_deleteを使うべし。
728 :
デフォルトの名無しさん :2008/02/24(日) 09:45:19
checked_delete なんてのがあるのか. しかしその実装を見てもなにやってるのかわからん. まんなかの (void) sizeof(....ってなにやってんの? template<class T> inline void checked_delete(T * x) { // intentionally complex - simplification causes regressions typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; (void) sizeof(type_must_be_complete); delete x; }
実際に何らかの形で使わないとエラーにならない処理系でもあるんじゃない?
730 :
デフォルトの名無しさん :2008/02/24(日) 10:02:04
>>729 使わないと最適化ですっ飛ばされちゃうこともあるのかねぇ.
>>728 sizeof(T)? 1: -1
sizeof(T) が 0 になることなんてあるの?
不完全型
struct Hoge {}; printf("%d", sizeof(Hoge)); →1 エーッ
サイズ0だと色々困る 例えば Hoge hoge[2]; &hoge[1] - &hoge[0] == 0 とかじゃまずい
>>733 不完全型とはvoidとか
class Widget;
のこと?
だったらsizeof(void) sizeof(Widget)はコンパイルエラーになるんだけど。
>>733 不完全型にはsizeof演算子は適用してはいけないと書かれてるんだが。
>>736 コンパイルエラーになってほしいんだからそれでおk
仮に 0 になる処理系があっても大丈夫という寸法なんだろう。
>>736-737 それを利用してコンパイルエラーにさせるから、"checked_" だろ
boostが使ってるね
その boost の話なんだが・・・
>>726 最小のフットプリントで不完全型を渡せる scoped_ptr の代替はないんだな。
unique_ptr でも不完全型を許可してほしいなぁ。 checked_delete 相当の
default_delete とか使うんだから、問題になることはないはず。
default_delete は不完全型の時には診断が要求される (A diagnostic is required if T is an incomplete type.) って書いてあるな。 デリータがテンプレートパラメータになってるから デリータを自分で指定すれば好きに出来そうではある。
>>744 そこまで書いておきながら、 unique_ptr に不完全型を許可する記述が無いのは
おかしいな。もしかして、書き漏らしてるだけ?
>>738 >>740 typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
仮に、sizeof(T)が0に評価されたときに
配列が-1という要素を持つことが許されないという理由でコンパイルエラー
にするという意図ならわかるが、
>>733 が言ってるとおりだとすると単に
不完全型だということなら、そもそもsizeof(T)自体がエラーの原因になるだろ。
だが、規格ではsizeof(不完全型)は許されていない。
規格に従えば、不完全型Tに対してsizeof(T)が0になることはない。
>>739 それなら納得
よく考えてるなぁ
全てのコンパイラが規格に従ってたら BOOST_WORKAROUND なんてもんは必要ないな。
>>745 デリータ次第だから default_delete に記述があれば十分だろう。
というか、これは不完全型は許可してないという記述じゃないのか?
いや、まあ挙動が定義されているからある意味許可はされているのか。
>>749 default_delete については不完全型を許可している(コンパイルエラーになると
規定している)ように読めるけど、それは unique_ptr に不完全型を渡した場合の
動作について何か言っていることにはならないでしょ。 default_delete 以外も
使えるんだし。
デリータはユーザが作った物も指定できるんだから、 規定できるわけないとまではいわんが 規定が無いのならユーザが自由にできるってことでしょう。
>>746 733は不完全型の場合にsizeof(T)が0になることがあるって意味だろ?
同じこと言ってると思うぞ
規格では不完全型で sizeof (T) するとエラーにならないといけないが、 エラーにならず 0 になる処理系があって、その対策なんだろうという話だな。
>>752 ああ、あああ、ああ、そうか。
じゃあ未定義なんだろうな。
>>755 俺に言われても知らない。733に聞いてくれ
>>757 誤解を招くってのは分かる
けど
>>732 に対して
>>733 なら「なることがある」だろ
# というか733みたいなおそらく一例を挙げただけの即答にツッコミ杉w
このスレに居るなら「すべきである」「しなければならない」みたいな違いに敏感だろうに・・・
肩凝ってしょうがねえ
&&の右辺値参照ってのは、右辺値を渡したときに渡した元のオブジェクト はどうなってもいいという前提なの?これがmove semanticsというもの? @ void f(X&& r); f(X()); // move semantics X()の状態は保障されない。 // r は右辺値参照。 A void f(X&& r); X x; f(x); //この場合(X&& r = x)は、rは左辺値参照。 B void f(X& r); X x; f(x); AとBは等価という理解でいい?
>>761 元のオブジェクトがどうなってもいいっていうのが非 const 右辺値参照でしょ。
2がコンパイルできるようだと右辺値参照の意味がないような気がする。
コンパイルエラーになるんじゃね?
template<int Value> struct base{}; struct a : base<0>{}; struct b : base<1>{}; struct c : base<2>{}; struct d : base<3>{}; ...... 何らかの型がbase<*>を継承している場合、その何らかの型とbaseの情報だけで baseに指定されたテンプレートパラメータを取得する方法はありませんか?
baseにpublic:enum{ VALUE=Value}とでもつけときゃいいじゃん
どういう状況で取得したいのかわからないから、 これが使えるかどうか自信がないけど。 template<int n> void f(base<n> const&) { }
>>763 intならenum
typeならtypedef
で保存
>>762 draftに以下の記述があるんだけど、これはどういう意味?
struct A {};
A a;
A&& ar = a;
The expression ar is an lvalue of Type A.
派生クラスもテンプレ化するとか
>>767 「 ar という式は型 A の左辺値である。」
・・・読んだまんまなんだが、こんな答えでいいのか?
>>767 は
>>762 の「2はコンパイルエラーになるかも」を受けての質問だろ?
draftにそうあるなら左辺値になるんだろうな。
それを
>>761 の(2)と(3)でオーバーロードされたfに渡したら
左辺値扱いなので(3)の方が選ばれる・・・とか? 俺も仕様知らないけど
>>770 説明不足だった。
ABのそれぞれの関数f()は、オーバーロードというつもりで
書いたわけじゃなくて渡す引数が左辺値なら、f()をどっちで定義しても
同義じゃないかと思った。
A
void f(X&& r);
X x;
f(x); //この場合(X&& r = x)は、rは左辺値参照。
B
void f(X& r);
X x;
f(x);
>>771 2が通るんなら右辺値参照受け取る関数なんて恐ろしくて作れない。
>>772 Aはとおるだろ。で、左辺値参照になるだけじゃねーの?
774 :
770 :2008/02/24(日) 22:59:32
>>771 説明不足なのはむしろ俺かwすまん
オーバーロードの意味じゃないのは分かってる
で、よく仕様知らないと言いつつ770で想定したのは↓
A a;
A&& ar = a;
f(ar); //arは左辺値扱い(?)なのでオーバーロードがあったら f(A&); の方が優先的に呼ばれるかも
で、arについての話だけ。
で、本題だけど、f(A());のケースだとf(A&&)しか呼べないだろうけど
引数が左辺値ならf()はどっちでも同義だと思う。
775 :
770 :2008/02/24(日) 23:00:39
「で、」が多いのは気にしないで下さい><
>>774 同じ認識になりますた。
で、オーバーロードの場合だと、左辺値引数を渡したら
左辺値参照を好むから void f(X&); が呼ばれるはず。
777 :
770 :2008/02/24(日) 23:06:56
>>772 もしコンパイルエラーにならなくても、
左辺値がオーバーロードでf(A&);に行くなら心配無いよな?
両方書いて、少なくともf(A&&)の方は「壊して良い」ってことになるから
778 :
772 :2008/02/24(日) 23:32:57
あー。 右辺値参照引数に左辺値が渡せないと、 unique_ptr みたいに移動だけを行うような モノが作れないな。 しかし「左辺値参照になる」ってのは解せないな。受け取った側では実引数が 左辺値か右辺値かによらず、扱いは同じ(式中の仮引数の型は左辺値参照)だろ。
const でない以上、壊されても文句は言えないっしょ。
すみません、ちょっと質問です。 あるstaticメンバ関数が指定のクラスに所属しているのかを見分ける方法はありますか? struct A { static void a() {}; static void ab() {}; } struct B : public A { static void ab() {}; } // メンバ関数がBに属するのかどうかを知りたい some_check_method<B, B::ab>() // true some_check_method<B, B::a>() // false といった感じにしたいのですが……。
>>780 そんな判別はできなさそうだなぁ。存在すらしてなければエラーになるし。
public 継承した上で、継承された名前が派生クラスのメンバと区別できるような
点が思い当たらないし。
なんでそんなことしたいのか、目的を言ってもらえればもうちょっと別の道が
ありそうな気はするんだけど
>>778 右辺値参照引数に左辺値を普通に渡すことはできない。
明示的にstatic_castするか、右辺値参照を返す関数を経由することで渡す。
void f(X&& r);
template <class T> inline typename remove_reference<T>::type&& move(T&& x)
{ return x; } // return文に限っては引数を暗黙に右辺値にキャストする!
X x;
f(x); // error
f(static_cast<X&&>(x)); // ok
f(std::move(x)); // ok
引数が左辺値の参照渡しに「なる」のは関数テンプレートだけの特殊なルール。
例えば上のmoveに左辺値xを渡すと、TとT&&はともにX&になってしまう。
fのように右辺値参照をとる非テンプレート関数に左辺値を渡せば単にエラーになる。
>>782 右辺値参照を取る非テンプレート関数に
キャストなしで左辺値を渡せると思いますよ
>>782 draftには
struct A {};
A a;
A&& ar = a;
これは可能ということになってる。独立右辺値参照は
左辺値で初期化可能で関数渡しはNGということは
右辺値参照に関しては、これまでの考えが通用せず
”右辺値参照パラメータの関数の引数渡しは初期化の
セマンティクスとは異なる”
ということになるの?
>>782 >引数が左辺値の参照渡しに「なる」のは関数テンプレートだけの特殊なルール>。 例えば上のmoveに左辺値xを渡すと、TとT&&はともにX&になってしまう。
これは、move(x)がmove<X&>(X&&& x)となり、&&&は&となるというルールだよな?
lvalue-to-rvalue conversion がかかるんで普通に渡せるんじゃない? static_cast とか std::move を使うのは overload の解決を制御するためだと思う。
787 :
782 :2008/02/25(月) 22:44:49
>>786 ものすごく細かい話になりますけれど, N2521 読む限りでは
>>784 のような例だと右辺値参照も左辺値参照も
全く同じ初期化の規則が適用されるように思われるので,
lvalue-to-rvalue conversion は適用されないんじゃないですかね?
lvalue-to-rvalue conversion があるので,右辺値で初期化できて
左辺値で初期化できないのは不自然に感じられるという意味なら
その通りだと思いますけれど.
>>786 void f(A&& rv);
A a;
f(a);
の場合、引数渡しでコピーは発生せずに rv は a を左辺値
として扱える(rvはaの別名)ということでOK?
791 :
デフォルトの名無しさん :2008/02/25(月) 23:20:35
void f(const A&); //@ void f(A&&); //A A g(); A a; f(a); //bound to @ f(g()); //bound to A これは間違いなさそうなんだけど、もし@が無くAだけだった場合は f(a) はエラーのような気もする。その場合は右辺値参照キャスト f(static_cast<A&&>(a)) or f(std::move(a)) を行う必要がある。 これが正しいのかな?
792 :
789=791 :2008/02/25(月) 23:23:57
>>790 >>788 を見て、
>>789 はNGかなと思ったんだけど、やっぱ正しいのかな?
それなら、
>>791 の内容は間違いで
f(static_cast<A&&>(a)) も f(std::move(a)) も必要ないな。
>>791 >もし@が無くAだけだった場合は
f(a) はエラーにはならないということでよいと思います.
>>792 788で本筋とあまり関係ないことを書いて混乱させたみたいですいません.
>>789 は適切という解釈でよいと思います.
スコットメイヤーズとかハーブサッターとかニコライジョスティスは 新規格が出たらまた本をたくさん出すんだろうな。 出たら欲しいもの 超簡単な初心者本 The C++ Standard Library (second edition) by ジョスティス Effective C++ (fourth edition) by メイヤーズ Effective STL (second edition) by メイヤーズ
ある程度の罠が減って、いくつかの罠が増えると
Modern C++0x Design
>>793 追記
A a;
A&& ar = a;
が正しくて、
void f(A&&);
f(a);
が正しくないとなると
”関数の引数渡しのセマンティクスは初期化のセマンティクスと同じである”
というこれまでの概念が崩れてしまうもんね。ちょっと安心した。
>>797 それは正直もういい。Singletonなんて考えすぎだろ。
確かにフェニックスパターンにはワラタ あれは考えすぎ
Modern C++0x using mpl (first edition) by ジョスティス なら欲しい。
小規模アロケータがデフォルトアロケータよりも遅かった という実験結果もWebに載ってたな。Efficient C++の シングルスレッド版は試したが確かに速かった。バグがあって ちと苦労したが。
803 :
780 :2008/02/25(月) 23:47:24
>781 理由は、 「ファクトリー関数を使用すると決めたけれども、派生クラスで関数の実装を強制できないと不安」 ということです。 #実際にはファクトリー関数みたいなものですが。 派生クラスを作成したときに必ずどこかでミスりそうなので、もしトラップする方法があったら 予防線を張っておこうかと考えました。
溺れてら
807 :
804 :2008/02/25(月) 23:57:38
>>805 runtime check で良いなら関数へのアドレス調べればよいだけだと思ったんですが
#include <iostream>
struct A
{
static void a() {}
static void ab() {}
};
struct B : public A { static void ab() {} };
int main()
{
std::cout << (&A::a == &B::a) << std::endl;
std::cout << (&A::ab == &B::ab) << std::endl;
}
compile-time check が要ったりしますか?
808 :
805 :2008/02/26(火) 00:04:20
& 体育座り
810 :
804 :2008/02/26(火) 00:39:50
うーん, compile-time check でメンバが存在しなくてもエラーにならないのを 考えてみましたけれど, MSVC7.1 では内部コンパイラエラーになる……orz GCC4.1.2 では通るんですが…… #include <iostream> struct A { //static void a() {} static void ab() {} }; template<class C> char (&has_a_helper(int))[sizeof(&C::a)]; template<class C> char (&has_a_helper(...))[sizeof(void (*)())+1]; template<class C> char (&has_ab_helper(int))[sizeof(&C::ab)]; template<class C> char (&has_ab_helper(...))[sizeof(void (*)())+1]; int main() { std::cout << sizeof(has_a_helper<A>(0)) << std::endl; std::cout << sizeof(has_ab_helper<A>(0)) << std::endl; }
struct A {private: //←追加 static void a() {} static void ab() {} }; struct B : public A { static void ab() {} }; でなんか問題アルの?
812 :
780 :2008/02/26(火) 01:05:48
>807 手動で関数へのアドレスを確認するのは面倒な気が…… >811 struct Aが使い物にならなくなります……。 一応、「登録したクラスと関数が一対一になっているかどうかを判別する」というところまでは 下記のコードで実現しています。 あくまで一対一対応の判別なので、クラススコープ内の関数かどうかは判別できませんが…… unsigned int count() { static unsigned int r(0); return r++; }; template<class type_t> unsigned int number() { static unsigned int r(count()); return r; }; template<typename member_t, member_t member> unsigned int number(unsigned int n) { static unsigned int r(n); return r; }; template<class type_t, typename member_t, member_t member> static bool check() { static unsigned int n(number<member_t, member>(number<type_t>())); return (n==number<type_t>()); }; struct A { static void a() {}; static void ab() {}; }; struct B : public A { static void ab() {}; }; BOOST_CHECK_EQUAL((check<A, void(*)(), A::ab>()), true); BOOST_CHECK_EQUAL((check<B, void(*)(), B::ab>()), true); BOOST_CHECK_EQUAL((check<A, void(*)(), A::a>()), true); BOOST_CHECK_EQUAL((check<B, void(*)(), B::a>()), false); ちなみに、このコードに興味ある人います?いるんでしたらフロ入った後に解説書きますけど。
よくわからんなー。struct Aは要するにインターフェースで、 static voidなa,abは要するに仮想関数なわけでしょ? で、オーバーライド必須にしたい、みたいな。 それのテンプレート版、という話と理解したけど、 ならNVIイディオム使えば終わる話じゃねーの?
814 :
780 :2008/02/26(火) 02:16:16
いや、>803にも書いたけど 「ファクトリー関数を使用すると決めたけれども、派生クラスで関数の実装を強制できないと不安」 ということですね。struct Bからさらに派生する場合も対応できるようにしたいです。 あとstaticメンバ関数は仮想にできないのでNVIはムリですね。
>>814 正直どういう風に使いたいのかよく分からん。
どういう風な事がやりたいのかとりあえずコード書いてくれ。
コンパイル通らなくてもいいから。
すみません、質問お願いします。 下のコードでパターン1と2をコメントアウトで切り替えると速度が大きく変わります。 原因わかる方いらっしゃいますか? for( i = 0; i < 1200000; i++ ) { *(pDst + 0 ) = *(pSrc + 0); *(pDst + 300) = *(pSrc + 1); *(pDst + 600) = *(pSrc + 2); *(pDst + 900) = *(pSrc + 3); pSrc += 4; // パターン 1 pDst += 1200; // こっちだと60msくらいかかる // パターン 2 pDst += 300; // こっちだと17msで終わる }
メモリのヒット率?
>>817 環境が判らんから何とも言えんが、恐らくは>818。
しかし、何でまたそんな小汚いコードを書いているんだ?
普通にpDst[900] = pSrc[3]と書けばいいものを。
>>817 そこだけならキャッシュのヒット率だと思うけど…
LinuxでIntelのx86使ってるならVTuneがタダで使えるよ
1200 * 1200000 = 1440000000 だけど、 そんなにメモリ確保してあるの? 確保してるとしても、ページフォールト起こしそう。 キャッシュよりそっちのが問題かもしれない。
みなさん回答ありがとうございます。
メモリのヒット率ですか・・・
そうだとするとここから先の高速化は難しそうですね・・・
ちなみに環境は以下の通りです。
Intel Core Duo T2500
メモリ1GByte
WindowsXP
VisualC++6.0
>>821 >1200 * 1200000 = 1440000000 だけど、
>そんなにメモリ確保してあるの?
ごめんなさい間違っていました。
1200000ではなく、300000です。
メモリは物理メモリ内に確保できています。
823 :
805 :2008/02/26(火) 20:26:04
ビョーン・ストラウストラップ氏はどこの国の人ですか?
ビャーネ・ストロヴストルップ(Bjarne Stroustrup, 1950年6月11日 - )は、 デンマーク・オーフス生まれのコンピュータ科学者。
>>824 thx
デンマークか。C++はアメリカ発信じゃないのがいい。
でも、C++はベル研生まれでアメリカ発信でそ?
ヨーロッパはやっぱりレベル高いよな。フィンランドとか凄いらしいな。
>>814 ファクトリーをstaticメンバ関数じゃなく関数テンプレートの特殊化にするのはダメ?
template <class T> T *factory();
class Base {
friend Base *factory<Base>();
protected:
Base();
virtual ~Base();
};
class Derived : public Base {
friend Derived *factory<Derived>();
protected:
Derived();
virtual ~Derived();
};
sizeof(空のクラス) = 1; sizeof(空の構造体) = 1; なぜ0バイトでなく、1バイトになるんでしょうか?
FAQ: EmptyRect kara[4];とかやってインスタンス化したとき、 サイズが0だと&kara[0] == &kara[3]とかになっちまってまずい。
>>829 複数のオブジェクトを作ったときにオブジェクトして何らかのサイズを持って
存在していないとuniqueなオブジェクとしてトアドレスが決まらない。
詳しくはInseide The C++ Object Modelに載ってる。
C++のSTLは便利なんですけど、 一行が助長に長くなってしまって耐えられません。
"助長に長く"の検索結果 2 件中 1 - 2 件目 (0.44 秒)
>>832 typedefを程よく使うしかないね。「程よく」ってのがまぁ、人それぞれなんだけど。
typedef std::vector<MyClass>::const_iterator Iter;
for (Iter i = vec.begin(); i != vec.end(); ++i) {
なんてのは、結構やる人多いはず。
Iterがこれ以降出てこない場合、このtypedefは全体としては「短縮」にも「簡略」にも
なっていないわけだけど、それでも「forの行を短く見せたい」というだけの理由で、俺はよくこう書いてる。
もちろん人によっては、「程よく」の範囲を超えた、余計な足踏みみたいに感じるのだろうけどね。
> 助長に長くなってしまって
このレス書き込む前にリロードしたらもう突っ込まれていたので、突っ込むのやめるw
C++0xのautoなら・・・いやなんでもない
言いかけて引っ込める意味がわからん。
態々それだけのためにレスをつける意味がわからん。 それはさておき、1行の長さを抑えるためにもインデントは4カラムにするのが定着した私。 >834みたいなことをすると、同じブロック内で別のイテレータ使いたくなるときに困ると思う。
ITE!救命阿!
#include <iostream> #include <vector> int main() { std::vector<int> v{ 1,2,3,4,5 }; for(auto i = v.begin(); i < v.end(); ++i) std::cout << *i << std::endl; }
BOOST_FOREACH()おいしいです
>>840 C++0xのSTLには採用されるのか?
>>842 禿が生きてる限り、標準ライブラリにプリプロセッサ使ったブツは追加されないんじゃね。
必要だってことになったら、言語に組み込む方法に持っていかれるだろ。
>>843 そういやマクロだからな
言語に組み込むなら、もっと詳細を詰める必要がありそうだな。
for (int x : v)のような構文でC++0xへ提案があったはず。
とりあえずまだ最新ドラフトには載ってない。
実は n2521 が出てる。
vc は独自拡張で for each なんて作っちゃってるよな
C++/CLIをVCの独自拡張とか言わないで欲しい
C++/CLIはVCの独自拡張。間違いない。
for eachはC++/CLI関係なく、ネイティブC++でも使用できる。 これは、C++でもC++/CLIでもないのだからVC++の独自拡張としか言えない。
むしろ独自拡張以外になんとお呼びすればよいのでしょうか的な
方言。
foreachとかrangeとか、ちょっと節操無さすぎだと思う。 今のC++への不満を直球で解決しようとしてるだけで、 STLが目指してきたものを蔑ろにしている。 autoとλを組み合わせて制御構造そのものはいじらないのが 正常な進化の方向だと思う。
859 :
デフォルトの名無しさん :2008/02/27(水) 23:24:30
#include <iostream> namespace{ void foo(){ std::cout << "anonymous foo" << std::endl; } } void foo(){ std::cout << "global foo" << std::endl; } int main(void) { //foo(); //コンパイルエラー ::foo(); //global foo } ここで無名名前空間のfooを明示的に呼ぶ方法はあるんでしょうか
ない
861 :
859 :2008/02/28(木) 00:46:45
まじすか・・・
無名名前空間って、staticの代わり以外に使い道ある?
>>862 ファイルローカルなクラスや列挙体を囲って ODR 違反を回避する。
namespace_start.hpp------ namespace{ namespace_end.hpp------ } #include "namespace_start.hpp" //... #include "namespace_end.hpp"
>>863 それってつまりどういうこと?
kwsk!!
>>866 // A.cpp
struct X { char x; };
// B.cpp
struct X { char y; };
両方コンパイルしてリンクすると同じクラスに対する2つの定義が異なるという
ODR 違反になり、未定義動作となる。
それぞれ無名名前空間で囲っておけば別々のクラスになるので問題なくなる。
868 :
デフォルトの名無しさん :2008/02/29(金) 02:25:40
class MyClass { private: int a; double b; char c; public: MyClass(int, double); ~MyClass(); void Func(int); }; int main() { MyClass myclass; myclass = MyClass(1, 2.0); } とした場合、myclass = MyClass(1, 2.0)は引数にある変数だけがコピーされるんですか? それともコンストラクタを実行した後のクラスの中身が全部コピーされるんですか?
代入演算子はデフォルトの動作はビットコピーだから
>>869 各メンバに対してoperator=を呼ぶんだと思ったが
どなたかわかる方いれば教えてください。 CE環境のプログラム上で、プログラムカウンタを参照する方法ってありませんか?
関数テンプレートHogeがあるとします。 HogeはT型のオブジェクトtを引数で受け取り、そのオブジェクトのメンバ関数Fugaを呼び出します。 ここで、Hogeに渡したtがFugaを持ってない場合、コンパイルエラーになりますが、 コンパイルエラーにせず、Fugaを呼び出さない別の実装に転送する方法はないでしょうか?
>>872 extern int* puroguramu_caunta asm ("pc");
使えるかどうかはしらね
っつうかスレ違い
>>873 コンパイル時に実装を切り替えるというのは、変態がよく使う。
本当にさまざまな方法がある。
例えば関数のオーバーロードとか、テンプレートクラスの特殊化など
詳しく知りたかったら、C++ Template Metaprogrammingを読め。
で、ある名前のメンバ関数を持っているかどうかってのは、
かなりトリッキーなコードになるので、もっとマシな方法で実装分岐させたほうがいい。
877 :
876 :2008/02/29(金) 15:17:45
>>875 ありがとうございます。
試してみます。
スレ違いになるのね…
すみませんでした。
>>877 C++ Template Metaprogrammingってよお、買ったけどboost::mplの
リファレンスじゃねーか。Webサイト見たほうがいいわ。
騙された。
881 :
873 :2008/02/29(金) 15:59:28
>>874 ,876
どうもです。
省略符号を使ったテクニックがあったんですね。
C++ Template Metaprogrammingは読んでいませんが、Modern C++ Designは読んだので大体分かります。
省略符号を使って変換可能性と継承を検出するテクニックも書いてありましたね・・。
テンプレートに関数ポインタ渡してメンバ関数の有無検出する方法、思いつかなかったorz
>>876 >で、ある名前のメンバ関数を持っているかどうかってのは、
>かなりトリッキーなコードになるので、もっとマシな方法で実装分岐させたほうがいい。
トリッキーでもいいけどC++ Template Metaprogrammingって本に何か例が書いてあるの?
>>882 >>873 がどの程度C++を知っているのか分からなかったから、出してみただけ。
ある名前を持つメンバ関数でコンパイル時の分岐がやりたいなんていいだす奴は、
そもそも何も分かってないバカか、本当に自分が言っている事を理解していて、それでもやりたい変態しかいない。
Modern C++ Desingを枕にするぐらいだったら、必要なかったね。
884 :
デフォルトの名無しさん :2008/02/29(金) 16:29:57
placement newで生成した配列データってどう解放すればいいんでしょうか? void *pvMem = AllocMemory(sizeof(CNode) * num); CNode *pcNodes = new(pvMem) CNode[num]; for(int i = 0; i < num; i++) { pcNodes[i].~CNode(); } FreeMemory(pcNodes); これだとダメみたいです。
placement deleteは呼ばなくてもいいんかい?
>>884 AllocMemory
FreeMemory
ここで何やってるんだ?
>>884 ×FreeMemory(pcNodes);
○FreeMemory(pvMem);
>>884 普通、
void FreeMemory(void*);
のシグニチャだと思うけど。
それなら、それでも良いはずなんだが。
>>885 FreeMemoryでメモリ解放するの特に必要ないかと思って・・・
>>886 AllocMemory(size)
sizeだけメモリを確保
FreeMemory(p)
pが先頭のメモリブロックを解放する
>>887 それもダメでした
890 :
885 :2008/02/29(金) 17:12:51
すまん、placement deleteは関係ないや。 (Effective C++ Item52)
>>889 >AllocMemory(size)
>sizeだけメモリを確保
特別なメモリ確保のライブラリか何か?
AllocMemoryでnew演算子を使用
FreeMemoryでdelete演算子を使用
なんてことじゃないよね?
>>884 new するときもひとつずつ placement new するしか無いんでは・・・
>>891 >特別なメモリ確保のライブラリか何か?
そうです。提供されているもので自作ではありません。ここでは関数名は変えて書きましたが。
>AllocMemoryでnew演算子を使用
>FreeMemoryでdelete演算子を使用
size分メモリ確保してるだけなのでnew,deleteはしていません。
>>884 AllocMemory(size)でreturn operator new(size);
FreeMemory(p)でoperator delete(p);
と思っていい?
>>892 そうなんですかね・・・。なんてこった
実はちょっと前にそっちのやり方で作ってたんですけど、確かにそれはきちんと動いていました。
VCでも似たような状況が再現できました。対処法はわかりませんが #include <iostream> #include <new> class CNode { public : int temp[3]; public: CNode(){ Init(); } virtual ~CNode(){} public : void Init(){ temp[0] = 0; temp[1] = 1; temp[2] = 2; } }; #define PLACEMENT_NEW 0
つづき int main() { char *buf = new char[sizeof(CNode) * 3]; #if PLACEMENT_NEW CNode *pcNode = new(buf) CNode[3]; #else CNode *pcNode = reinterpret_cast<CNode*>(buf); for(int i = 0; i < 3; i++) { pcNode[i].Init(); } #endif #if PLACEMENT_NEW for(int i = 0; i < 3; i++) { // placement newをやっていないと落ちる pcNode[i].~CNode(); } #endif // PLACEMENT_NEW=1のときは落ちない delete [] buf; return 0; }
>PLACEMENT_NEW=1のときは落ちない PLACEMENT_NEW=0のtきは落ちない、でした
確かサイズ指定しなきゃダメじゃなかったけ? そのせいで使い物にならなかった気がする。
>>900 ちょっとよくわかりません。もう少し詳しくお願いします
placement newに対しては、placement deleteを呼ばないといけない。 ちゃんとなってる? CNode::operator delete( p, buf );
>>898 ちょっとまて、placement newしているかどうかにかかわらず、
delete[]が呼び出されるのは何なんだ?
placement newしているポインタに、delete[]したら、鼻から悪魔が出てくるのは当たり前だろ。
あと、placement newしていない場合のコードも鼻から悪魔が出るな。
>>884 ところで、placement new[]に渡されるsizeはsizeof(T)*Nとは限らないぞ。
そこでメモリ破壊してるんじゃねえの。
ちょっと出直してきます。 いろいろ参考になりました。ありがとうございました
>>906 AllocMemory -> operator new(size_t) を使用
FreeMemory -> operator delete(void*) を使用
と思われる。(AllocMemoryのシグニチャでは要素数が判別できないので
内部でoperator new[](size_t)を使用することは難しい)
で、
CNode *pcNodes = new(pvMem) CNode[num];
これはマズイ。
配列用の配置newはCNodeクラスのデフォルトコンストラクタ
をnum回実行する。実装に依存するけど、例えば次のようなことが
考えられる。sizeof(delta)を配列の要素数などの管理情報を確保して
おくための領域のサイズとすると、アドレスpvMemからpvMem + sizeof(delta)
の領域に管理情報を書き込み、最初のコンストラクタはアドレス pvMem + sizeof(delta)
に対して実行される。そして最後のコンストラクタはsizeof(delta)バイトだけ
飛び出した未確保の領域まで初期化してしまう。
結局、非配列用のoperator new(size_t)の戻り値のアドレスに配列用の配置newを
使用することは危険。pvMemを自分で管理して、配列用ではない配置newをnum回実行
して初期化すべきかと。
>>905 ご使用のVCでは管理情報の領域として4バイトが使用されているのかも。
元々の環境では、違うサイズ、あるいは全く異なる実装で配列が管理
されてるのかも。
>261 のリンク先にもあるんだけどさ >SFINAE allows you to determine type information at compile-time through the usage of overload resolution. >However, it cannot prevent non-type syntax errors. An example of which you have demonstrated in your code. >The class member T::Foo does not exist, nor is it a type, as such SFINAE does not apply here. 規格上で SFINAE の根拠になるのは 14.8.2/2 だと思うんだけど、U::Hage はそこで挙がってる type deduction の失敗の例には 入らないので syntax error を引き起こすと思うんだが。いやコンパイル通っちゃったんだけどさ。 で、placement new についてだけど、>887 と >904 他が正しいと思われる。 > 5.4.3/12 > new T[5] results in a call of operator new[](sizeof(T)*5+x), and > new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f). > Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the > new-expression will be offset by this amount from the value returned by operator new[]. This overhead > may be applied in all array new-expressions, including those referencing the library function > operator new[](std::size_t, void*) and other placement allocation functions. The amount > of overhead may vary from one invocation of new to another.
class Holder.....Impl のポインタを持ち、Holder() : m_pImpl(new Default_Impl()){} class Impl.....抽象クラス class Default_Impl.....Impl を public 継承 std::vector<Holder> を持つ これで、Holderのインスタンス作ったらオーバーフローになってしまいました。 調べてみたら、 1, Holder のコンストラクタ 2, Default_Impl のコンストラクタ 3, std::vector<Holder> のアロケータ 4, Holder のコンストラクタ 以下ループ っということらしいのですが、 どういう設計にすれば上のようなクラスを問題なく作成できるのでしょうか。
>>912 やりたいことが間違ってるだけにしか見えん。
違うというのなら何がやりたいのか説明してくれ。
>>913 これ以外に、関数ポインタを受け取れる Func_Impl があって、
Holder(void (*func)(Arg)) : m_pImpl(new Func_Impl(func)){}
のようにHolderを作成できて、
Default_Impl で作ったHolderは上記のような関数を保持するHolderと、
それを複数保持するDefault_Implを保持するHolderを保持したくて、
Holderの operator() で保持してる関数全てを実行するようなクラスを作りたいと思っています。
>>914 なんで Default_Impl のコンストラクタで引数無しの Holder を生成してるの?
>>915 >>Default_Impl で作った
は、
Default_Impl を保持するHolder(引数なしHolderのコンストラクタから生成)
でした。紛らわしい表現をしてすみません…。
理想としては
Holder holder;
holder.add(Holder(関数ポインタ1));
holder.add(Holder(関数ポインタ2));
holder.add(holder2); // 別のHolder
holder(); // 全ての関数を実行
という動作をさせたいと思っています。
>>875 一体何のためにPCなんか参照したいんだ?
>>911 <new>で定義されてるグローバルの配置operator new(size_t, void*)関数である
new(pvMem) CNode[num]; については、pvMemをreturnしてるだけ。
その後で、コンストラクタが必要な回数だけ実行される。その際、配列の管理が
コンパイラ依存で行われる。
>>904 は一般的な配置newについて正しいが、このケースでは<new>のものを使用している
ので
>>908 、
>>910 が上手く表現している。
>918 とりあえず placement new で領域割り当ててるわけじゃない、という点については >908 の方がより的確なのかもしれないけど。 必要なサイズは sizeof(T)*N じゃない、ぐらいの気持ちで。 もともとの placement new の位置づけからすればこっち(別の割り当て済みメモリ領域にオブジェクトを生成する)の方が主な 使い方の気もするけど、AllocMemory とか FreeMemory に突っ込みが入るようだとあまり一般的じゃないのかなぁ。 で、どっちかというと >887 で指摘されてる点があんまり言及されてないのが気になって。 <new> で規定されてるのは allocation function であって、それ自体は単に渡された値を返していたとしても、 new 演算子の結果 new(pvMem) CNode[num] については、allocation fuction から返ってきた値そのままではないよね?
>>916 だからさ、 Default_Impl のコンストラクタで引数無しの Holder を生成しなくても
できるだろ。なんでわざわざ生成して当然の無限再帰を引き起こすのさ?
921 :
868 :2008/03/01(土) 01:11:57
>>920 std::vector<Holder> を初期化するときにHolderのコンストラクタが呼ばれる、ということでしょうか
呼び出し履歴からHolderの引数なしコンストラクタが呼ばれているのは分かったのですが、
Default_Impl のどこで呼ばれているのかとその対策が分からず困っています。
具体的にDefault_Impl の実装のどこが間違っていて、どう対処すればいいのか、
ヒントだけでも教えていただけると助かります。
>>922 Default_Impl の実装を見せずにその間違いを指摘しろとは、エスパーでも募集してんのか?
925 :
912 :2008/03/01(土) 01:29:04
>>925 > Default_Impl() : m_holder(0) {}
vector(size_type n, value_type const& x = value_type()) が呼ばれてる。
空でいいなら m_holder() でもいいし、何も書かずにデフォルトの初期化に
してしまってもいい。
927 :
868 :2008/03/01(土) 01:34:27
すみません。アンカーミスです。
>>870 でした。
>>925 vector<Holder>(0)は、2つの省略可能な引数を持つコンストラクタを読んでる。
そこで、Holder()が生成される。
>>926 , 928
ありがとうございます、無事実行することが出来ました
vector(0) でコンストラクタが呼ばれるはずがない、
という勝手な思いこみで要領を得ない質問ばかりしてしまいましたが、
回答をいただけてとても助かりました。
>>919 ><new> で規定されてるのは allocation function であって、それ自体は単に渡された値を返し>>ていたとしても、 new 演算子の結果 new(pvMem) CNode[num] については、allocation fuction
> から返ってきた値そのままではないよね?
実装依存なので絶対とは言えないけど、ほとんどの実装でそうなっていると思える。
おそらくは配列の要素数を格納するための領域分ずれてる。
実際、配列の要素数は配置new演算子に渡されたアドレスの直後に置かれることが多い。
でも、あくまでも実装依存であって規格では未定義。
でも問題はそれ以前であって、強調したかったのは、規格に従う限りにおいては、
AllocMemoryが戻すアドレスpvMemを配列用の配置構文newに new(pvMem) CNode[num]
のように渡すことさえ問題が起こりうるということ。何故なら、要素数がどこに書
き込まれるかは分からないから。実装を熟知し(配列の管理情報は本当に要素数だけか?
渡すべき正しいアドレスは何か?)、移植性を考えないという条件でのみこれは許され
ることになる。つまるところ、
>>908 と
>>910 のドキュメントどおり、ユーザーが確保した
領域に対して配列用の配置構文newを使うことは難しく、常に危険を伴っている。
配置構文newにどのアドレスを渡してよいかは厳密に言うと実装を知らないと判断できない。
931 :
780 :2008/03/01(土) 03:45:16
思ったんだが、C++で生のC配列なんか使う メリットないだろ。 配列用の配置構文が使い物にならんのは つまりそういうこと。
そもそも設計がおかしくないか?
>>932 つまらないこと言うなよ。
やるなと言えばそれまでだが、やったらどうなるの?
に対する回答にはならん。
>>917 あとから確認するときに、場所を特定するために残しておきたいんです。
>>934 明らかに回答ではないんだから(現在の話題に関して「思ったこと」を書いてるだけ)、
別に回答になっていなくても問題は無いと思うよ。
質問から始まった話題について何か書き込む時は、絶対に回答としての機能を
持っていなければならない、という信念があるとしたら、もうちょっと柔軟になったほうが・・・。
規格では未定義= もしそのコードを実行してしまったら何が起こるか予測できないって事 placement new は将来のために予約されたものだと俺は思ってるから 積極的に使うものじゃないと思う。 コレ使ってるライブラリって見たことない。
>>937 std::allocatorのconstruct
C++0xでアラインメントをサポートするんじゃなかったっけ そうなれば多少マシになるんじゃないの
>>938 サンクス
ユーザレベルなら
std::allocator
boost::pool_allocator
あたり使ったほうがいいですよね?
>>940 placement new 使いたいためにわざわざ std::allocator の construct 使うの?
なんで? placement new 使えばいいじゃない。
>>935 たとえば今のPCは、今居る関数のポインタ値にだいたい近いよね。
それじゃダメなの?
__FILE__と__LINE__で何が不満なわけ?
スタックトレースでもしたいんじゃないの
ドットイートのようなゲームを作りたいんですが、 どうしてもドットを食わず、素通りしてしまいます。 自機がドットを通ると道になるようなプログラムは どうしたらできるんでしょう?
ドットを表す値が入っている変数に道を表す値を代入すればいいんじゃない。
当たり判定チェックミスってんじゃね?
>>945 今はどうやってるんだ
まずそれを説明してみろ
template <typename T> と template<class T> といった 2種類の書き方が存在するみたいだけど、どっちも一緒ですか? あと、使うならどっちが望ましいんでしょう。
どっちも一緒。 template template parameter つまり template<template <typename T> class U> の時だけは class じゃないと駄目。 趣味の問題だから好きな方を使えば良い。
template<class T> class A { private: typename T::B m_abc; } のときはtypenameじゃないとだめ
600000000000を変数に入れたいんですけど、どうすればいいのか教えてください。 unsigned long int r=600000000000 だとinteger constant is too large for "long" type といエラーが出てしまいました。
>>952 厳密な精度が要らなければ double などの不動小数点数を使うといい。
そうじゃなければ多倍長整数を使うことになるでしょう。
>>952 long long int int r=600000000000;
コピペみすったorz long long int r=600000000000;
long long は正式には C++0x から導入されるものだろう・・・。 とはいえ、今の所規格上はそういう型はないしなあ。 まあ、規格で int が 32 ビットと決まってるわけではないから int が 64 ビットの場合もあるわけだが。 まあ、環境によって typedef unsigned __int64 UINT64; か typedef unsigned long long UINT64; かを定義すればいいよ。
まず何故そんな大きな数値を扱う必要があるのか、その理由を・・・ 目的によって double, 多倍長整数, UINT64, BCD など変わってくるだろ
だからそれも C++0x から導入される(略
C99を取り込んでいるコンパイラなら大抵使えるけどな。
よーしパパboost::uint64_t使っちゃうぞー
962 :
952 :2008/03/02(日) 22:36:22
>>952 コンパイラのデータモデルを調べよう
>>958 のようにデータモデル別に定義してくれてるライブラリの型を使うのが安泰
代表的なのだと、gcc4がILP32,LP64、vc++がILP32,LLP64など、
組み込み系だとLP32なんて曲者もあるから困る
class hoge を作っておいて、list<hoge> x を生成します。 そのとき、hogeのメンバ関数も使いたいのですが、STLを使った場合だと x.piyo()みたいではアクセスできません。 どうすれば解決できるんでしょうか?
Spring is here.
>>964 xの中には複数のhogeがあるだろ?hogeのリストなんだから
どのhogeのpiyoを呼びたいんだよ?って話
全部のhogeについて呼びたいんなら、
for (list<hoge>::iterator i = x.begin(); i != x.end(); i++)
i->piyo();
勘違いしてました。 分かりやすくありがとうございました
Spring has come.
Spring to gone.
wind the spring
gone with the wind
ride the wind
cut it out
974 :
デフォルトの名無しさん :2008/03/08(土) 20:52:30
Who are you?
coutやcinのcって何ですか? console?character?
976 :
デフォルトの名無しさん :2008/03/09(日) 11:51:19
977 :
デフォルトの名無しさん :2008/03/09(日) 13:29:11
プリプロセッサフリーにいつかはなるのかな? でもincludeできなくなるのは困るな。 assertも無くなると困るな。
console
the answer is blowing in the wind...
980 :
デフォルトの名無しさん :2008/03/09(日) 16:15:09
演算子オーバーロードはネームスペーススコープでやるのとクラススコープでやるのは 何が違うんでしょうか?
メンバ関数かどうか
>>980 1.クラススコープでしかできない演算子がある。
2.クラススコープの場合、第一引数(this)に暗黙の変換が適用されない。
二項演算子などで引数の対称性を表現できない。
3.非クラススコープで、非public部へアクセスする場合カプセル化の度合い
を弱めることになる。
C++の入門書のお勧めは?
個人的には本じゃなく入門サイトを巡ってみることを勧めるが・・・
入門サイトが正しいかどうか判断できない
一番の王道は言語仕様書
Accelerated C++ あたりか?
入門してからAcceleratedしようぜ。
>>986 だから巡るんだよ
本でもサイトでも1つだけを参考にするのは良くない
>>982 1の理由が2という理解であってますか?
またstaticなメンバやグローバル関数にできない演算子は
= () -> [] の四つであってますか?
入門書はC++Primerの英語のを読んでるけど、分厚くて萎えまくりです。
巡っても結局判断できないと思うが
趣旨分かってる? 質問者は入門、つまりC++を理解し始めたいのであって、 言語仕様書の日本語訳を探してるわけじゃないんだよ
>>993 くだらないこと言ってないでサイトでも本でもお薦めを教えてやればいいのに。
いつも思うが、まずは何でもいいから自分で探してやれよ。 後々、あれは失敗だったなと思うこともあるけどそれも経験だ。 原書含め数十冊読んだが、常に手元に置くものは自然と 決まってくる。それが自分のベストセラー。
教えたくないということだな
998 :
933 :2008/03/09(日) 19:35:44
>>994 だから俺は複数のサイトを自分で巡って見たほうが良いと言っているんだが・・・
むしろお薦めの本を教えてやればいいのは、巡っても意味無いと言う
>>992 とかだろ?
だから、巡るといい複数のサイトの候補を教えてあげればいいんだよ 質問者の趣旨を汲むならね
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。