Generic Programming with C++ Template
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNG参考図書:
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/
0577デフォルトの名無しさん
NGNGなんだかわからんけど、よくやった!
次もこの調子でたのむ。
0578デフォルトの名無しさん
NGNG0579デフォルトの名無しさん
NGNGよくやった!
ただ、
不明な型が厳密にひとつしかないクラステンプレートなら
部分的な特殊化を使わずに実装できるんだが
TypeListにはそうでない機能がいくつかあるんだよね。
0580デフォルトの名無しさん
NGNGって言ってもtemplateなstatic変数が作れないだけですから、
マクロ作って個々にインスタンスを作ってやっただけですけど。
で、ためしにLoki::SingletonWithLongevity使ってみたら
GetLongevityの戻り値が大きいほうから先に削除されちゃうんです。
ここでまたぶち切れですよ。
ModernにはGetLongevityの戻り値が小さいほうから削除されるように書かれているのに。
これはどう解釈したら言いのでしょう。
0581デフォルトの名無しさん
NGNGVC++でSelectをなんとか出来ませんか?
0582VC6に乗せたい
NGNGそれはさておき。
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おぉぉ!
template< A, B, C >
の
Aだけ特殊化は出来ないから
template< A > class{ template< B, C > }
にしてAを特殊化するんですね!
Select行ってみます!
0585583
NGNGtemplate< A, B, C > struct
{
template< A > struct
{ //↑ここを特殊化するんですね
}
}
0587VC6に乗せたい
NGNGあのように作り方を明記すると、考えが整理できるものですね。
>>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仕様に書き換える作業にご協力願いたい。
正直、一人ではきついので。
0588デフォルトの名無しさん
NGNGで、今どこまで出来てるの?
協力しようにも何が出来てて何がまだなのか分からんと。
ただ、漏れ VC++ 持ってねぇんだよなぁ・・・
0589デフォルトの名無しさん
NGNG>>587の
下から6行目
> template <> struct tmp2TypeAt<DefaultType>
↓
> template <> struct tmp2TypeAt<NullType>
だと思います。
0590VC6に乗せたい
NGNG本業もあるため、平日は遅々とした進度になるかと思われます。
できそうなところからどんどん発表していくつもりです。
あと、>>589の指摘ですが、原著の作者の実装をそのまま置き換えたため、
そのようになっております。元ソースと比較してみてください。
なお、先日から取り組んでいる Typlist 型関数は、
数値関数に置き換えれば、このようになります。
Result TypeAtNonStrict(class TList, int index,
class DefaultType = NullType)
{
if(TList != DefaultType)
{
if(index != 0)
{
return TypeAtNonStrict(TList.Tail, index-1, DefaultType);
}
else
{
return TList.Head;
}
}
else
{
return DefaultType;
}
};
元ソースよりもいくらか手続きっぽくなってるのかも。
0591デフォルトの名無しさん
NGNG0592VC6に乗せたい
NGNGResult TypeAtNonStrict(class TList, int index,
class DefaultType = NullType)
{
if(TList != DefaultType)
{
if(index != 0)
{
return TypeAtNonStrict(TList.Tail, index-1, DefaultType);
}
else
{
return TList.Head;
}
}
else
{
return DefaultType;
}
};
0593583
NGNG今MostDerived終わりました。後でどっかでマージしませう
あとtmpじゃ分かりにくいので名前付け方法を決めたほうがいいと思います。
私は
template <class TList, unsigned int index,
typename DefaultType = NullType> struct TypeAtNonStrict
{
template <class tmpTList> struct SelectTList
{
template <unsigned int cnt> struct SelectIndex
{
hogehoge...
};
};
typedef SelectTList<TList>::SelectIndex<index>::Result Result;
};
のようにしました
0594デフォルトの名無しさん
NGNG0595583
NGNGつーか使っててすげーです、Lokiマンセー!!!
0596デフォルトの名無しさん
NGNG素晴らしい。
第二版に日本人の名を連ねられるか??
期待して待つ!
0597デフォルトの名無しさん
NGNG漏れ私的に使いたかったTypeTraitsの移植に挑戦してみようかな・・・
0599583
NGNG0600583
NGNGもしかしてtypelist.h終わったじゃん。
どっかにウプしよーぜ!
0601デフォルトの名無しさん
NGNG0602デフォルトの名無しさん
NGNGsourceforge.netだ
0603583
NGNG使い方分からん・・・(´д`;
編集済みtypelist.hとtypemanip.h、
VC++用に改造したsingleton.hが入ってます。
http://www68.dns.ne.jp/~bbs2/upload3/helen/OB00011454.zip
VC++.NETで作ったので、VC++6.0で動かなかったらゴメソ
なにぶん以前は動いてなかったので、typelist.hとtypemanip.hが元と同じように動作するかは確認できてません。
特にtypemanip.hのConversionが、exists2Wayが元と違う方法を使ってるので、その辺でばぐるかも。
編集後のSingletonHolderは残念ながら元と全く同じように使うことは出来ません、
これを使うときは、
プロジェクト内のCPPファイル内でImplementLokiSingletonマクロを使って
SingletonHolderのstaticメンバ変数の実体を作ってちょ
とにかく576は間違いなく神だな・・・
神の啓示を受けた気分だ。
0604583(゚ Д ゚ ;)・・・・
NGNGhttp://www.geocities.com/rani_sharoni/LokiPort.html
0605VC6に乗せたい
NGNG>>603は早速ダウンロードして、すべてチェックしました。
今のところ、VC6でも正常に動作しているようです。
typename とはこういうものだったのですか。
これを知らずにAppendの実装がうまくいかず、一時中断していたのですが。
知らぬではどうにもならぬですね。まだまだ修行が足りないです。
勉強になります。
0606583
NGNG0607583
NGNGやっぱりやってることはほとんど同じか・・・(鬱
(汚いと見えた)MakeTypeListやis_TypelistはLokiのバージョンアップで追加されたものかな?
0608VC6に乗せたい
NGNG結局、VC6にはtypename 指定をしないと、
template<typename Head, typename Tail>
Typelist<Head, Tail>
と
NullType の区別がつかないようなのです。
VC.NET用はともかく、VC6用は、ここで新規開発しないといけないかも。
0609597
NGNGダメですた。
ポインタの特殊化がどーーーしてもできまへん。
と思ったら>>604 で見事に実装されてますた。
悔しいやら嬉しいやら。
ともかく念願のTypeTraitsが手に入りますた。
ありがとうございます。
0610597
NGNGなぜか前から関数テンプレートのポインタ等の特殊化を
サポートしてるんだよな・・。
その調子でクラステンプレートも実装してホスィ
0612デフォルトの名無しさん
NGNGこれがあるとがぜん使う気が起きるね!
0613VC6に乗せたい
NGNG>>609 LokiPort の MakeTypeList は単体で動作するようです。
>>583氏のヘッダに移植できました。
あと、うっかりサンプルソースでReverseを呼び出すのを忘れていたのですが、
こいつがエラーが出てコンパイラにとおりません。(VC6)
ガイドライン通りにちゃんと書かれているようなのですが。原因はまだ不明です。
0614デフォルトの名無しさん
NGNG>>613はその発想力を大切にするといい。
0615デフォルトの名無しさん
NGNG出てきたのが今年の3月だから、タッチの差は僅かだ。
MakeTypeList も上のほうで無理言われてたけどあっさり実装されちゃってる
まるで魔法だ。
C++って奥深すぎる。鬱だ。
0616デフォルトの名無しさん
NGNG1翻訳単位のコンパイルにジャスト3分(あんまり長いので測った
まだ(やってることは)小さなプログラムなのにビルド後のファイルサイズは1MB突破・・・
テンプレート依存は一箇所に局所化して他の翻訳単位は高速化したけどそれでもつらいっす・・・
0617デフォルトの名無しさん
NGNG0618616
NGNG0619デフォルトの名無しさん
NGNGひょっとしてポインタ型各種について展開してないか?
0620デフォルトの名無しさん
NGNG0621616
NGNG画像の描画処理を転送・フィルター・形状・スケーリングの4つのポリシーに分けらああなりますた。
特に2つの転送ポリシーを合成するポリシーを作ったらコードサイズも時間も爆発。(まぁ当然か
0622デフォルトの名無しさん
NGNGピクセルの特性をポリシーとするなら分かるが。
0624デフォルトの名無しさん
NGNG某otakuのGTLの発展したような物ですね、
かっこよさそうです。
0625デフォルトの名無しさん
NGNG0626613
NGNGテンプレートによって生成されるコード量を大幅に
減らすアイデアが載っていましたが、いかがか?
>>604からスレの流れが変わったので、コテハンやめるっす。
0627デフォルトの名無しさん
NGNGEffectiveもってないっす、詳細きぼん
0628デフォルトの名無しさん
NGNG0629デフォルトの名無しさん
NGNGageたよ
http://pc.2ch.net/test/read.cgi/tech/1004287394/
0630デフォルトの名無しさん
NGNGhttp://pc.2ch.net/test/read.cgi/tech/1021787032/556
に書いてしまった…。サンクスコ>>629
0631613
NGNGModern C++ Designは Effective C++に書いてあることが前提になっているので、
先に読んでおいたほうがいいですぞ。買っても後悔しないです。
要は、コンテナに入れるものをvoid*として格納するコンテナを用意しておき、
要素に対する操作を定義しておきます。(ソートだとか何とか)
で、void*として放り込む作成・破壊クラスを別に定義します。
確かこんな感じだったはず。詳細は当該書籍を読まれよ。
0632デフォルトの名無しさん
NGNGメンバー関数の有無によってコードを書き分けるにはどうしたら良いのでしょうか。
例えば、次のようなテンプレートクラスがあるとします。
template <class A>
class X {
void func() {
if (/* A::foo() があるかどうかの判定*/) }
/*CODE1: A::foo()を使う処理 */
} else {
/*CODE2: A::foo()を使わない処理、もしくはA::foo()の処理を肩代りする処理*/
}
}
};
ここでクラスA1にはメンバー関数foo()があり、
クラスA2にはメンバー関数foo()がないとします。
このとき、X<A1>::func()とX<A2>::func()は
それぞれCODE1とCODE2の部分だけ実行するようにしたいのです。
できれば、判定をコンパイル時に行ない、コンパイルされたオブジェクト
にはコードが最適化されてCODE1とCODE2のどちらかしかしか
存在しないようにしたいと思っています。
こういうことは可能でしょうか?
可能だとするとどのようにしたら良いでしょうか?
0633デフォルトの名無しさん
NGNGタグディスパッチ
0634632
NGNGさっそくどうもありがとうございました。
Googleで検索してみたら、次のURLがヒットしました。
http://www.issei.org/programming/boost/more/generic_programming.htm
ここで言われているのがそれですか?
なかなか凝ったやり方に感じましたが、勉強になりました。
0635デフォルトの名無しさん
NGNGC++にはリフレクション機能が無いので
特定メンバあるかどうかの判断はできない。(・・よね?)
だから他の条件が必要。
渡されるクラス全てにタグを定義とかの制限をつけてもよいならタグディスパッチ
だめならlokiのTypeTraitsで使えそうな特性をみつけるとか。
私的には特定のクラスのサブクラスかどうかで分けるのが良いと思うが。
0636626
NGNG>>583氏のヘッダに適宜 LokiPortのコードを移植することで、
LokiPortのTest_Typelist.cpp がコンパイルできてしまいました。
ということは、Typelistに関してはVC6でも動作可能ということですよね。
ううむ。
0637デフォルトの名無しさん
NGNG0638デフォルトの名無しさん
NGNGVC6ってテンプレートパラーメータサポートしてなかったと思うけど
どうやってるの?
0639デフォルトの名無しさん
NGNGん? できないのは部分特殊化でしょ?
テンプレートパラメータサポートしてないってどういうこと?
文字通り取るとtemplate自体使えないような。
0640デフォルトの名無しさん
NGNGテンプレートテンプレートパラメータのことでしょ。わざわざ揚げ足取らんでも。
template< class A, template<class> B > class C { ... };
ってゆーかしかし、LokiのTypeListって部分特殊化さえあれば動くと思ったが。
0641デフォルトの名無しさん
NGNGどういうときに使うの?
0643デフォルトの名無しさん
NGNG参照型が問答無用でconstと判断されてしまう。
まぁあんまり使い道の無い機能ではあるが
ザンネン。
0644デフォルトの名無しさん
NGNG参照そのものは変更できないからconstという判断でいいのかな。
そういうことにしよう!
0645デフォルトの名無しさん
NGNGisPointerの実装おかしいような??
これconstの判別できないだろ?
0646デフォルトの名無しさん
NGNG仮にVC++の話であるなら
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf14552partialorderingoffunctiontemplates.asp
なのでそこんとこ注意。
0647デフォルトの名無しさん
NGNGそうなんだよね・・
それなのになんで動くのかちと不思議。
保障されない動作なんだろうか。
とりあえずisPointerはポイント先の修飾された奴を全部消して
コンストポインタの判定を追加したらうまく動いた。
0648デフォルトの名無しさん
NGNGstatic yes is_pointer1(Type2Type<U *>);
static no is_pointer1(...);
template<typename U>
static yes is_pointer2(Type2Type<U * const>);
static no is_pointer2(...);
enum {
isPointer =
sizeof(is_pointer1(Type2Type<T>())) == sizeof(yes) ||
sizeof(is_pointer2(Type2Type<T>())) == sizeof(yes) ||
};
これで動いた。
これって単に動作確認してなかったのかな。
それともSPあてる・あてないで動作変わったのかな・・
0649デフォルトの名無しさん
NGNG激しく遅レスだが
VC++には__if_exists/__if_not_existsなるキーワードがあって
関数や変数の有無で処理を分けられる
移植性を考えれば使えないが
0650デフォルトの名無しさん
NGNGそれどうやって使うの?
解説キボンヌ
0651デフォルトの名無しさん
NGNGそれって.NET専用?
0652デフォルトの名無しさん
NGNG#include <iostream>
int main(void)
{
int a;
__if_exists( a ){ std::cout << "a ハケーン" << std::endl; }
__if_not_exists( a ){ std::cout << "そんな変数無いです" << std::endl; }
}
こんな感じ
このままだと "a ハケーン" が表示される
int a;をコメントアウトすると "そんな変数無いです" が表示される
( ) 括弧の中は変数だけじゃなくて、任意のシンボルが入れられる。
もちろんメンバ関数も。
0653デフォルトの名無しさん
NGNGネイティブにも使えるけど、もしかしたらVC++.NETから新しく追加された機能かも
0654デフォルトの名無しさん
NGNG0655名無しさん
NGNGメンバー、メソッドでもOKなの?
0656デフォルトの名無しさん
NGNG0657デフォルトの名無しさん
NGNG(識別子をどうするかは、考えないといけないが)
0658デフォルトの名無しさん
NGNGコンパイラによるリフレクション? 規格はさすがに無理ぽそうだけど...
0659名無しさん
NGNGウヒャ─、これは便利、って例ある?
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrfthe__if_existsstatement.asp
memberもOKなのね。しかし、なんじゃこりゃ? って感じ。
0660デフォルトの名無しさん
NGNGタグディスパッチがいらなくなるんじゃない
0661名無しさん
NGNGinline void advance(_Iterator& __i, _Distance __n) {
__if_exists( _Iterator::operator[]){ __i += __n; } // random
__if_exists( _Iterator::operator--){ if (__n >= 0) while (__n--) ++__i; else while (__n++) --__i; } // bi
// elseがないからtag抜きでforward iterator書きにくい。
}
こんな感じ?
0662デフォルトの名無しさん
NGNG0663デフォルトの名無しさん
NGNGコンパイラがコンパイルの前に置換をしてくれるんだよ。
プリプロセッサがやる単純な置換と違い、コンパイラが型チェックに
責任を持ってくれる。
0664デフォルトの名無しさん
NGNGTemplateはどういうときに使うのですか?
0665デフォルトの名無しさん
NGNGリストって知ってるよね?単方向でも双方向でも。
例えば、構造体Aと言う値を保持するリストのクラスを作ったとする。
これがなかなか便利で他のプログラムにも使いたい。
しかし、構造体Aは前のプログラム独自の物なので汎用性を持たせたい。
そこで、構造体Aの代わりにvoid *を持たせることにした。
しかし、これでは型キャストの嵐になるし、新しいノードを作るとき、自動的にデータ格納用の
メモリ領域を確保したり開放したりすることが困難になる。
next = new nextnode();
next.data = new ここを使う型が変わるたびに変更しなくてはならない。
そこでテンプレート。これは特定の抽象型を具体的な型に置換できる。
例えば、データ用の型をDATAとし、それをintと具体化すれば、
int型を扱うリストが出来るし、struct aaaと具体化すればaaa構造体のリストとなる。
0666デフォルトの名無しさん
NGNG0667デフォルトの名無しさん
NGNG抽象化する時
(メソッドとか関数とか)
0668613
NGNG激しくスレ違いに真面目にレス。2ちゃんねらーの鑑です。
私も見習わないと。
ということで真面目レスを追加しておきますと、
テンプレート(template)の萌芽はMFCのコンテナにも見られます。
(CMap、CListなど)
でもやはり、STLは一通り勉強しましょう。
ttp://www.wakhok.ac.jp/~sumi/stl/index.html
それから、Effective C++、More Effective C++を一通り読んで、
>>1 のModern C++ Design を買えば、
晴れてこのスレの住人に仲間入りです。
頑張りなされ。
0669デフォルトの名無しさん
NGNGいくらかかると思ってんのYO(`Д´)
0670デフォルトの名無しさん
NGNG全部持ってるYO!高かったけど仕方ないYO!
0671デフォルトの名無しさん
NGNG書籍にかけた金は、すぐに仕事実績で取り返せる(ちゃんと読めば)。惜しむな。
0672デフォルトの名無しさん
NGNGそう思いこみたいんですね :)
0673デフォルトの名無しさん
NGNG怖がりすぎー。
0674デフォルトの名無しさん
NGNG初期化するのはめんどくせー」ってことで、
WithInit< int , 600 > m_intvalue;
ちゅーよーなのを書いた。
ひょっとして、車輪を再発名した……?
勝手に600に初期化されるint ってこと?
0676age
NGNG"error C2516: 'Inner' : は正しい基本クラスではありません。"
を吐きます。
InnerInFunc は問題なく通ります。
これはC++の仕様?それともVC++の問題?
InnerInStruct も使えるように出来ないのでしょうか?
struct Base{ struct Inner{};};
template< typename T > struct Mid: public T{};
template< typename T > struct Sub
{
struct InnerInStruct: public Mid< T >::Inner{};
Sub()
{
struct InnerInFunc: public Mid< T >::Inner{};
}
};
int main(void)
{
Sub< Base > sub;
}
■ このスレッドは過去ログ倉庫に格納されています