トップページ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/
0075デフォルトの名無しさんNGNG
>>74
> 多分展開されるはず。
試してみ。
007653NGNG
>>75
お家にはC++コンパイラ置いてないの(しくり)。今、容量に余裕がなくって。
007753NGNG
とはいえ、
類似のコードは昔論文を読んだときに
g++で試したので、書き損じが無ければ>>74も動作はする筈。
inline展開と定数伝播の程度・能力に関してはコンパイラによるけど。
0078デフォルトの名無しさんNGNG
>>72-74
staticは意味が大きすぎてリンカは削除できないと思う。
5乗の計算に20バイト使う可能性がある!
constもinlineも保証はないので結局残るのはenumだけなんじゃないか?と。
運が悪いと普通のpowになっちゃいますよ的な。
そうして74のintの部分特別化にenumを使えるかなとかなんとか考えると疲れた寝る。
0079デフォルトの名無しさんNGNG
>>78
「意味が大きい」って?
あと20バイトくらいを問題にするなら展開されたコードの方が全然大きいかもよ?(w

大体enumの初期値として処理できる定数式なら
constの初期値として処理できない筈がない。
思うに、展開されたクラスのstatic constについて誰かがアドレス取らない限り
リンカまでも行かないで領域はないと思われる。

ちなみに、
Pow<N,X>::resultは定数式として定数の初期化に使えるところが利点。
Pow<T,N>(x)はNに関しては、
コンパイラが一般の部分特化のアルゴリズムを備えていなくても
テンプレートと定数伝播、inline展開の常識的な実装を備えてさえいれば
確実に部分特化の意図が伝わるのが利点。

初期のcfrontでトランスレートしてた時代ならイザ知らず、
constもinlineもここで出てる例くらいならば、今の最適化技術では
可能不可能の問題でなくやるかやらないかの問題だから、
一般用途のまっとうなコンパイラでは十分できる範囲だと思う。
0080デフォルトの名無しさんNGNG
>>79
だから、とりあえず手元の処理系で試してみろって。
008171?NGNG
>>74
BCCでためしたで
ASM見たけど思惑道理なってるで
0082デフォルトの名無しさんNGNG
>>81
よって問題なし、と。

規格について一通り調べがついた後は、「思う」と書いてあーだこーだ議論するより
実際処理系での結果を出した方が話が早いっしょ。
008353NGNG
>>81-82
どうもです。
今、ようやく試せる環境(研究室の自分の机)にたどり着きました(w。
もう話は終わってるみたいですが。
0084デフォルトの名無しさんNGNG
>>79
20バイトというより1バイトさえも使っては意味がないし
コードが展開されてはそもそもいけない。
コンパイル時評価になることが保証されてこその新しいPow。
Pow<N,X>::resultは、コンパイル時評価は保証されないし
計算ごとに生まれる多くのstatic intが削除されることが
保証されないので恐ろしくて使えない。
Pow<T,N>(x)は、やはりインラインが保証されない上、
インライン展開されてもコンパイル時評価になることが
保証されないので駄目。
いままで標準準拠のコードを書くためにがんばってきたのに
ここでenumを裏切るのはなぜか。
あとcfrontがどうとか言い出すのが好感度下げる。ワラ
008571?NGNG
>>84
いいたいことはわかるが、templateでやる以上、
pow( 2.0 , 3.5 )とかやりたいね。
0086デフォルトの名無しさんNGNG
>>84
完璧確実を求めるならちゃんとPartial Evaluationなり、
2-level Languageなり使うしかないんでは?
元々C++の機能の有り合わせで実現してるんだから。

とりあえず両者とも(仮に最適化されなくても)規格的には最低限動作することになっていて、
少なくとも普及している処理系の一つで意図どおり動作するコードではあるのは確か。

ちなみに実行時にtemplateの展開処理をする珍しいコンパイラでない限り
Pow<N,X>::resultはコンパイル時に定数になっていなければならない。
当然定数式の必要なところでは定数として利用できる。
このコードの本来の目的はそれ。
領域が割り当てられて残るかどうかは副次的なことに過ぎない。
仮に、アドレスを取ったりできるように領域が割り当てられたとしても、
定数伝播の最適化とはまた別の側面の話なので問題はない。
(せいぜいメモリ使用量が増えるだけ。実行速度に悪影響はない。
元々展開テクニックではメモリ使用量ではなくて実行速度に重点が置かれる。)

それに標準準拠って言うけどstatic const intではダメでenumに拘る理由も結局不明。
初期化がコンパイル時に実行できないかどうかは、初期化式の側の問題であって
初期化される変数・定数の側の問題ではない。

裏切るも何も、列挙しない単一の定数の宣言にenumを使うほうこそ
考え様によっては病的だと思うがどうか?
(領域がないことを保証させるための抜け道だということは知っているが、
病的なことに変わりはない。)

あと、>>84君の好感度などはこの際限りなくどうでもよいこと。

もう一つ言えば、
これは標準数学ライブラリのpowを置き換えることを意図したものではない。
Pow<N,X>::resultは定数式の必要なところ(固定長配列の長さとか)で
べき乗の計算を行うために必要なだけのもので、
Pow<T,N>(x)は整数Nを固定したべき乗演算が繰り返される場合に有効なコード。
そういう特殊な用途以外の一般の場合には標準的なライブラリのpow()を使えばよい。

さらに言えば、これはGenerativeなコードをC++の有り合わせで書く場合に利用できる
テクニックを紹介するためのサンプルかつ部品である。
powだけ計算して満足しているわけではない。

>>85
残念ながらx^nのnは整数でないと特化できない。
0087デフォルトの名無しさんNGNG
>85
@sin( 1.46 )とかを展開するような
独自プリプロセサを書けや。
0088デフォルトの名無しさんNGNG
>>87
そんなことせんでもsin(1460000) // =1.46*1000000とかして
1000000で割ればいいじゃん。
古典的手法
0089デフォルトの名無しさんNGNG
>sin(1460000)
sinをテンプレートで実用的にかけると仰る?
0090デフォルトの名無しさんNGNG
>>86
>少なくとも普及している処理系の一つで意図どおり動作するコード
それが駄目だとあれほど。

コンパイル時評価が保証されないので
全くGenerativeではない。君は

賢いコンパイラは仮想呼び出しを実呼び出しに最適化できるので
templateはいらない、仮想関数で十分。
領域が割り当てられて残るかどうかは副次的なことに過ぎない。
せいぜいメモリ使用量が増えるだけ。実行速度に悪影響はない。
多態性にtemplateを使うのは病的。

と思っている。確かにこれは正しい。ワラ
ここでSTLが大好きな君が裏切るのはなぜか。
0091デフォルトの名無しさんNGNG
つまりさあ、87とかの話題ってfixed演算なわけだよね。
そういうことしたいならLISPでプリプロでも書いたほうが自由度高いし簡単。

(defconst var `(,(sin 1.46))) ;;;リストvarにsin(1.46)の結果を埋め込み。

C++もコンパイル時に関数を実行できる仕様だったら便利なのにね。
0092デフォルトの名無しさんNGNG
べつにLISPじゃなくてもいいんだけどね。perlやRubyとかでも。
関係ないけどVBでこういうことができないのは不思議。
0093デフォルトの名無しさんNGNG
>そんなことせんでもsin(1460000) // =1.46*1000000とかして
>1000000で割ればいいじゃん。
まさか・・・
0094デフォルトの名無しさんNGNG
>>91
C++で実装される言語がなにやらほざいているな
0095デフォルトの名無しさんNGNG
STLいいんだけどさぁ、
コンパイルエラー等ででてくる、エラーをどうにかしてほしい。
0096デフォルトの名無しさんNGNG
>>95
『STL Error Decryptor』
 http://www.bdsoft.com/tools/stlfilt.html
みたいなものを使ってみるとか。
0097 NGNG
>96
をぉ!それは便利そうだ!!!!
と思ったら VC 用かよ・・・
残念sage
0098デフォルトの名無しさんNGNG
>>90
もう、その話題は良いって。

使えると思うヤツは自分のコンパイラで試した上で使えば良いし、汎用性が
必要なプログラムを書いてる場合には、それなりの対処しろ。
0099デフォルトの名無しさんNGNG
>>98
Genericが汎用って意味なのだが
0100デフォルトの名無しさんNGNG
>>99
言葉遊びは、技術系の板の外でな。

Generic Programming を Win32 API と組み合わせてプログラミングしたって
良いじゃない。
0101デフォルトの名無しさんNGNG
「入門C言語」とか銘打っておいて、なかみをみると
いきなりWinMainからはじまったりすると激しく萎える。
0102デフォルトの名無しさんNGNG
>>101
そんな本があるのかーΣ(゚д゚lll)
禿げしくスレ違いだが書名キボンヌ
0103デフォルトの名無しさんNGNG
94は煽りのつもりだろうか
0104デフォルトの名無しさんNGNG
良スレage
0105デフォルトの名無しさんNGNG
>>100
話のすり替えは、技術系の板の外でな。

enumを置き換えられると思いこんだんだな。
0106デフォルトの名無しさんNGNG
>>105
言語の仕様上はこの場合でもenumはstatic const intに置き換えられるのでは?
置き換えられないというなら実例をキボンヌ
0107デフォルトの名無しさんNGNG
>>106
もう相手にしないで、放っておいてやるのが良いと思われ。
0108デフォルトの名無しさんNGNG
>>91
この例の意義はC++が既に持っている機能でこういうことが書けると言うところに意味がある。

・実用的なGenerativeアプリケーションの開発
・Generativeを正式にサポートする言語の研究開発への動機付け

他の言語に替えてよければ、それこそLISPもそうだが'CとかMetaMLとか色々ある。
0109デフォルトの名無しさんNGNG
それにこの例はGeneric ProgrammingとGenerative Programmingの近しい関係を端的に示している。
0110デフォルトの名無しさんNGNG
かくしてtemplateによってC++は2レベル(コンパイル時/実行時)言語になってしまっているいるわけだが、
元々そういう用途を意図して設計しているわけではないので、
この2レベルで激しく構文が違ってしまっているという問題はある。

例えば……:
template引数にはクラス・オブジェクトはおろか整数定数しか渡せない。
書きなれた命令型ではなく関数型プログラミングのスタイルで書かなければならない。
コンパイル時関数を表現するのにtemplateクラスを定義するのはやっぱ無理がある。

というわけでプログラミング言語学的には今後の研究が待たれるところであるっす。
0111デフォルトの名無しさんNGNG
>プログラミング言語学的

0112デフォルトの名無しさんNGNG
>111

0113デフォルトの名無しさんNGNG
C++Builder6の案内が着たけど
3ユーザーとしては買いでしょうか?
0114デフォルトの名無しさんNGNG
>>110
煽りはともかくとして、昔のCでマクロレベルでどうにかする、
ってのと基本的に変わらないね。
処理系がえらく大きくなった割には対効果が低いのが気になる。
>>108
'Cってなんですか?
quote-C?
0115デフォルトの名無しさんNGNG
>>114
今回の Pow() あたりだと、
> 処理系がえらく大きくなった割には対効果が低い
のは確かだが、STL の関数オブジェクトやアルゴリズムまで行くと、そう
捨てたものじゃないぞ。
0116デフォルトの名無しさんNGNG
templateあたりはもうちょっと洗練して縮小とかしてくれないと
あんまり使う気になれないんですが。オブジェクト指向とか以前に。
LISPのマクロなんかは最小限の労力で物凄い効果を期待できますけど、
あんな感じになって欲しいな。
0117デフォルトの名無しさんNGNG
現状のC++って複数の言語使ってる感じなんだよね・・・
0118デフォルトの名無しさんNGNG
みんなC++なんて止めてほかの言語を使おう(笑
0119デフォルトの名無しさんNGNG
C#ですかあ?
0120デフォルトの名無しさんNGNG
AllegroCLでも使いますか?(笑
0121デフォルトの名無しさんNGNG
実行時型やtemplateあたりの登場からC++では「おや?」と
思うようになったな。
javaもgenericを搭載するらしいが、はたしてどうなることやら。
なんつーか、ポリシーを持って作ってほしいね。
0122デフォルトの名無しさんNGNG
C++ではなくObjectiveCが普及すべきであった、せめて。
0123デフォルトの名無しさんNGNG
Objective-Cが普及しないのは名前長いから?
コミュニティが弱小だから?
ともかくObjective-CをC++という名前にして、
今までのC++は無かったことにするとか。
ストラウストラップは始めからいなかった事に(w
BorlandもDelphiと統合できなくて困ってるみたいだし。
0124デフォルトの名無しさんNGNG
MacOSXもC++で開発できるようには出来なかったらしい。
OSの設計に言語の汚さがついて行けなったらしく。
ObjectiveCがメインで、Javaでもなんとかなるとかならないとか。

C#登場で一気に滅亡しそうな予感もしてるんだな。
0125デフォルトの名無しさんNGNG
>>117
それは言えてる。

手続き、OO、汎用プログラミングなんでもアリなのはメリットだとは思うが、各々の
親和性がもうちょっと上がると嬉しい気がする。template がらみのエラーメッセー
ジとか。
0126デフォルトの名無しさんNGNG
C#はガベコレあるから、もはや別の次元でしょう。>124
0127デフォルトの名無しさんNGNG
最初の方で generative generative って言ってた人もう来ないのかな?
generic なアプローチと generative な方法との違いが知りたいんだけど。
0128デフォルトの名無しさんNGNG
>>127
俺は最初の方の人とは違うけど、

generic
 型に依存しない操作

generative
 コンパイル時にポリシーを与えて、コードを動的に生成する

ってイメージがあるな。STL だと algorithm は generic だけど、container なんか
は generative っぽい気がする。
0129デフォルトの名無しさんNGNG
>>106
置き換えられないことを説明するのに疲れたよ
>>84あたり読んでくれ
>>107
自分で言うのがまさに再起的でこのスレにぴったりだな。思われ君よ。
0130デフォルトの名無しさんNGNG
>>129
> 置き換えられないことを説明するのに疲れたよ
もう説明しなくていいって。書くことは一通り書いたんだから、後は読んだやつが
各自で判断すればいいだろ?
0131デフォルトの名無しさんNGNG
>>130
レス早くて怖いよ!
あと>>86長すぎだよ!
もっと話そうよ友達になれそうだ
0132デフォルトの名無しさんNGNG
>>131
構って欲しければ、馴れ合い系の板に逝けよ(w
0133デフォルトの名無しさんNGNG
>>132
そういった時点で呉越同舟だよ!!ワラ
0134デフォルトの名無しさんNGNG
scheme読んでて思ったんだが
(自分はgenerativeプログラミングは
staticプログラミングとでも呼んだ方がいいと思う)
factorialとかsumとかpowとか書いてると
これらをさらにgeneralizeして
マクロにする。Modern..本のTYPELISTみたく。
こんなことやってるライブラリはないんだろうかね。
intのリストは全部staticに処理できるのではないかと。
あまり役には立たないだろうけれども。
0135デフォルトの名無しさんNGNG
>>129
ヲイヲイ、>>84のいったいどこが実例なんだYO!
0136107 (!= 106)NGNG
>>135
だから、放っておいてあげなよ。アレで本人は満足なんだから。
0137デフォルトの名無しさんNGNG
VC.NETのtemplateはまじでどうなったのかな。
たのむよ!
0138デフォルトの名無しさんNGNG
>>114
tick-C
実行時にコード生成できるように拡張したC。
処理を実行時まで遅らせるようにコードをマークする記法と、
遅らせた中の一部をコンパイル時に実行できるようにマークする記法を組み込んだ
2レベル言語になっている。

http://www.pdos.lcs.mit.edu/tickc/

テンプレート方式のコード生成と呼ばれる技法で実装されている。
0139デフォルトの名無しさんNGNG
>>128
genericな関数の定義を効率よく実装する方法の一つが
パラメータ毎に展開してコード生成すること。
templateを利用したgenerativeテクニックはそのコード生成機能を逆手に取って
実現されている。

ちなみにJavaに導入されるtemplateは実行時に処理されるらしいので、
ここで話題になったようなコード生成テクニックには利用できない。

まぁ、Javaの場合、
コード生成素直にダイナミック・ロードでなんとかしろってことなんでしょうか?
0140デフォルトの名無しさんNGNG
 保守age
0141デフォルトの名無しさんNGNG
Modern C++ Design買ったはいいけどまだぜんぜん読んでない。
0142 NGNG
>141
0143デフォルトの名無しさんNGNG
久しぶりにあげてみる
0144デフォルトの名無しさんNGNG
Modern C++ Design
amazon注文age
0145デフォルトの名無しさんNGNG
スレタイが際立ってるな。
0146デフォルトの名無しさんNGNG
age
0147デフォルトの名無しさんNGNG
>>146
ageてばかりだと、そのうち
ageばっかりになるぞ
なんかしゃべれ
0148(ΦωΦ)フフフ・・・NGNG
(ΦωΦ)フフフ・・・
0149(Φ∀Φ)フフフ・・・ NGNG
(Φ∀Φ)フフフ・・・
0150デフォルトの名無しさんkNGNG
買ってきた。明日の朝9時までに3章までは毒派する予定。
0151デフォルトの名無しさんNGNG
この本、期待してたほどにはカルチャーショック受けなかった。
なんつーか、何かにつけてめんどくさいね。
0152デフォルトの名無しさんNGNG
>>151
それが C++ の限界。
もうパズルだよな。

このスレは generic programing と generative programming が
混じってるので混乱する。
URL 紹介
http://www.generative-programming.org/
0153デフォルトの名無しさんkNGNG
これに書かれてる内容のようなことはMLやHaskellだったら
もっとスマートに出来るの?
0154デフォルトの名無しさんNGNG
>>151
haskellはともかく、MLはこういうことに関してはすんごいよ
0155デフォルトの名無しさんNGNG
>>154
Haskell はダメなの?
0156デフォルトの名無しさんNGNG
>>154
HaskellやMLで出来ない技が多いよ。

たしかに、この本の中に出てくるFunctorは
関数型言語では高階関数(カリー化)というものと、とても似ています。

しかしC++のテンプレートは、ソースを実際にマクロのように展開しています。
こういうマクロのように展開することを関数型言語ではα簡約といっているらしいですが。
こういう機能はLispとSchemaにはありますが、MLやHaskellでは無いです。

本質を見極めた上で書きましょう。
0157デフォルトの名無しさんNGNG
マクロ展開できることは本質的なことなんですか?
0158デフォルトの名無しさんNGNG
>>157
C++にとっては本質的
0159デフォルトの名無しさんNGNG
正直、Cのマクロを多少強化すれば解決する問題が多い気がするんだけど
0160デフォルトの名無しさんNGNG
>>159
「多少強化」がやろうとすると多少の強化では済まないことも多いからなぁ。
タイプ・チェックも計算能力も。
0161デフォルトの名無しさんNGNG
Lispに追いつこうと頑張るのは凄いけど、
> > >と最後の閉じカッコがなんともまぬけでイイ(w
0162156NGNG
<<157
何時、評価&簡約されるかということ。
α変換(C++で言えばプリプロセッサによるマクロの展開、テンプレートの展開)はコンパイルされるとき展開、簡約されますね。
β変換(実行時に引数を渡すこと)は、実行時に評価、簡約されます。
何時評価されるかって結構だよね。

訂正:α簡約なんていう言葉は無いです。α変換の間違いです。
漏れも逝きます。
0163λ中将NGNG
# α簡約と言わないことも無いと思う。。。
0164デフォルトの名無しさんNGNG
誰か下の二冊を読んだ人がいたら感想聞かせてほすぃ

【Generative and Component-based Software Engineering】
http://www.amazon.co.jp/exec/obidos/ASIN/3540411720/

【Generative Programming: Methods, Tools, and Applications】
http://www.amazon.co.jp/exec/obidos/ASIN/0201309777/
0165デフォルトの名無しさんNGNG
http://www.moderncppdesign.com/
0166デフォルトの名無しさんNGNG
>> 【Generative and Component-based Software Engineering】
かなり抽象度高くて眠くなる。 C++ で Lisp ごっこをやる章は楽しかったけど。
学術的な雰囲気の強い本なので、そういう素養がないとつらいとおもう。
(OOPSLA の論文読んで理解できるレベルなら十分。)
0167デフォルトの名無しさんNGNG
age
0168デフォルトの名無しさんNGNG
これからlokiみたいなライブラリが増産されていくのかと思うと、
楽しみと思う反面、地獄の予感もしたりする、、
0169デフォルトの名無しさんNGNG
だれか、>>53みたいなやつで、LOG書いてくれ。
0170デフォルトの名無しさんNGNG
>>162-163
β変換がβ簡約とも言われるのは適用されるたびにλ項が解消されて減っていくから。

(ある種のλ式ではβ変換を有限回適用することで簡約順序に関わらずそれ以上簡約できない
「標準形」になることがわかっている。無限回簡約できるようなλ式、
またその中でも評価順序によっては有限回でそれ以上簡約できなくなるようなλ式もある。)

α変換は名前の付け替え変換だから式の形自身は変わらないので、
無限回繰り返すこともできるが、
同一視することによって無視する(α合同関係)ことが多い。

というわけで、α簡約とはやっぱりあまり言わないかも。

まー、マクロ展開にせよテンプレートの展開にせよ
単純なλ計算そのものではない。

例えば、プリプロセサマクロの名前付け替えは、
付け替え後の名前が付け替え対象の名前になるような関係による
循環を避ければ有限回で終了する。

それでも敢えて喩えて言えば、
プリプロセッサのマクロ展開だからα変換とも限らず、
引数つきマクロなどはβ変換といってもいいかもしれない。
0171170NGNG
肝心なことを書き忘れた。
>>170
つまり標準形のあるλ式(計算が終了する)であるならば、
λ項はβ変換適用ごとに減っていくので「簡約」なわけです。
通常、計算は終了することに意味があるとされるので、逆に
β変換が「簡約」であるようなλ式を「正しい」プログラムの表現
と見るわけです。

ついでに言えば、現実のプログラムでは評価順序も決まってるから、
その評価順序において簡約し切れるような式であれば良いわけで、
標準形のあるλ式以外にも、特定の簡約順序によって
有限回で簡約不能な式(値)になるような式も
条件付で認めるが立場あり、実はプログラムの基礎理論としては主流です。
0172デフォルトの名無しさんNGNG
>>171=170
わかったから。
そいうことは関数型言語板かLispShcema板でやって
お願い
0173デフォルトの名無しさんNGNG
>>172
ModernC++Design読むと逆にSchemeとかMLやってみたくならねぇ?
これから10年後のC++のプログラムとか、今のクラスライブラリの
惨状から想像するとぞっとするんだけど。
0174デフォルトの名無しさんNGNG
>>172
この本のやってることってtemplateでどこまでconst演算できるか?
ってのもあるからあながち無駄でもないかも。
■ このスレッドは過去ログ倉庫に格納されています