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


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

C++相談室 part60



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

159 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:11:45 ]
リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ?
VC++2005の #pragma once を使ってる場合ですら200ファイルほどのプロジェクトでリビルド時間が半減したんだけど。


160 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:27:07 ]
>>157
using もヘッダん中ですんのか?

161 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:29:14 ]
precompiled headerになるようにしときゃいいだろ。

162 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:48:04 ]
>>159
よく分からんけど、

#pragma once

よりも、

#ifndef XXXXXXX
#define XXXXXXX

////

#endif

の方がビルド時間が短くなるの?

163 名前:くお [2008/01/26(土) 00:49:00 ]
c++でエクセル用のアドインを作るやり方を教えてください。
よろしくお願いします。

164 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:59:44 ]
>>162
#ifndef XXXXXXX
#define XXXXXXX
#include "myhoge.h"
#endif XXXXXXX

とやって include 行を読み飛ばす方法。
myhoge.h にアクセスする必要がない、展開後のファイルサイズが小さくなる、等の理由でビルド時間が短くなることが多い。


165 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:00:16 ]
くおーっ!

166 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:01:52 ]
>>157
all.h に含まれるヘッダのどれか一つでも更新されると all.h を含むファイルが全てコンパイルされる罠。
all.h をプリコンパイルヘッダにしたところで防げません。

167 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:08:25 ]
批判もいいけど先に解決策を示そうぜ。



168 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:11:42 ]
>>164
なるほど。それだとすると、159の
>リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ?
の理由は、ヘッダファイル使用時にやることが増えるから。かな?

いや、そっちの方が早いってのなら、合理的な理由じゃないとは思うけど
多分159に対する答えは、そんなところだと思う。

169 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:12:55 ]
en.wikipedia.org/wiki/Pragma_once

170 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:39:56 ]
初歩的な質問で申し訳ないのですが、ヘッダファイルの中で行う以下のような
0クリアは問題ないですか?sizeof(this)は正しく計算されます?

class HOGE
{
int a,b,c;
char str[128];

void init(void)
{
memset( this, 0, sizeof(this) );
};
};

171 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:41:18 ]
>>170
やってみりゃいいじゃん

172 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:44:07 ]
いえ、できれば構文的に正しいのか知りたいのですが…
テストのクラスで成功しても、他のクラスでは失敗するかもしれないので。

173 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 02:03:15 ]
>>172
コンパイルが通れば、構文的には正しい。
というのは置いといて、
メンバ変数をクリアしたければ、sizeof(*this)とすべき。
そして重要なのは、その方法が使えるのはPOD型だけ。
例えばHOGEに仮想関数を追加すると、動かなくなる。

174 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 02:03:42 ]
構文って意味分かってんのかいな…。

175 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:01:40 ]
>>173
詳しく有難うございます。納得できました。

>>174
「構文」は間違いでした。>>173のような事を表したかったのですが、
そういう場合は何と呼ぶべきですかね…

176 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:20:13 ]
>>175
つか、何がしたいの?

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);
}

179 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 05:34:13 ]
>>170
sizeof(this) ってポインタのサイズだと思われ
sizeof(*this) にしないとだめなんじゃね?

180 名前:179 mailto:sage [2008/01/26(土) 05:36:04 ]
って、すでに173で指摘されてた・・・

181 名前:110 mailto:sage [2008/01/26(土) 06:16:08 ]
>>177
std::listを使って一本のリストを作って、リストの各要素のオブジェクトを工夫したほうがいいよ。
リストクラス自作するにしても、これはあまりにも酷い。
せめてコンパイルが通りそうなコードを読ませてくれ。

182 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:09:34 ]
>>175
そもそも、クラスの初期化を外部から行なってはいけません。

183 名前:156 mailto:sage [2008/01/26(土) 11:23:55 ]
結局、他の人はどうしてるの?

184 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:48:39 ]
折角階層的にネームスペースを宣言しているのに、ユージング宣言し捲くるってどうなのよ。
そんなばかげたことする香具師いないからレスがつかないんじゃね?

185 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:54:16 ]
using なんて普通は使わないよな。

