コンテンツにスキップ

ジェネリックプログラミング

出典: フリー百科事典『ウィキペディア(Wikipedia)』

: generic programming

[]


[1]1970CLUAdaBETAC++DEiffelJavaDECTrellis/Owl (object-based)  (object-oriented) 

1995[][?]AdaEiffelJavaC#C++ (parameterized types) 使

[]




CPascal使C++

C++
template<typename T>
class LinkedList {
public:
    // 双方向連結リストのノード。
    class Node {
        friend class LinkedList;
    public:
        T value;
    private:
        Node* prev;
        Node* next;
    private:
        Node() : value(), prev(), next() {}
        explicit Node(const T& value, Node* prev = NULL, Node* next = NULL) : value(value), prev(prev), next(next) {}
        ~Node() {}
    public:
        Node* getPrev() { return this->prev; }
        Node* getNext() { return this->next; }
    };
private:
    Node dummy;
public:
    LinkedList() : dummy() {
        this->dummy.prev = &this->dummy;
        this->dummy.next = &this->dummy;
    }
    ~LinkedList() { this->clear(); }
    size_t getSize() const { /* ... */ }
    Node* getHead() { return this->dummy.next; }
    Node* getTail() { return this->dummy.prev; }
    Node* getSentinel() { return &this->dummy; }
    static Node* insertBefore(Node* node, const T& value) {
        assert(node);
        assert(node->prev);
        Node* temp = new Node(value, node->prev, node);
        node->prev->next = temp;
        node->prev = temp;
        return temp;
    }
    static Node* insertAfter(Node* node, const T& value) {
        assert(node);
        assert(node->next);
        Node* temp = new Node(value, node, node->next);
        node->next->prev = temp;
        node->next = temp;
        return temp;
    }
    static void remove(Node*& node) {
        assert(node);
        if (node->prev) { node->prev->next = node->next; }
        if (node->next) { node->next->prev = node->prev; }
        delete node;
        node = NULL;
    }
    void clear() {
        for (Node* current = this->getHead(); current != this->getSentinel(); ) {
            Node* temp = current;
            current = current->next;
            delete temp;
        }
        this->dummy.prev = &this->dummy;
        this->dummy.next = &this->dummy;
    }
};

LinkedList<int> list_of_integers;
LinkedList<Animal> list_of_animals;
LinkedList<Car> list_of_cars;

Ttypename TTTT (generics)  (constraint) T[]

[2]


template<typename T>
void Swap(T& a, T& b) // "&"により参照としてパラメーターを渡している。
{
    T temp = b;
    b = a;
    a = temp;
}

using namespace std;
string s1 = "world!", s2 = "Hello, ";
Swap(s1, s2);
cout << s1 << s2 << endl; // 出力は"Hello, world!"

使C++templateDC++JavaJ2SE 5.0C++T

C# 2.0Visual Basic .NET 2005 (VB 8.0) Microsoft .NET Framework 2.0ML (parametric polymorphism) Haskell

Objective-C使[]使JavaJavaListObject

Ada[]


Ada1977-1980 (generics) Ada20051998C++Standard Template Library (STL) 

 (generic unit) 0 (generic formal parameters) 

 (discrete) 


Ada[]



generic
   Max_Size : Natural; -- 汎用体仮オブジェクトの例
   type Element_Type is private; -- 汎用体仮データ型の例;  この例では制限型でなければ任意のデータ型が該当
package Stacks is
   type Size_Type is range 0 .. Max_Size;
   type Stack is limited private;
   procedure Create (S : out Stack;
                     Initial_Size : in Size_Type := Max_Size);
   procedure Push (Into : in out Stack; Element : in Element_Type);
   procedure Pop (From : in out Stack; Element : out Element_Type);
   Overflow : exception;
   Underflow : exception;
private
   subtype Index_Type is Size_Type range 1 .. Max_Size;
   type Vector is array (Index_Type range <>) of Element_Type;
   type Stack (Allocated_Size : Size_Type := 0) is record
      Top : Index_Type;
      Storage : Vector (1 .. Allocated_Size);
   end record;
end Stacks;

汎用体パッケージのインスタンス化

type Bookmark_Type is new Natural;
-- 編集中のテキストドキュメント内の場所を記録する

package Bookmark_Stacks is new Stacks (Max_Size => 20,
                                       Element_Type => Bookmark_Type);
-- ドキュメント中の記録された場所にユーザがジャンプできるようにする

汎用体パッケージインスタンスの利用

type Document_Type is record
   Contents : Ada.Strings.Unbounded.Unbounded_String;
   Bookmarks : Bookmark_Stacks.Stack;
end record;

procedure Edit (Document_Name : in String) is
   Document : Document_Type;
begin
   -- ブックマークのスタックを初期化
   Bookmark_Stacks.Create (S => Document.Bookmarks, Initial_Size => 10);
   -- この時点でDocument_Nameファイルを開いたり、読み込んだりが可能
end Edit;

利点と制限[編集]


Ada
generic
   type Index_Type is (<>); -- 離散型(discrete type)のみを許容
   type Element_Type is private; -- 制限型(limited type)以外の任意データ型
   type Array_Type is array (Index_Type range <>) of Element_Type;

Array_TypeElement_TypeIndex_Type



C++Ada

 (shared generics) 
C++



WikibookGeneric formal objects





Ada

Max

C++[]


C++C++14C++JavaC#C++

C++Standard Template Library (STL) 

D[]


DC++C++DD

D< >( )使!( )使Da!(b)C++a<b>

