トップページtech
985コメント328KB

Generic Programming with C++ Template

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
C++ による Generic Programming の話をしよう。

参考図書:
Modern C++ Design
Andrei Alexandrescu, Addison-Wesley, ISBN:0-201-70431-5
(訳書: ピアソン・エデュケーション, ISBN:4-89471-435-3)
http://cseng.aw.com/book/0,,0201704315,00.html

Generic Programming - STL による汎用プログラミング
Matthew H. Austern, ASCII, ISBN:4-7561-3441-6

関連スレッド:
C++相談室 Part3
http://pc.2ch.net/test/read.cgi/tech/1003832761/

STL スレッド
http://pc.2ch.net/test/read.cgi/tech/1004287394/
0488デフォルトの名無しさんNGNG
>>487
http://www2.tky.3web.ne.jp/~bandai/24net/prog2/tips1.html
0489デフォルトの名無しさんNGNG
>>487
だめだよ。大抵のコンパイラはtemplateの展開可能レベルが浅い。
0490デフォルトの名無しさんNGNG
最近のコンパイラは最低限のunrollは行ってくれる
最近のCPUはunrollするとキャッシュのミスヒットでパフォーマンスが低下する
0491デフォルトの名無しさんNGNG
>>490
unrollする量でチューニング。
テンプレートを利用した行列計算でメモリ階層を意識して
ブロック化、ループ展開などの最適化を施した例としてMTLがある。
0492480NGNG
>>484
いや、Typelistのとこでの話なんですから、コンパイル時に初期化が
終わるんじゃないかと。
このやり方だと、実行時に初期化してますよね。
0493480NGNG
この58ページの雰囲気的には、

std::type_info* intsRtti[Length<SignedIntegrals>::value] =
{
 TypeAt<SignedIntegrals,0>::Result,
 TypeAt<SignedIntegrals,1>::Result,
 TypeAt<SignedIntegrals,2>::Result,
 TypeAt<SignedIntegrals,3>::Result,
 // Lengthの示す長さ分だけ続ける…
}

これを、コンパイル時に自働的に解決するための汎用性のある書き方が存在する、
ってことだと思うんですよ。

…どうすりゃいいんでしょうね。
0494デフォルトの名無しさんNGNG
配列の要素が静的に初期化できる構文といえば

double a[3] = {1.0 ,2.0 ,3.0};

だが。テンプレートから生成できるとは思えんしなー。
まさか、

template<class T, int N>
struct A
{
T d = T(N)/*constant expression of N*/;
A<T, N-1> succ;
};

template<class T>
struct A<T,1>
{
T d = T(1)/* constant expression */;
};

template<class T, int N>
const T* getArray(const Struct<T,N> s)
{
return((T*)(&s))
}

なんてこたないよな。
仮想メンバ関数もなく継承とかもしてないstructはCの構造体と互換だが……。
移植性あるか?(alignment調整のpackingとか。)
0495494NGNG
>>494
今、手元にコンパイラがないんで未テスト。スマソ。
0496494NGNG
>>494
ごめん。packing -> padding
0497494NGNG
//さすがに動かなかったよ。

#include<iostream.h>

template<int N>
struct Init
{
static const double data = Init<N-1>::data * double(N);
static const Init<N-1> succ;
};

template<>
struct Init<1>
{
static const double data = 1.0;
};

template<int N>
inline const double* getArray(const Init<N> a)
{
return((double*)(&(a)));
}

Init<5> init;
const double* a = getArray(init);

int main(int Argc, char* Argv[])
{
cout << "\n";

for(int i = 0; i < 5; i++)
{
cout << " " << a[i];
}

cout << "\n";

cout << init.data << " ";
cout << init.succ.data << " ";
cout << init.succ.succ.data << " ";
cout << init.succ.succ.succ.data << " ";
cout << init.succ.succ.succ.succ.data << " ";

cout << "\n";

return(0);
}
0498494NGNG
>>497↑はコンパイルは通るけど結果は思ったようにならない。
結果:

4.85246e-270 2.96439e-323 5.08888e-322 1.58101e-322 4.85634e-270
120 24 6 2 1

ある意味ホっとした。
0499デフォルトの名無しさんNGNG
>>497
・・・えーとさぁ。突っ込んでいいかなあ?

> return((double*)(&(a)));
ここでアドレス取ってるけど、これって getArray の引数 a のアドレスだよなぁ?
getArray の引数 a は getArray の終了時にスタックから消滅してるから、
そのアドレスを戻り値として返すのは不正なんじゃなかろうか。