186 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:04:47 ]
>>166
all.hにはすべてのヘッダファイルではなく、外部から提供されたライブラリのヘッダだけ入れておけば
基本的に更新することはないんじゃない? (その場合、all.hというネーミングは不適切だね。)


187 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:05:50 ]
目的を既に忘れてるな



188 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:18:43 ]
using 宣言は使うだろ。
using しないとコードが汚くなる。
そこらじゅう ns1::ns2::hoge() とか nsN::nsM::hoge() とかばかりになるぞ。

189 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:21:44 ]
ある程度のプロジェクトではファイルの先頭が #include や using で埋め尽くされるのは避けられないこと。
耐えろ。

190 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:22:45 ]
>>188
おまいはヘッダファイルでも using 使って
迷惑かけるタイプか

191 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:26:55 ]
>>190
どっからヘッダファイルで using なんて考えが出てきたんだ?
*.h と *.cpp では書くものが違うのはあたりまえだろうが。常考。


192 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:32:23 ]
using なんて使わなくても
名前空間のエイリアス作ればいいだろ。

193 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:35:08 ]
>>188
namespace fuga1 = hoge1::hogeA::hogeX;
namespace fuga2 = hoge2::hogeB::hogeY;
namespace fuga3 = hoge3::hogeC::hogeZ;
……
みたいな解決策もある。


194 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:36:58 ]
using は関数増えた時に別の関数が選択される恐れがあるから怖い。
エイリアス作ろうぜ。

195 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:40:22 ]
>>194
例は?
using 指令と違って using 宣言では名前が衝突するとコンパイルすら通りませんが?


196 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:41:57 ]
そもそもネームスペースが上手く使われてる大規模プロジェクトって見たことないな。
パッケージ名を接頭辞に持つプロジェクトの方が上手くいってたりする。

197 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:44:54 ]
>>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
}



198 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:48:05 ]
>>193 の方法でいいんじゃない?
これなら普通は namespace の数 < 識別子の数 なので先頭部分は少し短くなる。
ただし、その代わりにコードは少し長くなる。
どっちにしろ先頭が namespace で埋め尽くされるのは変わらないが。


199 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:54:22 ]
そだよ。エイリアスが一番マシ。

ただ、エイリアスは .cpp のグローバルでのみ作るべし。
名前空間内で作っちゃうとまたややこしい問題が生じる。

200 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:59:57 ]
グローバルで using してたら意味ないだろ。
namespace HogeHoge {
 using Hoge::Foo;
 void Foo();
}
で普通にエラーでたぞ。

201 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:43 ]
>>200
あらホント。

202 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:57 ]
namespace Hoge { void Foo(); }
namespace HogeHoge{
namespace Hoge { void Foo(); }
void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo
}

別に間違いようはいくらでもある。

203 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:06:33 ]
名前空間って厄介だよな。

204 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:08:55 ]
>>202
これって防ぎようなくね?
どうすんの? これ。

205 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:11:53 ]
>>204
::Hoge::Foo() でアクセスできるよ。



206 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:12:27 ]
>>205
なるほど・・・。
でも、常日頃から :: から始めないと防げないよな。

207 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:13:53 ]
そもそも他人の名前空間と同じ名前の名前空間を
後から作るという時点で間違いだとは思うが、
開発中に後から導入したライブラリが・・・ということもあるか・・・。



208 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:17:40 ]
ちなみにこんなのも。

namespace Fuga { void Foo(); }
namespace Hoge = Fuga;

namespace HogeHoge {
class Hoge { public: static void Foo(); };
void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo();
}

209 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:22:31 ]
名前空間はクラス名・関数名・変数名なんかと違って規約がなかったりするから、結構みんなテキトーにつけてたりする。
酷い話だとグループ全員が自分用の関数を mylibs に入れていた例が...


210 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:25:14 ]
幾何学ライブラリで geom が衝突したりとかだな。

211 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:28:54 ]
かといってJavaみたいにドメインを逆さにするのもなぁ

