本文へスキップ
BecomeCoder

C++コース · 第13章 テンプレート ― 型に依存しないコード · レッスン54

クラステンプレート ― 型に依存しない型

ブラウザで完結

導入

関数だけでなく、クラスもテンプレートにできます。vector<int>vector<string> のように「どんな型でも入れられる入れ物」を、自分で作れるということです。

説明

クラスの前に template <typename T> を付け、メンバの型に T を使います。使うときは クラス名<型> と、入れる型を指定します。

#include <iostream>
using namespace std;

template <typename T>
class Box {
    T value;
public:
    Box(T v) : value(v) {}
    T get() const { return value; }
    void set(T v) { value = v; }
};

int main() {
    Box<int> a(10);          // int を入れる箱
    Box<string> b("hello");  // string を入れる箱
    cout << a.get() << endl;   // 10
    cout << b.get() << endl;   // hello
    return 0;
}

メンバ関数の定義をクラスの外に書くときは、少し記法が増えます。関数の頭にも template <typename T> を付け、Box<T>:: と書きます。

#include <iostream>
using namespace std;

template <typename T>
class Stack {
    T items[100];
    int count = 0;
public:
    void push(T x);
    T pop();
    bool empty() const { return count == 0; }
};

template <typename T>            // 外部定義にもテンプレート宣言が要る
void Stack<T>::push(T x) { items[count++] = x; }

template <typename T>
T Stack<T>::pop() { return items[--count]; }

int main() {
    Stack<int> s;
    s.push(1); s.push(2); s.push(3);
    cout << s.pop() << " " << s.pop() << endl;  // 3 2(後入れ先出し)
    return 0;
}

まとめ

template <typename T> をクラスに付けると、型を差し替えられる「入れ物」を作れます。使うときは Box<int> のように型を指定します。vectormap などの STL コンテナは、まさにこの仕組みで作られています。

実際に動かしてみよう

下のエディタにC++を書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のC++コンパイラ(clang + libc++)がその場でコンパイルして実行し、出力が表示されます。std::string・vector・クラス・テンプレート・STL などモダンC++がそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(cin)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。