それと、Init<5> の非スタティックメンバって何もないから、
sizeof(Init<5>) = 0 (あるいは 1)のはずで、
それを double にキャストして逆参照してもゴミ値なんじゃないの?
0500494NGNG
>>499
そうすね。頭寝てました。
0501デフォルトの名無しさんNGNG
std::iterator_traits<int*>::value_type val;

C++スレに書かれてたやつだけど、なんかこっちのほうがふさわしそうなんでこっち持ってきた。
VC++6でコンパイルエラーだそうです。

VC++.NETでコンパイルしたら

> xutility(98): error C2825: '_Iter::iterator_category': 限定名を形成できません。
> xutility(98): error C2039: 'iterator_category' : 'operator``global namespace''' のメンバではありません。
> xutility(98): fatal error C1507: エラーが多すぎてコンパイルを継続できません。

って言われた。
ツールチップの型ヒントではちゃんとintのtypedefになってるんだけど、
なぜコンパイルできないんでしょう?
0502デフォルトの名無しさんNGNG
>>501
そのソース、g++とかだと通るの?
0503デフォルトの名無しさんNGNG
>>502
501じゃないけど、g++ならふつうに通るみたいだよ。
0504501NGNG
調べてみました、VC++のコンパイラの能力ではiterator_traitsをポインタに対して特殊化することが出来ないんですね。
そのため特殊化されていない形式のiterator_traitsを構築しようとしてコンパイルエラーが出ているようでした。
STLのソースの中でもiterator_traitsはほとんど使用されていませんでした。
Genericの中に書かれている古いタイプの方法に近い形で実装されているようです。
0505デフォルトの名無しさんNGNG
ああ、まだ上には上がいるんだな。
勉強が足りなかった。
0506デフォルトの名無しさんNGNG
>>303
これってどういう意味? 8章を読んだけど全く理解できなかったってこと?
それとも、全部理解したけど期待した程じゃねーぞゴルァ、ってこと?
0507デフォルトの名無しさんNGNG
>>506
一ヶ月前のレスだぞ?
0508たんなる雑談NGNG
画像の描画処理にPoplicyを使うことにしました
描画処理は
・速度が要求される
・透過、拡大、反転など組み合わせ次第で処理の量が膨大になる
ということでPolicyの考え方にまさにベストマッチですが、
どこをPolicyクラスにしてどこをtemplateクラスにするのかの判断はやっぱり難しいですねぇ。
Policyの境界を越えた最適化が出来ないというのもちょっとネックになりそうです。
0509デフォルトの名無しさんNGNG
>Policyの境界を越えた最適化が出来ないというのもちょっと
これは層化の設計の問題でしょ。
下層で問題になるなら上層のPolicyをごっそり入れ替えればよし。

余談:Policyテクニック自体はSTLが存在するころから存在してるよね。
   STL自身が使ってるから。