212 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:32:14 ]
>エイリアスは .cpp のグローバルでのみ作るべし。
グローバルに alias 作るとヘッダが変わったときに突然コンパイルが通らなくなることあるよ。


213 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:35:49 ]
前に関ったプロジェクトは常にフル指定?でメソッドを呼び出すべし

という規約があった

基底クラスのメソッドさえも
Hoge::Foo:Base:Dosomething();

多重継承を多用していたからという事情もあるんだけど

面倒だけど、安全ではある

214 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:46:38 ]
その面倒なのがイヤだから using を使いたい、alias を使いたいってんだと思うが。
ぐるっと一周してきた感じだな。

215 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 14:07:49 ]
グローバルにエイリアス量産するぐらいなら名前空間内で using 宣言した方がいいと思う・・・

216 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 18:53:06 ]
しかしだな、エイリアスと別の名前空間が衝突することもあってだな・・・。

217 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 19:00:54 ]
無限下降スパイラル



218 名前:177 [2008/01/26(土) 19:12:06 ]
>>181
すいません、文字列クラスがcharacterDataではなくDatabaceでした。
>std::listを使って一本のリストを作って
listやmapを使うことも考えたんですが、リスト化した後のタイプの分岐判定のアルゴリズムが思いつかず断念しました。
なのでその辺のアルゴリズムのアドバイスも出してくれると助かります。
>コンパイルが通りそうなコード
コンパイルも通って動作確認もしてあるので正常に動作しているとは思います。
ただ、これだけ乱雑になると可読性に欠けてバグの温床になりそうなのでアイディアを聞きたいと思った次第です。

219 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 01:56:06 ]
>>175
遅レスだけど、
そういう場合は鼻から悪魔がでますか?って聞けばいいよ。

220 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 11:37:37 ]
//xxx.cpp
namespace
{
namespace ns = long::longlong::longlonglong::ns;
}

void F1()
{
ns::Foo();
}



221 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 13:21:55 ]
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 mailto:sage [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 mailto:sage [2008/01/27(日) 13:54:47 ]
int const val;
のように変数valを定義した場合、valの型にconstは含まれるのでしょうか?

int const& ref;
の場合は、refの型は int const& となりconstは含まれますよね?

224 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:46:48 ]
int const val; と const int val; は等価。
val の型に const は含まれる。

225 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:57:41 ]
>>222
パラメータリストのconst修飾は関数の型としては無視される、
ということからだろうと思われる
たとえばvoid f(int);とvoid f(int const)の型は全く同一になる
f<int const>(j); とすれば 2 が表示されることに保証があるのか
俺は知らない

226 名前:221 mailto:sage [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 ともに同じ結果でした。


227 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 16:49:54 ]
そもそも const int を int な引数の関数に渡せるしね。
規格でどうか知りたいなら、規格を読むのが一番だ。



228 名前:221 mailto:sage [2008/01/27(日) 17:09:22 ]
>>227
それはvalue functionのパラメータ及び引数のルールであって、
テンプレートのtype parameterのdeductionはまた別の問題のよ
うに思います。もう少し規格を見てみます。


229 名前:221 mailto:sage [2008/01/27(日) 17:12:18 ]
>>227
>>228は撤回します。
確かにそれが理由のような気がします。
そうすると、const int と T を比べると T が intに
deductionされるのも頷けます。

230 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:14:12 ]
>>226
>partial specializationが使用 されることは間違いないです

ああそりゃそうか

>これはテンプレートの標準における正しい仕様なのでしょうか?

14.8.2 -3-にあった


231 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:17:06 ]
手元にドラフトがあるのでそれで調べてみたが、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.

232 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:18:11 ]
あー、そっちかもしれん。>>230

233 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:19:04 ]
>>226
type function とか value function とか、何の方言?
意味がわからない。

234 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:20:09 ]
最新のドラフトを見ると怖いことが書いてあった

[ 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 ]

235 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:24:04 ]
>>234
まあ明示的に指定する分には違っててもいいんじゃね?

236 名前:221 mailto:sage [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

すっきりしました。

237 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:40:02 ]
int const& の const はトップレベルの const じゃないからそうなるわな。なるほど。



