Menu
Coddy logo textTech

関数テンプレート

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 64/104。

2つの integers の maximum を find する function を書いていると、double に対しても、さらに string に対しても same のロジックが必要だと気づく場面を想像してください。テンプレートがなければ、それぞれの型に対してほぼ同一の function を書くことになります。Function templates は、ロジックを一度だけ書き、コンパイラーに型固有のバージョンを自動的に生成させることで、この問題を解決します。

関数テンプレートでは、templateキーワードの後に山括弧で囲んだテンプレートパラメーターを使用します。

template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    std::cout << maximum(5, 3) << std::endl;       // int版を使用
    std::cout << maximum(3.14, 2.71) << std::endl; // double版を使用
    std::cout << maximum('a', 'z') << std::endl;   // char版を使用
}

コンパイラは各呼び出しを検査し、その特定の型に対する具体的な function を生成します。このプロセスはテンプレートのインスタンス化と呼ばれます。必要に応じて、型を明示的に指定することもできます。

std::cout << maximum<double>(5, 3.14) << std::endl;  // double バージョンを強制する

テンプレートには複数の型パラメータを指定できるため、さらに柔軟な設計が可能です。

template <typename T, typename U>
void printPair(T first, U second) {
    std::cout << first << ", " << second << std::endl;
}

printPair(42, "hello");    // T=int, U=const char*
printPair(3.14, 100);      // T=double, U=int

function テンプレートはコンパイル時ポリモーフィズムを提供します。型は実行時ではなく、コードのコンパイル時に決定されます。つまり、仮想関数と比較して実行時のオーバーヘッドがゼロになるため、テンプレートはパフォーマンスが重要な汎用コードに最適です。

challenge icon

チャレンジ

簡単

関数テンプレートを使用して、互換性のある任意の型で動作する再利用可能な操作を作成するユーティリティツールキットを構築しましょう。ジェネリック関数をヘッダーファイルに整理し、メインプログラムでその柔軟性を示します。

2つのファイルを作成します。

  • MathUtils.h: 一般的な操作を実行する関数テンプレートのコレクションをDefineします。

    minimum: 同じ型の2つの値を受け取り、smaller方を返すテンプレート関数です。

    clamp: 3つのparameters、つまり値、low bound、high boundを受け取るテンプレート関数です。bound内にconstrainedされた値を返します(valueがlow未満の場合はlow、highより大きい場合はhigh、それ以外の場合はvalue自体をReturnsします)。

    swapValues: 同じ型の2つのreferencesを受け取り、それらの値をexchangesするテンプレート関数です。

  • main.cpp: 6つのinput(それぞれ別の行)をReadします。

    1. first integer
    2. second integer
    3. clampするdouble値
    4. low bound(double)
    5. high bound(double)
    6. character

    次の操作を行って、テンプレートを実演します。

    1. 2つのintegersのminimumをfindし、次のようにprintします: Min of <a> and <b>: <result>
    2. character 'm'とinput characterのminimumをfindし、次のようにprintします: Min of m and <char>: <result>
    3. double値をclampし、次のようにprintします: Clamp <value> to [<low>, <high>]: <result>
    4. first integerをrange [0, 100]にclampし、次のようにprintします: Clamp <value> to [0, 100]: <result>
    5. 2つのintegersをswapし、次のようにprintします: After swapValues: <a>, <b>

たとえば、inputが25103.71.05.0zの場合:

Min of 25 and 10: 10
Min of m and z: m
Clamp 3.7 to [1, 5]: 3.7
Clamp 25 to [0, 100]: 25
After swapValues: 10, 25

各functionテンプレートがintegers、doubles、charactersでシームレスに動作することに注目してください。compilerは、使用する各型に適切なversionを生成します。swapValues functionはreferencesを通じてoriginal variablesを変更する必要があります。これは、テンプレートが通常のfunctionsと同様にreference parametersでも動作することを示しています。

自分で試してみよう

#include <iostream>
#include "MathUtils.h"
using namespace std;

int main() {
    // 入力を読み取る
    int a, b;
    double value, low, high;
    char ch;
    
    cin >> a;
    cin >> b;
    cin >> value;
    cin >> low;
    cin >> high;
    cin >> ch;
    
    // TODO: minimumテンプレートを使用して2つの整数の最小値を求める
    // 出力: "Min of <a> and <b>: <result>"
    
    // TODO: minimumテンプレートを使用して'm'と入力文字の最小値を求める
    // 出力: "Min of m and <char>: <result>"
    
    // TODO: clampテンプレートをdoubleの値に使用する
    // 出力: "Clamp <value> to [<low>, <high>]: <result>"
    
    // TODO: clampテンプレートを最初の整数に範囲[0, 100]で使用する
    // 出力: "Clamp <value> to [0, 100]: <result>"
    
    // TODO: swapValuesテンプレートを2つの整数に使用する
    // Print: "After swapValues: <a>, <b>"
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