0510508NGNG
う〜〜ん使いこなせるようにはまだしばし時間が必要(^^;
0511デフォルトの名無しさんNGNG
http://pc.2ch.net/test/read.cgi/tech/1021548960/3
>書籍中で紹介、また使用されているライブラリLokiはVC++ではコンパイルできません(;_;)サイアク・・・
これって、ちょっとした手直しとかのレベルでは、
使える様にはならないのかな。
0512デフォルトの名無しさんNGNG
>>511
誰か手直ししたら漏れにも下さい
0513デフォルトの名無しさんNGNG
>>511
ほんの一部なら動くがほとんどはダメです。
LokiのキモであるところのTypeListは
テンプレートの部分的な特殊化を前提に組まれてます。
再帰的な処理、その終端の特殊化もその機能に依存してます。
そしてVCでは部分的な特殊化はサポートされません。
これはヘルプにはっきり書いてあります。
0514デフォルトの名無しさんNGNG
じゃあだめじゃん。
クリティカルな問題が無くならないね。
もうちょっと単純な仕様にすればいいのに。>テンプレート
0515デフォルトの名無しさんNGNG
↓これどうなん?

Q: 他のC++ ツールで、より標準に適合しているものはありますか?

JON CAVES: はい、Visual C++よりも標準に適合するC++ コンパイラはあります。
1つの例は、私が100%適合していると信じるEdison Design Group (EDG)によるコンパイラです。
ただし、このコンパイラはWindows プラットホームではあまり利用できませんが。
Windows プラットホームではやはり、Visual C++が最も標準に適合するコンパイラの1つです。
0516デフォルトの名無しさんNGNG
>>515
一長一短ではあるけど、
gcc3 、CodeWarrior7、 bcc5.6 (C++Builder) 辺りは
VC6よりは遙かに標準に近い気がする。VC.NETだとどうなんだろ?
それに、EDGのフロントエンドも100%とは思えないが…。
0517デフォルトの名無しさんNGNG
VC.NETのテンプレート機能はVC6と大差ないです。
テンプレートパラメータがサポートされた程度。
てゆうかLokiコンパイルできません。
0518デフォルトの名無しさんNGNG
>>517

>テンプレートの部分的な特殊化

はどうなの?
0519デフォルトの名無しさんNGNG
VC6と変わりません。つまりダメ。
>>513 はVC.NETでの話。
0520デフォルトの名無しさんNGNG
テンプレートの部分的な特殊化は実装がなかなか複雑なようで
その優先順位の判断にパターンマッチングやらなんやらが必要らしいです。
しかしModernC++によって部分的な特殊化がほぼ別物といっても良いくらい
飛躍的な表現力の向上につながることが明らかにされたわけなので
今後積極的にサポートされていく可能性は高いでしょう。
0521369NGNG
>>519
だ、ダメなんすかー!? がーん。
0522デフォルトの名無しさんNGNG
ModernC++はほんとパラダイムシフトだよね。
あれでコンパイラメーカーの奮起を期待したいところだね。
VC++に関してはどうなんだろう。MSやる気あんのかなぁ。。

個人的には.netでのアクロバットなテンプレートサポートに
期待してるけどね。
0523デフォルトの名無しさんNGNG
>>522
Adobe Acrobat.NET(テンプレート付き)
0524デフォルトの名無しさんNGNG
ワロタ
0525名無しさんNGNG
gcc 3.1 でてるね。
0526デフォルトの名無しさんNGNG
C++じゃ無くても良いんじゃないのかな。
0527508NGNG
デキタ━━(゜∀゜)━( ゜∀)━(  ゜)━(  )━(゜  )━(∀゜ )━(゜∀゜)━━!!!!!

拡大反転透過楕円半透明コピーが出来たときには感動した!!
馬鹿正直に書いてたら数千〜数万行のコードがたったの500行ですんだ、すごいYO!!
0528デフォルトの名無しさんNGNG
『Moder C++ Design』を読んでいるのですが、
公式サイトからダウンロードしたソースに、バグらしきものを発見しました。

該当個所は、第四章で紹介されているFixedAllocatorのVicinityメソッドです。
SmallObj.cpp の中で以下のようになっていますが(左は行番号)、

271: Chunk* lo = deallocChunk_;
272: Chunk* hi = deallocChunk_ + 1;
273: Chunk* loBound = &chunks_.front();
274: Chunk* hiBound = &chunks_.back() + 1;

もし deallocChunk_ が &chunks_.back() と同じ値であった場合、

290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength)

この hi が指しているのは範囲外の要素となってしまいます。
これは既知のバグなのでしょうか。
参考までに VicinityFind メソッドを全文引用しておきます。



264:FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p)
265:{
266: assert(!chunks_.empty());
267: assert(deallocChunk_);
268:
269: const std::size_t chunkLength = numBlocks_ * blockSize_;
270:
271: Chunk* lo = deallocChunk_;
272: Chunk* hi = deallocChunk_ + 1;
273: Chunk* loBound = &chunks_.front();
274: Chunk* hiBound = &chunks_.back() + 1;
275:
276: for (;;)
277: {
278: if (lo)
279: {
280: if (p >= lo->pData_ && p < lo->pData_ + chunkLength)
281: {
282: return lo;
283: }
284: if (lo == loBound) lo = 0;
285: else --lo;
286: }
287:
288: if (hi)
289: {
290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength)
291: {
292: return hi;
293: }
294: if (++hi == hiBound) hi = 0;
295: }
296: }
297: assert(false);
298: return 0;
299:}
0529直してみたNGNG
264:FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p)
265:{
266: assert(!chunks_.empty());
267: assert(deallocChunk_);
268:
269: const std::size_t chunkLength = numBlocks_ * blockSize_;
270:
271: Chunk* lo = deallocChunk_;
272: Chunk* hi = deallocChunk_; // ココ
273: Chunk* loBound = &chunks_.front();
274: Chunk* hiBound = &chunks_.back() + 1;
275:
276: for (;;)
277: {
278: if (lo)
279: {
280: if (p >= lo->pData_ && p < lo->pData_ + chunkLength)
281: {
282: return lo;
283: }
284: if (lo == loBound) lo = 0;
285: else --lo;
286: }
287:
294: if (++hi == hiBound) hi = 0; // ココ
288: if (hi)
289: {
290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength)
291: {
292: return hi;
293: }
295: }
296: }
297: assert(false);
298: return 0;
299:}
0530デフォルトの名無しさんNGNG
行番号ウザイ
0531デフォルトの名無しさんNGNG
return 0 は0行目に戻れな罠。
0532528NGNG
>>529
おー、これだとたしかになおってそうですね。
つうか、オレもなおしちゃったけど。
もし未知のバグなら、報告したほうがいいんですかね。英語わかんねえけど。

