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と……と、比較話をやっちまうわけですが。