concept_map
C++0xの話を聞いてきました。
concept_mapという、Haskellのclassに対するinstanceで書くアダプタをusingで後から選択/交換可能というステキ機能が追加されるそうです。
仮に、++と*と比較演算子を要求するInputIteratorがあったとして、intに足りないのは*だけなのでこう書けるそうです。(以下ちょううろおぼえコード)
template <typename It> where InputIterator<It> void PrintAll(It begin, It end) { for(; begin != end; ++begin) cout << *begin; } concept_map InputIterator<int> { int operator * (int x){ return x; } } ... vector<int> x; PrintAll(x.begin(), x.end()); PrintAll(0, 5);
で、01234と出るのですが、concept_mapのところをreturn x * 2;にすると、02468になるそうです。
concept_mapの再選択用の構文は無いらしいですが、それぞれをnamespaceに閉じ込めておくことで、いつでもusingで好きな実装を引っ張り出してこれるというステキな代物。定義済みのものについても静的にオーバーライドできるそうです。
concept_map InputIterator<vector<int>::iterator> { int operator * (int vector<int>::iterator){ return *x * 2; } //このoperator *はwhere明記されたtemplate以外からは見えないので再帰はしないらしい }
で、まあ、よく考えたらAdaですと最初からいらないなあ……と。
generic type Element_Type(<>) is limited private; type Cursor is private; with function Element(Position : Cursor) return Element_Type is <>; with procedure Next(Position : in out Cursor) is <>; with function "<=" (Left, Right : Cursor) return Boolean is <>; with procedure Put (Item : Element_Type) is <>; procedure Generic_Print_All(First, Last : Cursor); procedure Generic_Print_All(First, Last : Cursor) is I : Cursor := First; begin while I <= Last loop Next (I); end loop; end Generic_Print_All;
があったとしましてまずはvector
package Ints is new Ada.Containers.Vectors(Positive, Integer); use Ints; procedure Print_All is new Generic_Print_All(Integer, Ints.Cursor);
test.adb:28:09: instantiation error at line 14 test.adb:28:09: no visible subprogram matches the specification for "<="
は?
なんか知らんけどVectorのCursorには比較演算子が無いそうです。
function "<=" (Left, Right : Ints.Cursor) return Boolean is begin return To_Index(Left) <= To_Index(Right); end "<=";
Ada.Containers制定者の意図を探すのは今度にして、今は↑を書き足して通します。
で、値2倍バージョンが欲しければ、operator *相当のElementを置き換えるわけですが、Adaの型はカプセル化されているわけではなく、メソッドも、適合するものが暗黙に探されているだけですので、明示的にこんな形で実体化できるという寸法です。
function Element_2(Position : Ints.Cursor) return Integer is begin return Element(Position) * 2; end Element_2; procedure Print_All_2 is new Generic_Print_All(Integer, Ints.Cursor, Element => Element_2);
つまり、メタプログラミング能力こそ無いけれど、元々の汎用プログラミングに関しては、Ada > C++ > Haskellと……と、比較話をやっちまうわけですが。