>>530
がんばって行番号つけたのにッ! BASICを使ってた思い出に浸っていたのにッ!
オレの思い出をこわさないでー!

>>531
んなわけねえだろ。だいたい0行目なんて存在しねえんだよ。
テメエはCのやりすぎだ。一日二回くらいにしといたほうがいいぞ。
0533デフォルトの名無しさんNGNG
>>532
なんか、ギャップにワラタ
0534デフォルトの名無しさんNGNG
>>532
訳者のページに行ってみてはどうか。
オンラインで直ってないなら未知と思われるので。
0535デフォルトの名無しさんNGNG
>>532
me fix bug. this patch
とか書いてdiff結果張り付けてメールとか。
0536528NGNG
とりあえずいろいろ検索してみたら、同じようなことを書いているようなページ発見。
でも英語なので、あいかわらずよくわかりませんです。
http://www.kuro5hin.org/story/2002/4/5/82022/76326

>>533
ギャップってアレか。テキストエディタつくるときに使うとか聞いたことあるやつ。
それはギャップバッファだー! ちゅどーん!

>>534
訳者の方のページは見てみましたが、誤植の情報しかないようでした。残念賞。

>>535
出会い系サイトじゃないと、知らない人にメールなんて出せませんよ。怖すぎ。
しかも外人さんだし。やけに深呼吸ばかりしてそうだし(洋モノビデオの見すぎ)。
0537デフォルトの名無しさんNGNG
>>529
ワロタ。
0538デフォルトの名無しさんNGNG
528が常駐してからスレの雰囲気が悪くなったな
0539デフォルトの名無しさんNGNG
うむ
0540528NGNG
>>538-539
あら、雰囲気悪くなっちゃった? ユーモアってやつをわかってねえなあ。
ほれ、良書って言われる類の書籍には、たいていアメリカンジョークが書いてあるじゃん。
それもすっげーつまんないやつ。立派なプログラマなら、それで笑えるようになろうぜ。

理想としては、>>537の人みたいにソースコードを見ただけで
笑いがこみ上げてくるレベルを目指すべし。
0541デフォルトの名無しさんNGNG
>>540 面白くもないモノに笑えるほど出来た人間じゃないんでね。
キエロ
0542デフォルトの名無しさんNGNG
541<<<<<<<<<<<540
0543デフォルトの名無しさんNGNG
>たいていアメリカンジョークが書いてあるじゃん。
528のはそれ未満なので笑えません。
0544デフォルトの名無しさんNGNG
>>542
それはあり得ない。
常に541>540である
0545デフォルトの名無しさんNGNG
いやホント、>>528って救いようがないよ。
0546デフォルトの名無しさんNGNG
せめてIQが平均気温より高ければなぁ。
0547デフォルトの名無しさんNGNG
>>546
単位は?

(ケルビンじゃないよな)
0548デフォルトの名無しさんNGNG
528って自分に自信のないデヴオタヒッキーなんだろうなぁ…
なんか、某駄スレのJohnに酷似しているし。

