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

Generic Programming with C++ Template

レス数が900を超えています。1000を超えると表示できなくなるよ。
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/
0809デフォルトの名無しさんNGNG
頭の中で英語に訳しながら理解すべし。(ワラ
0810名無しさん@カラアゲうまうまNGNG
bk1 で More 注文したけど入荷できずにキャンセルされちゃったよ。
思い切って洋書を注文したよ。がんがろ。
0811デフォルトの名無しさんNGNG
More Modern C++ Design
0812デフォルトの名無しさんNGNG
effective C++って第2版でどう変わったの?
0813デフォルトの名無しさんNGNG
>>808
普通に読めたよ。
0814デフォルトの名無しさんNGNG
D&E
ARM
(;´Д`)
0815デフォルトの名無しさんNGNG
>>812
標準C++の文法に準拠した新しい機能を使っている。
0816名無しさん@カラアゲうまうまNGNG
救いage
0817 ◆4COMPILE NGNG
>>813
すごいな、漏れは "コンストラクター" と、伸びる時点でかなりひいたし、
後半はわけがわからないので、原書かっちまったが・・・
0818デフォルトの名無しさんNGNG
>>817
伸ばし棒の事なんかどうでもいいから後半のわけわからないっぷりについて
おしえてください。
0819 ◆4COMPILE NGNG
>>819
たとえば、
const と コンストラクタ が混同されている部分があったりする。
そんな間違いをできるくらいで(だって普通文脈上そんな間違いできないでしょ)、
訳者は著者の書いていることを全然理解してない。
0820 ◆4COMPILE NGNG
>>819
(・∀・)サイキレス カコイイ!!

すまぬ、>>818の間違い。
0821デフォルトの名無しさんNGNG
その点ModernC++Designの村上氏は、
誤植の問題にも逐一訂正を載せてるし、
原著の修正にも載ってないものに
関しては報告してるみたいだから素晴らしいね。

翻訳もののダメっぷりばかりが目立つ
この業界の出版事情だけどいい仕事してる
ひともいるわけで、そういった人の本が
もっと売れるようになって欲しいところだね。
ダメな人を晒あげても切りがないので、
いい仕事をしている人を取り上げよう。

私は村上さんの本は信頼できると思います。
0822デフォルトの名無しさんNGNG
そういや訳してるヤシはプログラマなのか?
0823デフォルトの名無しさんNGNG
>>819
わしは脳内補正して読んだ。
0824デフォルトの名無しさんNGNG
>>819
それはすごい。
0825_1NGNG
関数ポインタを勉強してるんですが、
CTest2みたいなことは無理でしょうか?(CTest1はOKでした)
/*
int test(int a)
{
CTemp temp;
return temp.Func(*this,f,a);
}
クラス(*this)を渡して動的にテンプレートで作成させれば 何個も CTemp<???> を作らなくて済む。
*/

#include<iostream>
using namespace std;

template <typename _T>class CTemp
{public:
typedef int (_T::*Pstd)(int);
int Func(_T& ob,Pstd f1,int a)
{
return (ob.*f1)(a);
}
};

class CTest
{public:
int f(int a){ return a*2;}
int test(int a)
{
CTemp<CTest> temp;
return temp.Func(*this,f,a);
}
};


0826_2NGNG
class CTemp2
{public:
template <typename T,typename R> typedef R (T::*Pstd)(R);//typedef はtemplate化 できないのか?
template <typename T,typename R> R Func(T& ob,Pstd f1,R a)
{
return (ob.*f1)(a);
}
};

class CTest2
{public:
template <typename TM1>TM1 f(TM1 a){return a*2}
template <typename TM> TM test(TM a)
{
CTemp2 temp;
return temp.Func(*this,f,a);
}
};

int main()
{
CTest t;
cout << t.test(100);

CTest2 t2;
cout << t2.test(100);
}
0827デフォルトの名無しさんNGNG
>>826
typedef のテンプレートはまだできないよ
0828825NGNG
>>827
そうでしたか...。ちょっと変えたらできました。
class CTemp2
{
public:
template<typename T,typename R> R Func(T& ob,int (T::*f1)(R),R a)
{
return (ob.*f1)(a);
}
};

class CTest2
{
public:
int f(int a){ return a*2;}
template<typename R> R test(R a)
{
CTemp2 temp;
return temp.Func(*this,f,a);
}

};
0829名無しさん@カラアゲうまうまNGNG
http://sourceforge.net/projects/loki-lib/
0830828NGNG
下みたいにすると、
関数テンプレートを関数の引数として使用できません。
とでるんですけど、
無理なんでしょうか?
(補足:828はC++.NETならコンパイル可です。gccはオプションの設定が
よく分からないのでコンパイルできませんでした)

class CTest2
{
public:
template<typename R> R f(R a){ return a*2;}//ここを変更
template<typename R> R test(R a)
{
CTemp2 temp;
return temp.Func(*this,f,a);
}

};
0831デフォルトの名無しさんNGNG
>>830
少なくともVC++.NETならこれで通った。

template<typename R> R test(R a)
{
  int (CTest2::*tf)(R) = f<R>;
  CTemp2 temp;
  return temp.Func(*this,tf,a);
}

が、bccとかgcc2.95はICEる。gcc3.xはわからん。
0832デフォルトの名無しさんNGNG
>>831
できた!サンクス。
LokiのFunctorをVC++.NETでコンパイルできないんだけど
やっぱり書き換えないと駄目なのかな?それとも設定ミス?

template<typename R> R test(R a)
{
typename R (CTest2::*tf)(R) = f<R>;
CTemp2 temp;
return temp.Func(*this,tf,a);
}
0833デフォルトの名無しさんNGNG
>>832
LokiPortは?
0834デフォルトの名無しさんNGNG
++a+a+++a+++a+a+++a+++a+a+++a+a+++a++; // + 激しくインクリメント + //
0835デフォルトの名無しさんNGNG
>>834
ワロタ
0836デフォルトの名無しさんNGNG
ジェネリックネタは尽きたか・・・!?アゲ
0837デフォルトの名無しさんNGNG
template<class T,class S>class Typelist{
typedef T t;
typedef S s;
};
0838デフォルトの名無しさんNGNG
>>837
パブリックのメンバしかないクラスはstructを使うのが
彼のコーディング規約らしい。
あとテンプレートパラメータがプリミティブになるときにはtypename

これが一番役にたったかな。。。鬱
0839デフォルトの名無しさんNGNG
template<class T,class S>struct Typelist{
typedef T HEAD;
typedef S TAIL;
};
template<class A>struct TCA{
typedef A::HEAD A;
typedef A::TAIL B;
A a;
};
void main(void)
{
TCA<Typelist<int,double> > tca;
}
なんでエラーになるねん?
0840デフォルトの名無しさんNGNG
間違ってるから
0841デフォルトの名無しさんNGNG
>>838
> typedef A::HEAD A;
そりゃー無理だろう。
0842デフォルトの名無しさんNGNG
template<class T,class S>struct Typelist{
typedef T HEAD;
typedef S TAIL;
};
template<class A>struct TCA{
typedef typename A::HEAD HEAD;
typedef typename A::TAIL TAIL;
A a;
};
void main(void)
{
TCA<Typelist<int,double> >::HEAD tca1;
TCA<Typelist<int,double> >::TAIL tca2;
}
0843デフォルトの名無しさんNGNG
>>839
まぁでもBCCだと通ってしまうという
0844デフォルトの名無しさんNGNG
Lokiにはstruc.incの亡霊が見える。
こういう拡張は、言語の死の前兆なのだろうか、と思ってみたり。
0845デフォルトの名無しさんNGNG
著者はテンプレの制限追っかけるより
手っ取り早くcppを拡張してほしい。
C++は詰め込みすぎだ。
0846デフォルトの名無しさんNGNG
多次元配列についてはどうだ?
0847デフォルトの名無しさんNGNG
なにが?
0848デフォルトの名無しさんNGNG
最近boost-mlではMPLの話題が多いのぅ…
あれがboost本家に入ればここも盛り上がる…かな?
0849デフォルトの名無しさんNGNG
誰か俺に力を

template< typename T > class A
{
public:
//A(void){}
~A(void){ T::function_not_called(); }
};
class B
{
public:
A< class C > c;
};

int main(void)
{
new B();
}

VC.NET
A()のコメントはずすと~A()でコンパイルエラー・・・Why?
0850デフォルトの名無しさんNGNG
>>849
g++ でちょっと調べてみた。

A() がある場合、 B() をコンパイラが生成する。
で、 B() が生成された段階で、 B(){throw 0;} みたいなコードに
対応するために(だと思う) ~A<C>() がインスタンス化される。

A() が無い場合、 B() も無いことになって、このとき ~A<C>() はインスタンス化されない。

ためしに、 A(){} をコメントアウトしたまま、 B(){} を追加しても同じエラーになる。
でも、 B(); として外部参照にすると、エラーは消える。
これは、 ~A<C> が B() のコンパイル時にインスタンス化されているということだと思う。

それならと思って例外処理を無効にするオプションを追加してみたけど、
結果が変わらなかったのがよくわからないところ。
0851デフォルトの名無しさんNGNG
>>850
あんたすごいよ!
俺は思いつきもしなかった・・・
VC.NET も同様の結果。
実際のコードは B もテンプレートだったりして、あきらめるしかないか。
0852デフォルトの名無しさんNGNG
プチStateパターン。なんてのを提案してみます。

状態ごとに振る舞いを変えたいけど、Stateパターンをやるまでもないという
場合は、だいたいこんな感じでやってますよね?

// Hoge.h
class CHoge
{
  int state_;
  void age(void) {}
  void sage(void) {}
  void giko(void) {}
  void mona(void) {}
public:
  void Action(void);
};

// Hoge.cpp
typedef void (CHoge::*FUNC)();
FUNC table[] = {
  &CHoge::age,
  &CHoge::sage,
  &CHoge::giko,
  &CHoge::mona,
}

void CHoge::Action(void)
{
  // 状態ごとに振る舞いを変える。
  (this->*table[state_])();
}


こうやっていると、ひとつ状態が増えただけで、呼び出す関数が増えるから、
Hoge.hを書き換えなきゃならないのが弱点。そこで、こんなのはどうでしょう。
0853デフォルトの名無しさんNGNG
(続き)

// Hoge.h
class CHoge
{
  int state_;
  template<int> void InnerAction(void);
public:
  void Action(void);
};

// Hoge.cpp
enum {
  AGE,SAGE,GIKO,MONA,
};

template<> void CHoge::InnerAction<AGE>(void) {}
template<> void CHoge::InnerAction<SAGE>(void) {}
template<> void CHoge::InnerAction<GIKO>(void) {}
template<> void CHoge::InnerAction<MONA>(void) {}

typedef void (CHoge::*FUNC)();
FUNC table[] = {
  &CHoge::InnerAction<0>,
  &CHoge::InnerAction<1>,
  &CHoge::InnerAction<2>,
  &CHoge::InnerAction<3>
}

void CHoge::Action(void)
{
  // 状態ごとに振る舞いを返る。
  (this->*table[state_])();
}

こうすると、状態がいくら増えても、変更するのはHoge.cppだけ。
Hoge.hは変えなくてよくなります。プチStateパターンと名付けたけど、
なにげにBridgeパターンも兼ねてるわけです。
tableで「CHoge::InnerAction<0>」とマジックナンバーが入っているのは、
enum順が変わっても、tableの並びを変えなくていい、というテクです。
>>369-423を参照して下さい。

仕様が不安定な中で開発するときは割と使えると思いますけど、
どうでしょ、このテク。
0854デフォルトの名無しさんNGNG
template<>の中でifは使えないが、三項演算子なら使えるのだな。
誰かこれ使って何かしてくれよ。
0855デフォルトの名無しさんNGNG
>>854
boost::call_traits
0856デフォルトの名無しさんNGNG
>>853
Hoge.hを書き換えられないという状況があんまり想定できん
0857名無しさん@カラアゲうまうまNGNG
>>856
Hoge.h を書き換えてビルドしたら、これをインクルードしている
ものも再構築しなければならない罠ってやつでは?
0858デフォルトの名無しさんNGNG
>>857
やればいいやん。ビルドに時間がかかるんならそれはそれで問題。
0859デフォルトの名無しさんNGNG
>>857
外部インターフェースと実装を分離したいなら pimpl イディオム使うのが
一般的だと思う。pimpl イディオムだと、内部的に使うメンバ変数が増えて
も OK だし。
0860デフォルトの名無しさんNGNG
関数レベルのプチな振る舞い変化ならStateパターンなど使わずにswitch/case使うべきと思われ
0861デフォルトの名無しさんNGNG
>>849
それ以前に、C++で f(void)はやめれ。間違いじゃないけど。
0862デフォルトの名無しさんNGNG
>>861
なぜっすか?
0863デフォルトの名無しさんNGNG
俺はvoidな変数とvoidな引数がホスィな

void set_name_age( char const* name, int age ){}

void result = set_name_age( "もな", 5, void, void );

テンプレート使うときに幸せだ・・・
0864デフォルトの名無しさんNGNG
>>862
無意味だから。
0865デフォルトの名無しさんNGNG
>>864
おまえの存在が無意味
0866デフォルトの名無しさんNGNG
>>861
じゃ戻り値intもその時のreturn 0も書くのやめるか?
0867デフォルトの名無しさんNGNG
>>866
意味不明だが……何を主張してるんだ?
0868デフォルトの名無しさんNGNG
>>867
main(){

}
で十分だろ
0869デフォルトの名無しさんNGNG
>>868
いいえ
0870デフォルトの名無しさんNGNG
>>869
なぜ?
0871デフォルトの名無しさんNGNG
>>870
本気で聞いてるの?
0872デフォルトの名無しさんNGNG
>>871
つーか本気で言ってるの?
0873デフォルトの名無しさんNGNG
>>872
Are you a Generic C++ Programmer?
0874デフォルトの名無しさんNGNG
>>872
>867 と >869 は本気で言ってる。それ以前の書き込みは俺じゃないから知らん。

>>866
> じゃ戻り値intもその時のreturn 0も書くのやめるか?
C++ の規格に照らし合わせて

1. 仮引数宣言を (void) とするのは () と等価。
2. 関数の型を省略すると int と見なされる

までは正しいが、

3. int 型関数で return を省略すると、デフォルト値 0 が戻り値として渡される

のは嘘だよな。

省略可能な int, void を書くかどうかはスタイルの問題だが(俺は書くけど)、
return を書かないのは規格上マズイって話。
0875デフォルトの名無しさんNGNG
>>874
mainに限ってはreturnがない場合0が返る。
0876デフォルトの名無しさんNGNG
// 望洋せんせいは

int foo1() {
}
int foo2( void ) {
}
int var() {
  foo1( 0 ); // 問題なし
  foo2(); // コンパイルエラー
}

// ってゆってたよ。
0877876NGNG
ちがった!
foo2( 0 ); // これで、コンパイルエラー。
foo2(); // は、もちろんOK。
0878デフォルトの名無しさんNGNG
>>876
多分、いろいろ勘違いしている
0879デフォルトの名無しさんNGNG
>>876
CならOK
C++じゃだめ。
0880876NGNG
>>879
いま g++ と gcc で試してみたらそのとおりだった。
スレ汚しちゃってスマソ。
0881876NGNG
// これも試してみたよ。
// 常に 0 が表示されちゃう。
#include <stdio.h>
int foo() {}
void main() {
    printf("%d\n",foo());
}

// % g++ -v
// gcc version 2.95.3-5 (cygwin special)
0882デフォルトの名無しさんNGNG
>>875
ほんとだ。いつ追加された仕様なんだろうな、これ?

(VC6 あたりだと警告が出る)
0883デフォルトの名無しさんNGNG
C99からだったりして
0884デフォルトの名無しさんNGNG
亀レスで失礼。

>>323
"もっと技術的な話をきぼんぬ" って本人にメール出したら多分聞き入れてくれるよ。
...どういった方向の技術の話題を希望するのか書いとけば恵比寿氏も喜ぶよ、きっと。

>>327
いや、恵比寿氏が用意した場所で本人にうざいって言うのは人としてどうかと思うぞ。
わざわざ、人んちに押しかけといて家主に "あんた邪魔、帰れ!" って言うのと同じ様なもんだぞ。
0885デフォルトの名無しさんNGNG
>>884
御説はもっともなのだが、おぬし、流石に亀レスすぎないか。
0886デフォルトの名無しさんNGNG
>>885
ごめん。古い書き込みとはいえ、なんか無駄な非難をほっとけなくて。
0887デフォルトの名無しさんNGNG
ひょっとして本人?
0888デフォルトの名無しさんNGNG
>>876
ANSI規則でコンパイルしてみれ。
0889884NGNG
>>887
違う、道イヒ師。
0890デフォルトの名無しさんNGNG
わざわざ名乗らんでもええのに
0891884NGNG
>>890
気づかれなかったことが、なんか寂しかった。

...スレ汚しスマソ。本題の話を続けてくれ。
じゃ、バイバイ〜♪。(´ω`)ノシ
0892デフォルトの名無しさんNGNG
そんなこと言われても本題と言えるほどのネタがない罠。
0893デフォルトの名無しさんNGNG
Lokiがboostに入るなんて話はないんでしょうか?
0894デフォルトの名無しさんNGNG
あったりする。
0895sageNGNG
trickタソ…
ハァハァ
0896 ◆4COMPILE NGNG
>>894
まじ?
0897デフォルトの名無しさんNGNG
>>896
894の妄想。
0898デフォルトの名無しさんNGNG
>>896
・Functor, メモリプール, TypeTraits 辺りは既にboostにある。
・TypeListなどはMPL( MetaProgrammingLibrary )とゆーもっと
 汎用的な枠組みで吸収。1.30.0くらいでリリース版に入りそう。
・Policyベースのスマートポインタは統合作業&議論中。
・AbstractFactory/Singletoneなどは、boost::DesignPattern
 ライブラリを作るとか作らんとか言ってた気がするけど不明。
0899 ◆4COMPILE NGNG
>>898
にゃるほど、ちょっと調べてみる。
0900デフォルトの名無しさんNGNG
4compileさん(・∀・)イイ!
0901デフォルトの名無しさんNGNG
boostってフリー?商用もいけるの?
0902デフォルトの名無しさんNGNG
ライセンス調べろ
0903デフォルトの名無しさんNGNG
キミのこと気持ちよくしてあげたいんだ・・・
0904デフォルトの名無しさんNGNG
>>902
英語読めねぇから聞いてんだYO。
0905デフォルトの名無しさんNGNG
>>904
何様?(w
0906デフォルトの名無しさんNGNG
>>905
何様か聞いてどうしる?
0907デフォルトの名無しさんNGNG
>>906
愛撫するとか。


a means for you!: http://www.excite.co.jp/world/text/
0908デフォルトの名無しさんNGNG
>>907
thanks
でも変な訳で意味がよくわからんよ。
誰かやわらかく教えて臭い。
レス数が900を超えています。1000を超えると表示できなくなるよ。