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/
0334デフォルトの名無しさん
NGNGテンプレート周辺にバグがあるんでしょ?がっかり。
しっかりしてくれよ、Borland。期待してるんだから。Pascal以外の言語もがんばってくれよ。
0335デフォルトの名無しさん
NGNGえっ?初耳。ソースはどこかにありますか?教えて下さい
0336デフォルトの名無しさん
NGNGstruct pr : public std::binary_function< string, string, bool>{
bool operator()(const string& x, const string& y)const{
return search(x.begin(), x.end(), y.begin(), y.end()) != x.end();
}
};
vector<string> articles;
・・・
articles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "ぢ")), articles.end());
articles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "ちう")), articles.end());
0337デフォルトの名無しさん
NGNGarticles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "FUKUDA Fumiki")), articles.end());
で。
0338デフォルトの名無しさん
NGNGえっ?猫耳。
0339デフォルトの名無しさん
NGNGえっ?愛猫。
0340デフォルトの名無しさん
NGNGつまんねーよきみら
0341デフォルトの名無しさん
NGNGすごい!!
0342デフォルトの名無しさん
NGNGtemplate<class T> void swap(T& x, T& y) {}
template<class T> void swap(vector<T>& x, vector<T>& y) {}
これコンパイル通らないんだよね・・
プログラミング言語C++ではこういう書き方してるのに。
0343デフォルトの名無しさん
NGNGusing namespace std; を外して、std::vector にしてごらん。
0344デフォルトの名無しさん
NGNG0345デフォルトの名無しさん
NGNG最近関数オブジェクトがおもしろくてしょうがないんだけど、
引数がいっぱいあるメンバ関数をもつクラス T があるとして、
std::vector<T> t(100);
std::for_each(t.begin(), t.end(), &T:func);
みたいなのを引数渡ししつつぐるぐるやる方法はないかな。
mem_funcだとうまく引数が渡せないので、引数をなんとかする
関数オブジェクトをいっこつくってぐるぐるするしかないと思うんだけど、
いざコードを書こうとするとかっこわるくていかんのです。
0346デフォルトの名無しさん
NGNGsage鬱
0347デフォルトの名無しさん
NGNGboost::bindとboost::mem_funとかで出来るんじゃないか?
0348デフォルトの名無しさん
NGNGたとえば引数が三つあるメンバ関数を考えたとき、
すべての引数に値を渡せるかな?
0349デフォルトの名無しさん
NGNG3つのうち2つが固定なら出来るんじゃないか?
0350デフォルトの名無しさん
NGNGふむ。ちと試してみるよ。
ありがとん
0351デフォルトの名無しさん
NGNGtemplate<T> void swap(T& x, T& y) {}
template<T> void swap(Class<T>& x, Class<T>& y) {}
2個のオーバーロード関数があいまいで最適な変換ができません。
STLソースではこうなってる模様
template<class T> Class {
public:
friend void swap(Class& x, Class& y) {}
};
でもこれでは既に他の名前空間にあるswapを特殊化できない罠。
なんかおかしくない?
おかしいのは漏れ?
0352デフォルトの名無しさん
NGNGたぶん、キミがおかしい。
VC7 のことはよくわからんけど、ふつう swap は <algorithm> の中で
次のように定義されているはず:
namespace std{
template<class T> inline void swap(T& x, T& y) { … }
}
で、何か標準ヘッダーをインクルードして、using namespace std;
してるでしょ? それで、1行目の swap とバッティングしてるんだと
思うけど。
ちなみに、2行目の swap は関係ない。それを外してもエラーが出るん
じゃない?
0353デフォルトの名無しさん
NGNGusing namespace std はやめよーよ。
0354デフォルトの名無しさん
NGNG例が悪かった・・
swapじゃなくてなんでもいいです。
とにかくテンプレート関数をクラステンプレートで特殊化しようとすると
特殊化優先順位で弾かれる。
名前空間とは関係ない問題です。(これが後々関係してくるが)
0355デフォルトの名無しさん
NGNGtemplate<class T> class Class {};
template<class T> void func(T& x, T& y) {}
template<class T> void func(Class<T>& x, Class<T>& y) {}
void main() {
Class<int> x, y;
func(x, y);
}
error C2667: 'func' : 2 個のオーバーロード関数があいまいで最適な変換ができません。
で、
template<class T> class Class {
public:
friend void func(Class& x, Class& y) {}
};
template<class T> void func(T& x, T& y) {}
これならOK。VC7のSTLもこのパターンで実装されてる。
でも例えばfuncとClassが違う名前空間にあると
このパターンは成り立たない。色々試したがダメだった。
具体的にはstd::swapなんかを
自作のテンプレートクラスで特殊化しようとした場合なんかに
困るわけなんだな、これが。
0356デフォルトの名無しさん
NGNGあんまり実りが無い感じ。
0357デフォルトの名無しさん
NGNG前半部分、13.5.1(p.404) によって後者が選ばれなきゃいけない話?
gcc 2.95ではちゃんと選ばれたよ。
0358デフォルトの名無しさん
NGNGC++の本を見る限りではそのgccの動作が正しいと思うんだけど。
VC7では選ばれる以前にコンパイルエラーになる。
多分、テンプレート関数とクラステンプレートで特殊化したテンプレート関数の
特殊化優先順位が等しいからこんなことになる。
これだったらすぐ直りそうなもんだからSPで直してほしい・・
0359デフォルトの名無しさん
NGNGC++のテンプレートの仕様を把握するのが一苦労って事なのかな?
0360デフォルトの名無しさん
NGNG違う名前空間の関数を特殊化するなという意味だろうか。
Javaみたく階層的に名前空間分けてたら
同一プロジェクトでも同じ問題が発生するが・・
共通関数を使わずメンバ関数を使えという話になるんだろうけど
それだとSTLのうまみも半減だわな
ところでクラステンプレートをクラステンプレートで特殊化って
C++的に可能なの?VCではダメだった。
0361デフォルトの名無しさん
NGNG0362デフォルトの名無しさん
NGNGBorland-C++ 5.6では正しくコンパイルできますた。
0363デフォルトの名無しさん
NGNG0364デフォルトの名無しさん
NGNG0365デフォルトの名無しさん
NGNGでDLしたらVC.NETじゃコンパイルできねージャン!!
氏ねMS!IDEばっか凝ってねーでコンパイラ改良しる!
0366デフォルトの名無しさん
NGNG ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄」
―――――――――――――‐┬┘
|
____.____ |
| | | |
| | ∧_∧ | | C++を窓から投げ捨てろ
| |( ´∀`)つ ミ |
| |/ ⊃ ノ | | C++
 ̄ ̄ ̄ ̄' ̄ ̄ ̄ ̄ |
--------------------------------------------
0367デフォルトの名無しさん
NGNGそもそもMSがcl.exeをANSIに完全対応させる気がないのだとしたら
どういう事態になるんだろう。
0368デフォルトの名無しさん
NGNG0369デフォルトの名無しさん
NGNGenum {HOGE,MOGE,MONA,SAGE};
void hoge(void);
void moge(void);
void mona(void);
void sage(void);
typedef void (*FUNC)(void);
FUNC func[] = {hoge,moge,mona,sage};
こんな感じで、HOGEのときはhogeを呼ぶ、みたいに対応させてます。
このとき、enumの順番を変えたら、それに応じてfunc内の関数順番を
手動で変えるのがわずらわしいのです(enumとfuncは別ファイルです。
includeして、見えるようにはなってますけど)。
enumの順番に沿って、対応する関数がfunc内で自働的に並んでいて欲しいのです。
コンパイル時点では順番は確定しているんですから、テンプレートを
ごりごり使いこなせる人間ならできるんじゃないかと淡い期待を
持ってるんですが、どうにかして出来ませんでしょうか?
0370デフォルトの名無しさん
NGNG不可能
0371デフォルトの名無しさん
NGNGなぜ順番を変えようとする?
0372デフォルトの名無しさん
NGNGVBAかなにかでボタン一個でソース吐くようにしとけば?
俺だけかもしらんが、よくやってるよ。
その場限りならセルに文字列適当に連結する式かいてコピペ、とかもやるし。
0373デフォルトの名無しさん
NGNG見栄えが気にくわなくてあっち入れ替えたりこっち動かしたりする時期があるもんさ。
0374デフォルトの名無しさん
NGNG0375デフォルトの名無しさん
NGNG#include "stdafx.h"
template< int > struct Function{};
#define DEF_FUNC( index, func ) template<> struct Function<index>{ \
static void call(void){ func(); } }
enum {HOGE,HAGE,};
void hoge(){puts("hoge");}
void hage(){puts("hage");}
DEF_FUNC( HOGE, hoge );
DEF_FUNC( HAGE, hage );
int main(int argc, char* argv[])
{
Function<HOGE>::call();
Function<HAGE>::call();
return 0;
}
0376375
NGNG今頃気づいたけど、呼び出し時のインデックスはコンパイル時には確定してないのか・・・じゃ駄目だ。
0377375
NGNGちょっとオーバーヘッドがあるけど、
(テンプレートクラス内のcallをfuncへのポインタに出来ればいいんだろうけど、俺はやり方知らない。)
void (*funcs[])(void) = {
Function<HOGE>::call,
Function<HAGE>::call
};
int main(int argc, char* argv[])
{
for( int index = HOGE; index<=HAGE; ++index )
{
funcs[index]();
}
return 0;
}
0378デフォルトの名無しさん
NGNG> Function<HOGE>::call,
> Function<HAGE>::call
> };
それだと結局、enumを
enum {HAGE,HOGE,};
に変えられたときにマズーではないか?
0379375
NGNGやっちまった(藁
0380デフォルトの名無しさん
NGNGちょっとなぁ、という気がする。
自分が書くにはいいが、人には見せられない。
そもそも、見栄えを気にする(順番を入れ替える)んだから、
その書き方はいいとは思えない
0382375
NGNGenum値と対応させるってことは配列のインデックスは手打ちでenumの値を書くってことだろ?
インデックスが実行時に決まるならenumに対応させる意味もないし。
0383デフォルトの名無しさん
NGNGHAGE,
HOGE,
};
template<int i>
void f();
template<>
void f<HAGE>()
{
return;
}
void f<HOGE>()
{
return;
}
void (*func[])() = {
f<HAGE>,
f<HOGE>,
};
0384デフォルトの名無しさん
NGNG0385369
NGNGどうやればいいのかはさっぱり分かりませんけど。
>>382
いや、呼び出すときは (*func[n])() ですが…。
対応させる意味がない…? えーと。考えます。
0386デフォルトの名無しさん
NGNG0387デフォルトの名無しさん
NGNGテーブルを動的に作るのはだめなん?
0388デフォルトの名無しさん
NGNG俺もそう思う。
0389369
NGNGエンコーダとデコーダを作ってまして。
エンコーダは、テキストの文字列 "hoge" "hage"を読み込んで、
バイナリでenum値「HOGE,HAGE」を吐きます。んで、
デコーダは、バイナリでHOGE,HAGEをみて、関数hoge(),hage()を呼ぶ、と。
そういう状況です。
>>テーブルを動的に
いや、いいんですけど。でも、静的に解決できることじゃないですか。
出来たらかっこいいじゃないですか。そういうスレじゃないですか、ここは。
0390デフォルトの名無しさん
NGNGもし出来たとしても決してかっこよくはならないと思うぞ。
0391デフォルトの名無しさん
NGNGusing std::cout;
using std::endl;
enum {SAGE,MONA,MOGE,HOGE, END}; // ←ここ順番変えてよし!
typedef void (*FUNC)();
void hoge() { cout<<"hoge"<<endl; }
void moge() { cout<<"moge"<<endl; }
void mona() { cout<<"mona"<<endl; }
void sage() { cout<<"sage"<<endl; }
template<int> inline void f() {}
#define ASSOC_FUNC(E,F) template<> inline void f<E>() { F(); }
ASSOC_FUNC(HOGE,hoge)
ASSOC_FUNC(MOGE,moge)
ASSOC_FUNC(MONA,mona)
ASSOC_FUNC(SAGE,sage)
FUNC func[] = { f<0>, f<1>, f<2>, f<3> };
int main()
{
for( int i=0; i<END; ++i )
func[i]();
return 0;
}
…と思ったんだけど、関数ポインタ経由だからinline展開されないよなぁ、これ…。
0392デフォルトの名無しさん
NGNGそれだったら、
std::map<std::string, void(*)()> m;
m["hoge"] = hoge;
これでいいじゃん。
0393デフォルトの名無しさん
NGNG試みとしてはおもしろいかな。
でも、おれの知識じゃまだ無理だなあ。
Modern もっとよむか
0394デフォルトの名無しさん
NGNGそれがもの凄く伝わってくるスレ
0395デフォルトの名無しさん
NGNG改造してみた、本末転倒?
#include <iostream>
using std::cout;
using std::endl;
enum {SAGE,MONA,MOGE,HOGE, END}; // ←ここ順番変えてよし!
#define sage f<SAGE>
#define mona f<MONA>
#define moge f<MOGE>
#define hoge f<HOGE>
typedef void (*FUNC)();
template<int> void f() {}
template<> void sage(){cout<<"sage"<<endl;}
template<> void mona(){cout<<"mona"<<endl;}
template<> void moge(){cout<<"moge"<<endl;}
template<> void hoge(){cout<<"hoge"<<endl;}
FUNC func[] = { f<0>, f<1>, f<2>, f<3> };
int main()
{
for( int i=0; i<END; ++i )
func[i]();
return 0;
}
0396デフォルトの名無しさん
NGNG全然かっこよくないぞ
0397デフォルトの名無しさん
NGNG0398369
NGNG0399デフォルトの名無しさん
NGNGModern(の前半)読んでかっこいいと思ったか?
俺は、すげぇとは思ったがかっこいいとは思わなかったよ(むしろ汚い)。
このスレで今やってることも同じようなもんさ。
おとなしく動的作成にしない389が悪い。
0400デフォルトの名無しさん
NGNG#include "stdafx.h"
をソースファイルの先頭に入れ忘れてるとか。
0401デフォルトの名無しさん
NGNGVCだとバグのせいでうまくいかなかったはず。
たしか、すべて同一の実体を指すようになってたような。
0402デフォルトの名無しさん
NGNG他のに乗り換えれ。
0403デフォルトの名無しさん
NGNGtemplate <int i> void func()
{
std::cout << i << std::endl;
}
int main()
{
func<0>();
func<1>();
return 0;
}
これをコンパイルしてみればわかる
0404デフォルトの名無しさん
NGNG0405369
NGNG0406デフォルトの名無しさん
NGNGtemplate<int i> class func {
public:
func() {
std::cout << i << std::endl;
}
};
0407デフォルトの名無しさん
NGNG0408369
NGNGで、あとは391と組み合わせれば…?
0409369
NGNGどうすれば…。
0410デフォルトの名無しさん
NGNGヒント
enum {
HAGE,
HOGE,
};
class FuncBase {
public:
virtual void operator()() { }
};
template<int i> class FuncObj;
template<>
class FuncObj<HAGE> : public FuncBase {
public: void operator()() {
std::cout << "hage" << std::endl;
}
} hage;
template<>
class FuncObj<HOGE> : public FuncBase {
public: void operator()() {
std::cout << "hoge" << std::endl;
}
} hoge;
FuncBase* func[] = {
&hage,
&hoge,
};
int main()
{
(*func[HOGE])();
(*func[HAGE])();
return 0;
}
テーブルに登録するところをいじってくれ
0411デフォルトの名無しさん
NGNG0412デフォルトの名無しさん
NGNG最悪だな
0413デフォルトの名無しさん
NGNG0414デフォルトの名無しさん
NGNG********************** 終了 ************************
0415369
NGNG>>395にはかないませんけど、>>391より効率よく、なおかつVC6でも動きます。
#include <iostream>
using namespace std;
enum{HOGE,MOGE,HAGE,SAGE};// ←順番は任意に入れ替え可能
void hoge(void){cout<<"hoge"<<endl;}
void sage(void){cout<<"sage"<<endl;}
void moge(void){cout<<"moge"<<endl;}
void hage(void){cout<<"hage"<<endl;}
typedef void (*FUNC)(void);
template<int v>
struct f{
static FUNC f_;
};
#define ASSOC_FUNC(A,B) template<> FUNC f<A>::f_ = B;
ASSOC_FUNC(HOGE,hoge)
ASSOC_FUNC(HAGE,hage)
ASSOC_FUNC(SAGE,sage)
ASSOC_FUNC(MOGE,moge)
#undef ASSOC_FUNC
FUNC funcTable[4] = {f<0>::f_ ,f<1>::f_ ,f<2>::f_ ,f<3>::f_ };
int main(int argc, char* argv[])
{
for (int i=0;i<4;++i)
(funcTable[i])();
return 0;
}
0416デフォルトの名無しさん
NGNG0417デフォルトの名無しさん
NGNG0418デフォルトの名無しさん
NGNG0419デフォルトの名無しさん
NGNG0420369
NGNG ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
∧_∧
( ´Д⊂ヽ
⊂ ノ
人 Y
し (_)
(´-`).。oO(っていうか、考えついたのが満足であって、>>415を使ったりはしないけどね…)
(´-`).。oO(.NETなら>>395を使えるのかしら?)
0421デフォルトの名無しさん
NGNGでも誰も使うことはないだろう。
0422デフォルトの名無しさん
NGNGこれが実戦と同じだと勘違いしたら問題だが、
こういう鍛え方でしか鍛えられないことはある。
どんどんやるべきだと思うよ。
0423デフォルトの名無しさん
NGNG運動するための筋トレはまったく別物。
鍛え方を間違っちゃいかん。
0424デフォルトの名無しさん
NGNG0425369
NGNG通ることに気付いてしまいました。
#include <iostream>
using namespace std;
class Hoge
{
public:
void operator()(void){cout<<"hoge"<<endl;}
};
int main(){
Hoge()();// ←なんと奇怪な構文!
return 0;
}
…うわー。これ、ホントに通っていいんですか? まあ、理屈には合ってますけど…。
(最初のカッコでHogeのデフォルトコンストラクタでテンポラリインスタンスを生成。
次のカッコでHogeのoperator()を呼び出す)
VCだけじゃないことを祈りまふ…。
ちとスレ違いかな。sage.
0426デフォルトの名無しさん
NGNGそれ、普通だが?
文が完了するまで一時オブジェクトの寿命が続くはず。
Hoge(), foo(), bar();
こうすると、bar()の後にHogeのデストラクタが呼ばれる
0427369
NGNGコンストラクタやoperator()の引数次第で、関数宣言だとか
関数ポインタだとか、そのあたりと間違えてしまいそうな構文だなーと。
0428デフォルトの名無しさん
NGNG0429デフォルトの名無しさん
NGNGstruct Hoge { Hoge& operator()(void){return *this;} };
int main() {
Hoge()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()();
}
…はともかくとして、何の変哲もないふつうの構文だと思うよ。
> 関数宣言だとか関数ポインタだとか、そのあたりと間違えてしまいそうな構文
引数付きのコンストラクタを呼び出したりする時に、
下手すると関数宣言扱いになっちまうことはあり。
Effective STLとか参照。
0430デフォルトの名無しさん
NGNGそれ、Cでも通らん?
#include<stdio.h>
typedef void (*fp)(void);
typedef fp (*fpp)(void);
void hogegege(void)
{
printf("\nhogegege\n");
return;
}
fp hogege(void)
{
printf("\nhogege\n");
return(hogegege);
}
fpp hoge(void)
{
printf("\nhoge\n");
return(hogege);
}
int main (int argc, char argv[])
{
hoge()()();
return(0);
}
----
/tmp>gcc hoge.c
/tmp>./a.out
hoge
hogege
hogegege
/tmp>
0431デフォルトの名無しさん
NGNGしかしそれはC++信望崩壊への、ほんの序曲でしかなかった──────。
425「げ、良く考えたらどれもこれも、Cで作れるじゃん!」
430「それ、Cでも通らん?」
413「はっきりいって、ここまでしてやることじゃないと思う」
426「それ、普通だが?」
425「し、Cマンセー!C++なんてクソ。これ定説!」
だれかprojクトX風に仕立ててくれ。
0432デフォルトの名無しさん
NGNG\ ヽ / /ソ
プ ロ ジ ェ ク ト\ ヽ P r o j e c t X
─────────────────────
Generatorたち /|_/ /\Generators
| / \ 丶
\/ \__ノ
Genericスレッド。
このスレで425は一人で悩んでいた。なぜこんな構文が許されるのかと。
「いや、関数オブジェクトでは当たり前だ。」
「こんな物は普通だ。」
次々とヤジが飛ぶ。へこんだ。
万策尽き果てたとき、ふと430が現れる。
「Cでも出来るんじゃないか?」
これは、C++に翻弄された男たちの物語である。
風の中のスバル〜♪
0433デフォルトの名無しさん
NGNG1+-+-+-+-+-+-+-+1 とか
■ このスレッドは過去ログ倉庫に格納されています