0549デフォルトの名無しさんNGNG
Johnの方が小賢しいな
0550デフォルトの名無しさんNGNG
テンプレート使いまくりのコード書いたら
コンパイル速度激しく遅くなったんですが(;´Д`)
PCHにいれても入れなくても変わらず
自業自得ですけど・・・死ねるほどおそひ・・・VC.NET・・・
0551デフォルトの名無しさんNGNG
PCH使って死ぬほど遅いのは、9割方使い方がおかしいだけ。
0552デフォルトの名無しさんNGNG
ちょっとした短いコード(10行以内?)以外は
インライン実装するべきじゃない。
デメリットのほうが大きい。
素直にテンプレートの具体的な特殊化か
ポリモフィズムを使用するべし。
0553デフォルトの名無しさんNGNG
>>552
昔の実装と違ってinlineはregisterと同じくもはやヒントでしかないし……。
そうカリカリせんでもいいんじゃない?
(暗黙のstticの意味を除けば。)
0554デフォルトの名無しさんNGNG
ほっしゅほっしゅ
0555デフォルトの名無しさんNGNG
>>552
VC++の場合ちょっとでも大きいとインライン展開してくれないようです
3行くらいでもわりと複雑な計算してると展開されません
チョー速度が要求されるところだったから__forceinline使いましたが
0556デフォルトの名無しさんNGNG
差分コンパイルができない。=
依存関係のある全てのソースにリコンパイルがかかる。
また、インライン展開されなくとも複数の実体が生成される可能性もある。
そもそもインライン展開の判断自体、処理系依存である。
ちっこいプロジェクトなら問題ないかもしれんが
大規模ではちょっとした手抜きの割に被害はでかい。
テンプレートの使い方とその設計手法をまともに考えれば
クソでかい関数はできないはず。
0557デフォルトの名無しさんNGNG
テンプレートだけ変換することってできない?
0558デフォルトの名無しさんNGNG
>>552 が言っていることがよくわからなんだけど、
inlineとexportしてない(できない)templateとtemplateの明示的特化って
別物じゃないの?
0559デフォルトの名無しさんNGNG
ああまだ上には上がいたんだな(´Д`)
出直そう
0560552NGNG
>ちょっとした短いコード(10行以内?)以外は
>インライン実装するべきじゃない。
>デメリットのほうが大きい。
ここは一般論でその理由は>>556

>素直にテンプレートの具体的な特殊化か
>ポリモフィズムを使用するべし。
こっちは>>550に対してアドヴァイスしたつもりだった。
言葉足らずスマン。
テンプレート関数をexportできる処理系はまだ見たこと無いので
無いものとして話してる。

補足:
>テンプレートの具体的な特殊化
具体的な特殊化でテンプレート引数がすべて決まれば
普通のクラスと同じように非インライン関数として書ける。
テンプレートの用途からするとほとんど使えないテクだが・・
0561デフォルトの名無しさんNGNG
以下のようなテンプレートの特殊化がVC++(ver6)では通らないんですが
何が問題なのでしょうか?g++ならば通るんですが・・・。

template<typename T, typename U> struct test {};
template<class T> struct test<int,T> {};
0562デフォルトの名無しさんNGNG
>>561
VC++は諦めてください
0563561NGNG
マジですか?>>562
いやほんとに頼みます。
0564デフォルトの名無しさんNGNG
>>563
マジです
0565561NGNG
>>564
ありがとうございます。ショックでかいです。
で質問なんですが.NETなら大丈夫とかないですか?
スレとずれて恐縮なんですが。
0566デフォルトの名無しさんNGNG
>>565
.NETでもダメです。
正直がっかりでしたがVC8に期待しましょう。
0567561NGNG
>>566
ありがとうございました(TДT)
0568デフォルトの名無しさんNGNG
VCっていう前提が取れないところが素晴らしい
0569デフォルトの名無しさんNGNG
いまさらVC使う意味は無いと思うんだが。
0570デフォルトの名無しさんNGNG
VitaminC
0571デフォルトの名無しさんNGNG
お金が無いんだよ!!無職なんだから
0572デフォルトの名無しさんNGNG
お金がないならそれこそどうしてVC++?
0573デフォルトの名無しさんNGNG
VSのIDEでコンパイルだけgcc使えればいいのに・・・。
0574デフォルトの名無しさんNGNG
デバッグできないから意味無いじゃん
0575デフォルトの名無しさんNGNG
IDEというのはこれとなんか関係してますか?

http://www.objectcentral.com/
0576VC6に乗せたいNGNG
VS.NETが買えない貧乏人の私としては、VC6で何とか動かしてみたい。

template <class TList>
struct Length
{
  enum { value = 1 + Length<TList::Tail>::value };
};
template <> struct Length<NullType>
{
  enum { value = 0 };
};