Static-if[]


Dstatic ifC++#if#endifstatic if使C++DD
template Factorial(ulong n) {
    static if (n <= 1)
        const Factorial = 1u;
    else
        const Factorial = n * Factorial!(n - 1);
}

エイリアスパラメーター[編集]

D言語のテンプレートはまたエイリアスパラメーターを受け入れることができる。エイリアスパラメーターはC++のtypedefと似ているが、テンプレートパラメーターを置き換えることもできる。これは今後利用可能なC++0x仕様に追加されるであろう、C++のテンプレートのテンプレート引数にある機能の拡張版である。エイリアスパラメーターは、テンプレート、関数、型、その他のコンパイル時のシンボルを指定できる。これは例えばテンプレート関数の中に関数をプログラマーが挿入できるようにする。

template wrapper(alias Fn) {
    // "extern(C)"インターフェイスでD言語の関数をラップする
    extern(C) void wrapper() {
        Fn();
    }
}

この種のテンプレートはC言語APIとD言語のコードを接続するときに使いやすいだろう。仮想のC言語APIが関数ポインタを要求する場合、このようにテンプレートを利用できる。

void foo() {
    // ...
}

some_c_function(&wrapper!(foo));

Javaのジェネリクス[編集]


2004J2SE 5.0JavaC++Java1JavaList<Integer>List<int>

Java (type erasure) List<Integer>List

List<Integer>List<String>ListCollectionJavaCollections.checkedList(List<E>, Class<E>)Collection

C++C#JavaList<Map<Integer, String>>

[]


JavaJava使List<?>List<?>Objectnull

extends使List<? extends Number>NumbernullNumber

super使List<? super Number>List<Number>List<Object>NumberObject

[]


Javanew T[size];TJavaTTClass1java.lang.reflect.Array.newInstance(Class, int)使1Java<?>

Haskell[]


Haskell (parameterized types) (parametric polymorphism)JavaC++ (type classes) HaskellHaskell

Haskell6EqShow (derived instances) 

EqShow
data BinTree a = Leaf a | Node (BinTree a) a (Bintree a)
      deriving (Eq, Show)

TBinTree T (==)  (show) 

EqShow==show"" (type-indexed) Ralf Hinze (2004) HaskellHaskell

PolyP[]


PolyPHaskellPolyPpolytypicpolytypicPolyPHaskellt*  *att a

PolyP
   flatten :: Regular d => d a -> [a]
   flatten = cata fl
   
   polytypic fl :: f a [a] -> [a]
     case f of
       g+h -> either fl fl
       g*h -> \(x,y) -> fl x ++ fl y
       () -> \x -> []
       Par -> \x -> [x]
       Rec -> \x -> x
       d@g -> concat . flatten . pmap fl
       Con t -> \x -> []
   
   cata :: Regular d => (FunctorOf d a b ->b) -> d a ->b

Haskell[]


HaskellHaskell1

Type-indexed valuesHaskell使type-indexed values使1

type-indexed value

Kind-indexed types*k  kkind-indexed type



Generic abstraction

Type-indexed typestype-indexed types

Haskell
   type Eq {[ * ]} t1 t2 = t1 -> t2 -> Bool
   type Eq {[ k ->l]} t1 t2 = forall u1 u2. Eq {[k]} u1 u2 -> Eq {[l]} (t1 u1) (t2 u2)
   
   eq {| t :: k |} :: Eq {[k]} t t
   eq {| Unit |} _ _ = True
   eq {| :+: |} eqA eqB (Inl a1) (Inl a2) = eqA a1 a2
   eq {| :+: |} eqA eqB (Inr b1) (Inr b2) = eqB b1 b2
   eq {| :+: |} eqA eqB _ _ = False
   eq {| :*: |} eqA eqB (a1 :*: b1) (a2 :*: b2) = eqA a1 a2 && eqB b1 b2
   eq {| Int |} = (==)
   eq {| Char |} = (==)
   eq {| Bool |} = (==)

[]


 (Scrap your boilerplate approach) Haskell (Lämmel and Peyton Jones, 2003)HaskellGHC>=6.0使greadgshowgeq

C#.NET[]


C#.NET.NET Framework 2.0200511Java.NET

.NET

CLR
Java

JIT

JavaList<List<Dictionary<int, int>>>

C#.NETwhere使/

C# 4.0outin使
using System;
using System.Collections.Generic;

static int FirstIndexOfMax<T>(List<T> list) where T: IComparable<T>
{
    if (list.Count == 0) {
        return -1;
    }
    int index = -1;
    for (int i = 0; i < list.Count; ++i) {
        if ((index == -1 && list[i] != null) ||
            (index >= 0 && list[index] != null && list[i] != null && list[index].CompareTo(list[i]) < 0)) {
            index = i;
        }
    }
    return index;
}

FirstIndexOfMaxTIComparable<T>IComparable<T>CompareTo

C++/CLI.NETC++

[]


 (parameterized types)  (parametric polymorphism) MLOCamlAda

Verilog1[3]

脚注[編集]

  1. ^ Stanley B. Lippman. “Pure C++:Generic Programming Under .NET”. マイクロソフトMSDNマガジン. 2008年12月28日閲覧。[リンク切れ]
  2. ^ 統一モデリング言語 (UML) の用語では、それぞれ汎化 (generalization) および特化 (specialization) と呼ぶ。
  3. ^ Verilog by Example, Section The Rest for Reference. Blaine C. Readler, Full Arc Press, 2011. ISBN 978-0-9834973-0-1

関連項目[編集]