238 名前:221 mailto:sage [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と考え
ると通常の関数のように関数とみなせるというもだと
理解してます。

239 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 18:03:50 ]
>>238
「テンプレートの本」ってどれだ?

普通に「関数」と「クラステンプレート」って言ったほうがいいと思うよ。
意味の違いを正しく表している呼び名だとは思えないからね。
後者は「(テンプレート)メタ関数」とか呼ばれるもののような気もするなぁ。

240 名前:221 mailto:sage [2008/01/27(日) 18:36:02 ]
>>239
ここでいうtype functionとは
最近の言葉で表せばメタ関数でしょうね。
Boost::mplなどの最近のメタプログラミングで
使われていますが。

本はC++ Template The Complete Guideです。
著者は標準化委員会の現メンバーでもあり
信用できないものではないと思います。

通常の関数と対比して、コンパイル時に型を引数
とする”関数”という概念的に上手い言葉だと感じ
ているので自分はなるほどと思いました。


241 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:21:38 ]
>>240
メタ関数でいいならそう言ったほうがいいでしょ。
わざわざ廃れた用語を使い続ける理由もない。

242 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:32:18 ]
meta function == type function
別に正式な名前じゃないけど、
type functionってのはそこそこみる表現だから覚えておいてもいいと思うよ

243 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 23:07:12 ]
>>241
別に廃れてるわけではないよ。
概念を表した言葉だから。

244 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 11:46:24 ]
適当なオブジェクトのポインタが与えられたとき、そのオブジェクトのクラスがある特定の
名前と引数のタイプを持ったメンバ関数を持つときに限りその関数を呼んで処理したい
のですが、C++ で可能でしょうか?

あ、オブジェクトは必ずしも共通のスーパークラスを持たないとします。要はそういう
場合でも仮想関数的なことをしたいというか...
その特定のメソッドをもつ別クラスを作って、それを全てのオブジェクトで多重継承、
というのも考えているのですが、ちょっとダサいかな? と思って。あとソースのないクラス
では無理ですよね(今のところはソースのあるクラスだけでいいんですが)。

そもそもこんなことを考える事自体ナンセンス、と言われるとアレなんですがw

245 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:35:21 ]
ポインタの型がテンプレート引数で与えられているならば、可能

246 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:41:29 ]
>>245 嘘だろ。怪しいからソースを晒してください。

247 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:44:38 ]
>>244おとなしく多重継承すべし。



248 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:52:14 ]
>245が言いたいのは「コンパイル時にクラスが確定できる」場合だろ。

249 名前:245 mailto:sage [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 mailto:sage [2008/01/29(火) 13:42:58 ]
最後の一行間違ってるけど気にしないで

251 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:42:17 ]
template < typename Y > static Yes test(typename Y::hage const *) ;

はおかしくないか?
マッチしなかったぞ。

やるなら

template < typename Y > static Yes test(void (Y::*)(void));

か?

でも、これじゃあ関数名の一致の評価はムリだな。
何か仕組みが必要か。

252 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:42:50 ]
struct BjarneStroustrup
{
void hage(){cout << "hage" << endl; }
};
struct Others
{
void fusafusa(){cout << "fusafusa" << endl;}
};

253 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:43:13 ]
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);
}


254 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 14:44:52 ]
int main()
{
BjarneStroustrup b;
call(&b);

Others o;
call(&o);
}

255 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:02:09 ]
struct BjarneStroustrup
{
typedef void HAGE;
void hage() const {cout << "hage" << endl; }
};

こういう風に typedef 定義して(擬似的な名前一致)

template < typename Y > static One test(typename Y::HAGE *);

じゃだめかいな。

256 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:34:33 ]
これじゃあシグニチャが合わないか。

257 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:45:03 ]
ちょっと変更

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>();
}




258 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 15:46:00 ]
こっちだった。

template <typename T>
struct has_hage
{
・・・・
template < typename Y > static One test(void (Y::*)(HAGE));
・・・・
} ;

259 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 17:12:00 ]
このスレって頭悪い奴多いね






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

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

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