【C++】template 統合スレ -- STL/Boost/Loki, etc.
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNG以下のスレッドを統合するスレです。
STLスレッド
Part1 http://pc.2ch.net/tech/kako/1004/10042/1004287394.html
Part2 http://pc3.2ch.net/test/read.cgi/tech/1026793823/
【C++】Boost使い集まれ!
http://pc3.2ch.net/test/read.cgi/tech/1033830935/
Generic Programming with C++ Template
http://pc.2ch.net/tech/kako/1008/10085/1008593126.html
関連スレ、その他リンクは >>2-5 あたりに。
0101デフォルトの名無しさん
NGNGhttp://www.codeproject.com/interview/stanlippman14nov2001.asp
> Microsoft’s goal is to have a ‘competitively compliant’ compiler -
> meaning it won’t be 100% compliant. There are a couple of features
> of the ANSI/ISO standard (for instance the ‘export’ keyword as
> applied to template classes) that won’t be implemented because
> they are considered by Microsoft to be obscure and, at this stage,
> theoretical.
とか。ただ、exportなんでEDGのですらサポートされてない
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpdndeepc/htm/deep04202000.asp
とか言えた時代と違って、すでにexportが使えるコンパイラが
登場してきてるからには、認識も変化しているかもしれないけど。
>>100
C#のGenericsはどうなるのか知らんけどJavaのGenericsは例えば、
「内部では全てObjectへの参照を保持するようなコンテナをオブジェクトコードとして
生成しておいて、それを利用するソース側のコンパイル時に型チェック/自動型変換を
かける」 みたいな方法で実装してるだけだから参考にならん、という面はあると思うが。
C++にも「Object型があって、変数は全てポインタ」みたいな
制限があればtemplateのexportは相当楽になるわけで。
0102デフォルトの名無しさん
NGNG「mapの要素の挿入と削除には対数時間(logN)が必要ですが、
位置を指定して要素を挿入する場合は償却定数時間(ε)しかかりません。」
と本にあったのですが、いまいちよく分かりません。
(1)削除
void erase(iterator i); -> logN ?
void erase(iterator start,iterator end); -> length*logN ?
size_type erase(const key_type &k); -> logN ?
(2)挿入
iterator insert(iterator i,const value_type &val);-> ε ?
template<class InIter>
void insert(InIter start,InIter end ); -> length*logN ?
pair<iterator,bool> insert(const value_type &val);-> logN ?
であってますでしょうか?
0103デフォルトの名無しさん
NGNG位置指定が正しい場合にのみ、定数時間で挿入ができるらしい。
ttp://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html
で、「正しい位置」は lower_bound で取れる。
0104102
NGNGvoid erase(iterator i); -> ε に修正します。
>>103
[挿入|削除]する[位置|反復子]が分かっているときは定数時間だが、
その位置を探すのにlower_bound ->logN 時間かかるということですかね。
ありがとうございました。
0105デフォルトの名無しさん
NGNGコンパイラがどの型にも固有の値を割り振っていて、
それをコンパイル時に参照できたら
式templateとマクロでtype_of作れるんだけど、
静的使えるのがsizeofしかないぽいから無理くさいのかな。
//ないんでとりあえず実験
#define class_id(x) sizeof(x)
template <int> struct Type_of;
struct Type_of<class_id(int)>{typedef int type;};
struct Type_of<class_id(char)>{typedef int type;};
#define type_of(x) Type_of<class_id(a)>::type
#include<iostream>
int main()
{
int a;
char c;
type_of(a) a2=200;
type_of(c) c2=100;
std::cout << a2 << c2;
}
0106105
NGNG× struct Type_of<class_id(char)>{typedef int type;};
○ struct Type_of<class_id(char)>{typedef char type;};
0107>>105
NGNG-----------------------------------------------
typedef char (&no_tag)[1], (&yes_tag)[2];
template<int> struct id_counter;
template<typename> struct t2t;
template<typename T> no_tag test(T*, ...);
#define EMPTY(n) sizeof(test((t2t< id_counter<n> >*)0))==sizeof(no_tag)
template<int val_ =
(EMPTY(1) ? 1 :
(EMPTY(2) ? 2 :
(EMPTY(3) ? 3 :
(EMPTY(4) ? 4 :
(EMPTY(5) ? 5 :
(EMPTY(6) ? 6 :
(EMPTY(7) ? 7 :
(EMPTY(8) ? 8 :
(EMPTY(9) ? 9 :
-1)))))))))> struct id_counter {
enum { val = val_ };
friend yes_tag test( t2t< id_counter<val> >* );
};
template<typename T> struct id_of { enum { val = id_counter<>::val }; };
#define class_id(T) id_of< T >::val
0108107
NGNGint main()
{
std::cout << class_id(int) << ' '
<< class_id(int) << ' '
<< class_id(char) << ' '
<< class_id(int) << ' '
<< class_id(long) << ' '
<< class_id(std::istream) << std::endl;
}
が
1 1 2 1 3 4
になる。とゆーか、分割コンパイルまで考えると、コンパイラ的にはtypeofよりも
staticなTypeIdの方がよっぽど面倒な気がするので、素直にc++0xを待つべきかと。
0109107
NGNGtemplate<typename T> struct sized { char size[id_of<T>::val]; };
template<typename T> sized<T> obj_class_id_helper(const T&);
#define obj_class_id(x) sizeof(obj_class_id_helper(x).size)
//int a; float b;
//assert( obj_class_id(a+b) == class_id(float) );
0110105
NGNGすごすぎる!!!
id_counterってほんとにその名の通りですね。
少し手を加えて
type_ofとtestプログラム作ってみたけど、
こういうものはウプしてもいいのかな?(どういう場所がいいのか)
どうにか手を入れれば、GCCでも動かせそうな気がするんだけど、
自分では無理そうでした。
0111デフォルトの名無しさん
NGNG逆に、IDから元の型を取得することはできないの?
float f = 1f;
int i = (class_id(int))f;
キャストに使えたりするとうれしい。
0112デフォルトの名無しさん
NGNG知らなかった。
http://www.puni.net/~mimori/rfc/rfc3092.txt
0113デフォルトの名無しさん
NGNG0114デフォルトの名無しさん
NGNGしっ!!
0115デフォルトの名無しさん
NGNGRFC勉強になりすぎ。
0116107
NGNGhttp://lists.boost.org/MailArchives/boost/msg37791.php
ね。
>>111
それが出来ると typeof の完成なんだけど、思いつかないっす。
105氏のType_ofみたいに、必要なクラスのid - typeのマッピングを
全部手で書いていくくらいしか。何か上手い手はないかな。
0117105
NGNGにとりあえず上げてみました。
中を見ると分かるけど
>>111
int i = (type_of_id( class_id(int) ))f;
でできます。でもType_ofで登録した物にしか使えません。
>>107
ちょこっと追加として
int addfunc(int,int);
type_of_declare(addfunc(int,int),aa);
std::cout << aa;
とかできるようにした。(定義場所わかりにく...
>>107(116)
入れ子の式テンプレートでできないかと思ったけど撃沈...。(以下、略
template <typename T> struct Type_of_collection
{
template <int N> struct Type_of_Num;
struct Type_of_Num<class_id(T)> { typedef T type;};
};
0118デフォルトの名無しさん
NGNGttp://www.xlsoft.com/jp/products/vtune/icppwin.html
0119デフォルトの名無しさん
NGNG#include <list>
using namespace std;
void main(){
list<list<int>> a:
}
というのでエラーがでます。
listのlistを作るにはどのようにしたらいいのでしょうか?
0120デフォルトの名無しさん
NGNG0121デフォルトの名無しさん
NGNG>list<list<int>> a:
色々違ってるな。
0122デフォルトの名無しさん
NGNGありがとうございました。
直りました。
0123デフォルトの名無しさん
NGNGただなの?
0124デフォルトの名無しさん
NGNG0125デフォルトの名無しさん
NGNGconst int N = 2000000;
int cmp(const void *, const void *);
int main()
{
static double d[N];
std::vector<double> vd;
std::clock_t ti;
std::srand(0);
for (int i = 0; i < N; i++) d[i] = std::rand();
std::srand(0);
for (int i = 0; i < N; i++) vd.push_back(std::rand());
ti = std::clock();
std::qsort(d, N, sizeof(double), cmp);
std::cout << "qsort = " << std::clock() - ti << std::endl;
ti = std::clock();
std::sort(vd.begin(), vd.end());
std::cout << "sort = " << std::clock() - ti << std::endl;
}
0126デフォルトの名無しさん
NGNG{
if (*static_cast<const double*>(a) < *static_cast<const double*>(b)) return -1;
else if (*static_cast<const double*>(a) > *static_cast<const double*>(b)) return 1;
return 0;
}
qsort = 906
sort = 734
0127デフォルトの名無しさん
NGNGqsort = 702
sort = 328
差が開く。
0128デフォルトの名無しさん
NGNGint cmp(const void* a, const void* b)
{
return *static_cast<const TYPE*>(a) - *static_cast<const TYPE*>(b);
}
に換えたらちょっと速くできるけどまだsort()の方が速い。よくできてるなあ。
qsort = 562
sort = 344
0129デフォルトの名無しさん
NGNG0130デフォルトの名無しさん
NGNGSTL は VC6 付属のもの。
コンパイラ付属のソースをインライン展開しまくった my_qsort でもやってみたよ。
double:
my_qsort = 4340
qsort = 4720
sort = 1760
int:
my_qsort = 1540
qsort = 3240
sort = 830
int (quick cmp):
my_qsort = 1430
qsort = 2520
sort = 830
どうも、インライン展開うんぬんより、アルゴリズムが根本的に違ってるように見える。
STL のソートって何ソートなの?
0131
NGNGしまって最適化されない qsort は正直かなりのオーバーヘッドがあると思う。
0132デフォルトの名無しさん
NGNGqsort の方はよく知らんが、STL の方は、
基本はクイックソート
pivot には先頭・ど真ん中・末尾の要素の中央値を使う
要素数が小さくなってきたら挿入ソートに切り替える
あと、最新版では再起が深くなってきたらマージソートに切り替えるって機能も付いてたと思われ。
0133デフォルトの名無しさん
NGNG参考書を読むと、標準にはないbinary_composeと組み合わせて使うと
書いてあるのですけど、どういう意味なのでしょうか?
0134デフォルトの名無しさん
NGNG130 の 3 行目は読んでくれたか?
> int (quick cmp):
> my_qsort = 1430
> sort = 830
その関数呼び出しのオーバーヘッドが無い状態で、これだけ差があるの。
>>132
VC6 付属の qsort.c については、
> pivot には先頭・ど真ん中・末尾の要素の中央値を使う
> 要素数が小さくなってきたら挿入ソートに切り替える
これと同じっぽい
要素数 8 以下で挿入ソートに入る。
ただし、マージソートはやってなくて、再帰は使わずに goto で戻してる。
ネックになりそうなのは、STL の場合のように代入演算子が使えないので、
char 単位にデータ転送しているところかな。
でも、それを無理矢理 int 決め打ちの swap にしても、まだ sort() のが
速い。
> my_qsort = 1100
後は何だ?
0135デフォルトの名無しさん
NGNGbinary_composeにはSGIのSTLやSTLportで定義されている。std::compose2
というヘルパ関数を持つ。
例えば _1 < 1 || 3 <= _1 という関数オブジェクトを作るには
std::compose2(std::logical_or<bool>(), std::bind2nd(std::less<int>, 1), std::bind2nd(std::greater_equal<int>, 3))
とすればよい。
boostではネーミングが異なり、boost::compose_f_gx_hyとなっている。
0136デフォルトの名無しさん
NGNG> char 単位にデータ転送しているところかな。
double が異様に遅いのはこのせいだな。
インライン展開しまくり、かつ代入演算子に変えたら、sort() に肉薄した。
my_qsort = 1965
qsort = 4715
sort = 1753
でもやっぱり sort() のが遅いけど。
あと、↓でより正確に測れる。
#pragma comment(lib , "winmm.lib")
#define clock_t DWORD
#define clock() timeGetTime()
0137デフォルトの名無しさん
NGNGsort() のが速いけど。ですた。
0138デフォルトの名無しさん
NGNGスマソ。boost::compose_f_gx_hxとなっている。に訂正します。
0139デフォルトの名無しさん
NGNGそうだったのか。あらゆる型に汎用にするために、charでアラインされた
転送単位を持つためにqsort()は遅いのか。
ということはcharでsortするとそんなに差は出ないはずだな。
・・・・やってみた。
qsort = 265
sort = 282
測定誤差により、逆転する事もあるが、大ざっぱに測定するとqsort()の
方が速くなった。納得。
0140デフォルトの名無しさん
NGNGなし崩しにboostを認めようという作戦ですか?
私は認めませんよ!>boost
0141boost
NGNGごめんなさい
0142デフォルトの名無しさん
NGNG0143デフォルトの名無しさん
NGNG0144小技
NGNGU hoge( T foo, U* = NULL )
{
...
}
// 使い方
hoge<string, int>( "第二引数はダミー" );
0145デフォルトの名無しさん
NGNGこれのどこが技なのか・・・・・
0146デフォルトの名無しさん
NGNG0147107
NGNG> ttp://www3.to/typeof
素晴すぃ。
結局friendで勝手に定義を挿入するしかなさそう、と思ってその方向で
弄ってたんだけど、id_counter と違ってsizeof以上の情報を
オーバーロードされた関数からとってこなきゃいけないのがうまく行かなくて撃沈続き…。
0148デフォルトの名無しさん
NGNGVC6対策か?
0149デフォルトの名無しさん
NGNGわからんのか?ヒントは返り血
0150デフォルトの名無しさん
NGNGU hoge(T foo, U* up = 0)
{
return *up;
}
int main()
{
hoge<std::string, int>( "第二引数はダミー" );
}
としてみてもなあ。。。。intが無駄に使われているような気がして
ならない。
0151デフォルトの名無しさん
NGNGじゃなくて、ふつーに書くと返り値の型が異なるだけの関数は多重定義できん
という話でしょ。
template じゃなくても良いんだが
int foo();
void foo();
これは NG だが、
int foo(int);
void foo();
これなら行ける。
> intが無駄に使われているような気がして
とりあえず最適化有効にしてアセンブラ出力させてみ。
0152デフォルトの名無しさん
NGNG0153デフォルトの名無しさん
NGNG今いち存在意義がわからんが・・・・・・
0154デフォルトの名無しさん
NGNGint GetValue("キー")
string GetValue("キー")
みたいなことができるってことかい?
0155154
NGNG具体的な使用例をあげてみてくれないかい?
0156デフォルトの名無しさん
NGNGtemplateの特殊化したいときとか使えるけど?
>>155
>>151に書いてあんだろ?アホか?
0157デフォルトの名無しさん
NGNG155 はそんなことをする理由を訊きたがっているんだぞ。
無理やり使いどころを考えると、template クラスで Factory 関数を使うときか?
0158154
NGNGそういうことです
(だから>>154でわざわざ”GetValue"という関数名を使ったのですが伝わらなかったようで・・・)
>無理やり使いどころを考えると、template クラスで Factory 関数を使うときか?
うーん。確かに無理やりですね。
Widget MakeWidget() ※Widgetは基底クラス
ってするもんじゃないでしょうか。
同じ関数名で返り値が違うってのがそもそも想像できないんですが・・・。
0159154
NGNG利用法が無いなら無いでいいんです。
「こういうこともできるよ」って例なのだとしたら。
でも実際に使いどころがあるんでしたら聞いてみたいのです。
0160デフォルトの名無しさん
NGNGそれなら
template<class U, class T>
U hoge( T foo )
{
...
}
// 使い方
hoge<int>( "第二引数なんざ要らん" );
で十分では?古いヘタレコンパイラでどうなるかは知らんが。
0161デフォルトの名無しさん
NGNG> 同じ関数名で返り値が違うってのがそもそも想像できないんですが・・・。
template を使って Mixin (あるいは Strategy パターン) をを書くときに使える。
0162デフォルトの名無しさん
NGNGそれだと、明示的に型を指定する必要があるのが難だなぁ。
パラメタとして関数オブジェクト、関数ポインタ、ともかく () つければ処理して
くれるモノ何でも渡せるようにしておくと、コードの汎用性が上がる(場合がある)。
0163160
NGNG引数をtemplateにして型指定を緩くしとくと嬉しい、というのはその通りだけど、
この場合関係ないでしょ。(>>144のも同じく明示的な型指定が必要)
違うのは返値の型のみ、という関数を作りたいとき (例えばModern C++ Design の
Factoryパターンの話とか) の話でないの?
0164デフォルトの名無しさん
NGNGが通るコンパイラが有るなら教えてくれ。
0165デフォルトの名無しさん
NGNGないだろう。class を typename にすれば通るけど。
0166デフォルトの名無しさん
NGNG同じもの作らなくて済ませることができそうな気がする。
これって実行時に判定してるのかな?
Tって静的だけどデバッガで見るとswitch文の中は最適化されてないみたいなんです。
template <typename T> struct FFF
{
FFF(T a=0)
{
switch( class_id(T) )
{
case class_id(char):
std::cout << "char" << std::endl;break;
case class_id(short):
std::cout << "short" << std::endl;break;
default:
std::cout << "other" << std::endl;
}
}
};
template <> struct FFF<int>
{
FFF(int a=0)
{
std::cout << "int" << std::endl;
}
};
0167続き
NGNG{
//出力結果
FFF<int> fff1; //int
FFF<char> fff2; //char
FFF<short> fff3; //short
}
0168デフォルトの名無しさん
NGNGVC++.NET と Bcc5.51 と DigitalMarsC++8.31 と
g++3.2 と g++2.95 と Comeau C++4.31 と Intel C++6.0 では通ったが?
通らないコンパイラを教えてくれ。
0169デフォルトの名無しさん
NGNG0170続き
NGNGclass_id(short) ->3 (enum定数)
直接は飛んでないけど、結局同じなんで問題ないか。
(↓最適化なしのものVC)最適化すると変わるんだろうか...。
; 168 : FFF<char> fff2;
mov DWORD PTR -416+[ebp], 1
cmp DWORD PTR -416+[ebp], 1
je SHORT $L23144
cmp DWORD PTR -416+[ebp], 3
je SHORT $L23145
jmp SHORT $L23146
0171デフォルトの名無しさん
NGNGたとえば >>53
0172デフォルトの名無しさん
NGNGひどいことを言うなよ。お前だってアホだったろうが
0173デフォルトの名無しさん
NGNGひどいことを言うなよ。
0174デフォルトの名無しさん
NGNG確か>>164の脳内コンパイルだと通りません。
0175デフォルトの名無しさん
NGNG0176デフォルトの名無しさん
NGNG0178デフォルトの名無しさん
NGNGやめい、って交換しなきゃ第二引数が省略できんだろ。
0179デフォルトの名無しさん
NGNGtemplate<class T, class U>
T hoge( U foo )
{
...
}
hoge<int>("できますが何か?");
0180160
NGNGああ、なるほど。混乱させてすまなんだ。
U を使うのって Undeducible か何かの略かと思ってたんで>>144と
同じに返値U、引数T、になるようにtemplateの方を変えたんだけど、
Tの次はUってことか。自分では2引数以上のtemplateを書くときは
T1、T2、 T3 ... なのでなぁ。
0181デフォルトの名無しさん
NGNGコロンブス的な発想にチトワラタ(w
0182デフォルトの名無しさん
NGNGtemplate<class T, class U>
を
template<typename T, typename U>
とは書かないの?
0183160
NGNG個人的には、
・タイプ数減らしたい時はclass。
・template template parameter は class と書くので、
何となく全部 class で統一したい気分の日は class。
・マジメに書くときはtypename。
0184デフォルトの名無しさん
NGNGテンプレート引数はclassのみ使用。
typenameは
typedef typename T::iterator iterator;
とがぐらいしか使わない。
0185デフォルトの名無しさん
NGNG漏れはtypenameに直した。
ってか,intとかにも対応するのにclassって気持ち悪いんだよな。C++のintはクラスじゃないし。
0187デフォルトの名無しさん
NGNGまだChapter 3までしか読んでないけど、なかなか良さげ
0188デフォルトの名無しさん
NGNGどこの出版社?(・∀・)イイ?
0189デフォルトの名無しさん
NGNGAddison-Wesley だが……出たばっかの洋書でふ
0191デフォルトの名無しさん
NGNGありが�d。俺も本屋行って見てくるよ。
0192デフォルトの名無しさん
NGNGAddison-Wesley キタ─wwヘ√レvv~(゚∀゚)─wwヘ√レvv~─ !!!!
Addison-Wesley、もう大好き♪
分かりやすいし、詳しいし…。
0193デフォルトの名無しさん
NGNG俺は int などのプリミティブ型も引数に取る場合には typename, クラスしか
引数に取らん場合には class にしてる。まー、趣味の問題だね。
0194デフォルトの名無しさん
NGNG0195デフォルトの名無しさん
NGNG日本訳が出るまで最低1年はかかるからなー。
0196デフォルトの名無しさん
NGNG0197デフォルトの名無しさん
NGNGまだ使ってるのか… 御愁傷様です。
0198デフォルトの名無しさん
NGNG全く同一だよ。だからみんなして趣味の問題とか個人的にはとか言ってるわけ。
>>195
出たばっかりの洋書はWebで買った方が良いと思う。
0199デフォルトの名無しさん
NGNGhttp://fara.cs.uni-potsdam.de/~kaufmann/?page=lokiport
■ このスレッドは過去ログ倉庫に格納されています