template <class TList, unsigned int i>
struct TypeAt
{
  template<int cnt>
  struct isEnd
  {
    typedef typename TypeAt<TList::Tail, cnt-1>::Result type;
  };
  template<> struct isEnd<0>
  {
    typedef typename TList::Head type;
  };
  typedef typename isEnd<i>::type Result;
};

こういう風に書き換えればTypeListを使うことができるようになった。
既出ならスマソ
0577デフォルトの名無しさんNGNG
>>576
なんだかわからんけど、よくやった!
次もこの調子でたのむ。
0578デフォルトの名無しさんNGNG
>>576は神!!
0579デフォルトの名無しさんNGNG
>>576
よくやった!

ただ、
不明な型が厳密にひとつしかないクラステンプレートなら
部分的な特殊化を使わずに実装できるんだが
TypeListにはそうでない機能がいくつかあるんだよね。
0580デフォルトの名無しさんNGNG
VC++で無理やりSingletonHolderを動くようにしたんです。
って言ってもtemplateなstatic変数が作れないだけですから、
マクロ作って個々にインスタンスを作ってやっただけですけど。
で、ためしにLoki::SingletonWithLongevity使ってみたら
GetLongevityの戻り値が大きいほうから先に削除されちゃうんです。
ここでまたぶち切れですよ。
ModernにはGetLongevityの戻り値が小さいほうから削除されるように書かれているのに。
これはどう解釈したら言いのでしょう。
0581デフォルトの名無しさんNGNG
>>576
VC++でSelectをなんとか出来ませんか?
0582VC6に乗せたいNGNG
昼頃出先で書き込もうとしたら、串が2ch鯖に知られてて書き込めず、激しく鬱。
それはさておき。

VC++6.0は、ご承知のようにクラステンプレートの部分的な特殊化を
サポートしていません。
しかし、クラステンプレートの完全な特殊化はサポートされています。

[VC6で使えない例]
template <class TA, class TB>
struct baa{};

template <class TA>
struct baa<TA, int> ← すでに定義されているというエラーが出る
{};

[VC6で通る例]
template <class T>
struct baa{};
template <> struct baa<double> {};

あるいは、
template <class TA, class TB>
struct tee{};
template <> struct tee<double, int> {};

これだけなら大したことはできないのですが、
これをTypeAtのように、クラス内クラスで使うことで、
事実上の部分特殊化を掛けることができるようになります。

現在、手元でIndexOf まで仕上げました。
私はファンクタとダブルディスパッチを使いたいと思っているので、
それらの実装を目指すことにします。
0583デフォルトの名無しさんNGNG
>>582
おぉぉ!

template< A, B, C >

Aだけ特殊化は出来ないから
template< A > class{ template< B, C > }
にしてAを特殊化するんですね!
Select行ってみます!
0584583NGNG
Selectはできたけんども
TypeAtNonStrictで見事に撃沈・・・
完成したら作者に報告とともにどっかにウプしてくれ・・・>>583
0585583NGNG
583を訂正

template< A, B, C > struct
{
 template< A > struct
 { //↑ここを特殊化するんですね
 }
}
0586584(´д`;NGNG
584を訂正
ポインタが・・・>>583じゃ無くて>>582だ。
・・・鬱だ・・・氏んでくる
0587VC6に乗せたいNGNG
>>583殿。>>582で示したガイドラインに沿ってTypeAtNonStrictを書いてみました。

あのように作り方を明記すると、考えが整理できるものですね。
>>576で載せたテンプレートも、ガイドラインに沿った命名に書き換えました。

template <class TList, unsigned int index,
typename DefaultType = NullType>
struct TypeAtNonStrict
{
  template <class tmpTList>
  struct tmp2TypeAt
  {
    template <unsigned int cnt>
    struct tmp1TypeAt
    {
      typedef TypeAtNonStrict<tmpTList::Tail, cnt-1, DefaultType>::Result Result;
    };
    template <> struct tmp1TypeAt<0>
    {
      typedef tmpTList::Head Result;
    };
    typedef tmp1TypeAt<index>::Result Result;
  };
  template <> struct tmp2TypeAt<DefaultType>
  {
    typedef DefaultType Result;
  };
typedef tmp2TypeAt<TList>::Result Result;
};

このコードで、コンパイル、テスト動作ができることは確認しております。
願わくば、この勢いで TypeList.h で定義されている
テンプレート群をVC6仕様に書き換える作業にご協力願いたい。
正直、一人ではきついので。
■ このスレッドは過去ログ倉庫に格納されています