D言語の欠陥
D言語は、なんと関数の引数に構造体を渡せません!!
以下のようなコードを実行してみましょう
struct X{} template id(X x){const id = x;} const x = id!(X.init);
上のようにid関数の引数を構造体にしてインタプリタを起動してみましょう。
インタプリタの使い方とかはid:niha:20070103とか参照
Error: arithmetic/string type expected for value-parameter, not X
数と文字列以外を値渡しするなとインタプリタ様がブチ切れたようです。
さて、どうすればいいでしょうか?
実はこれを解決する手段は沢山存在します。
まず昔から使われていて有名なのは型を実行時に渡すようにすることです。
struct Point{int x,y;} template id(X,X x){const id = x;} const Point v = {20,30}; const x = id!(Point,v);
このように型を実行時に引数として渡すことでエラーを回避できます。
しかし、これは型を書かないといけないという凄く重大な欠陥があります。
私のような超めんどくさがりにはこんなもの出来ません。
あと、どうみても実装の穴を突いてる感が漂います。
ちなみに、この手のアプローチとしてもうひとつ有名なのはtypedefを使うのがあります。
struct Point{int x,y;} template id(X){const id = X.init;} typedef Point v = {20,30}; const x = id!(v);
このようにtypedef修飾した変数に値をセットすることでinitで取り出せるようになります。
なお余談ですがD言語では
const int hoge1 = 0;//OK auto int hoge2 = 0;//OK static int hoge3 = 0;//OK typedef int hoge4 = 0;//OK const hoge5 = 0;//OK auto hoge6 = 0;//OK static hoge7 = 0;//OK typedef hoge8 = 0;//NG (°Д°)ハァ?
とtypedef変数だけは型推論が出来ません。Walterたんの実装忘れの可能性が高いです。
とまぁ、書きましたが、実はこのコードはdmd 1.00で実行すると何故かインタプリタが異常終了しました。
D言語は関数周りの実装は怪しいのです。
そのため一見正しく見えても動かないことが多々あります。諦めましょう。
ああ、そうそう。
Dでは構造体の値渡しは出来ませんが参照渡しなら出来ます。
struct Point{int x,y;} template id(alias X){const id = X;} const Point v = {0,20}; const x = id!(v);
こうすればいいわけです。
しかし、こうするとintの即値のようにアドレスを取れない値を渡せません。
id!(20) ; // ERROR!
このように参照渡しは値を直接関数に渡すことが出来ません。
C++で
f(int&); ... f(0);
が怒られるのと同じですね。
さて、以上のような値渡しすら満足に出来ない状態が長らく続いていたわけです。
このように関数の引数に構造体を渡せないため、
intやdoubleなどのプリミティブな値に分解して扱うのがD言語プログラミングの基本でした。
しかし、tupleが導入されてからこの問題は解決しました!!
struct Point{int x,y;} template id(X...){const id = X[0];} const Point p = {0,0}; const x = id!(p); // OK! const y = id!(0); // OK!!!