「Cpp テンプレート」の版間の差分

提供:yonewiki
(ページの作成:「C++に戻る <table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> <tr> <td style="width:1px;"></td> <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++ テンプレート</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td>…」)
 
 
(同じ利用者による、間の2版が非表示)
11行目: 11行目:
<br />
<br />
== '''テンプレート''' ==
== '''テンプレート''' ==
 テンプレートは、型定義を伴って宣言する各種関数や、各種クラスにおいて、型を柔軟に入れ替えて、いくつもの関数を形に変身できる機能と言えます。型が少し違うだけでなんども同じ定義を記述するのは面倒であるという部分を補うための仕組みです。


=== '''関数テンプレート''' ===
 関数テンプレートは以下のように定義します。TYPENAMEに任意の型が割り当てられると想定して考えると良いでしょう。Function_Nameとvalue1とvalue2は好きな名前つまり任意の名前で扱えます。
<syntaxhighlight lang="cpp">
template <typename TYPENAME>
TYPENAME Function_Name(const TYPENAME& value1, const TYPENAME& value2) {
  …
}
</syntaxhighlight>
 具体的に使うときは
<syntaxhighlight lang="cpp">
    // int型の場合
    int intValue1 = 5;
    int intValue2 = 8;
    int minIntValue = minValue(intValue1, intValue2);
</syntaxhighlight>
 のように型を取り決めて使うことができます。クラスのテンプレートの場合はちょっと違いますが、標準関数でもテンプレートで定義されているモノがあり、この項目では詳しい説明はせず、少し後で詳しく説明しますが、std::pair<int, int>のようにしてテンプレートを使います。もちろんここのintを更にテンプレートにして定義することができますので、このあとの実用サンプルでは、ちょっと活用したものをチラ見せしておきます。
 以下に、簡単な関数テンプレートを使用したサンプルプログラムを示します。このプログラムでは、2つの値を比較し、小さい方の値を返す関数テンプレート minValue を定義します。また、比較結果を出力するために << 演算子をオーバーロードします。
<syntaxhighlight lang="cpp">
#include <iostream>
// 関数テンプレートの定義
template <typename T>
T minValue(const T& value1, const T& value2) {
    return (value1 < value2) ? value1 : value2;
}
// << 演算子のオーバーロード
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values) {
    return os << "[" << values.first << ", " << values.second << "]";
}
int main() {
    // int型の場合
    int intValue1 = 5;
    int intValue2 = 8;
    int minIntValue = minValue(intValue1, intValue2);
    std::cout << "Minimum value of " << intValue1 << " and " << intValue2 << " is: " << minIntValue << std::endl;
    // double型の場合
    double doubleValue1 = 3.14;
    double doubleValue2 = 2.71;
    double minDoubleValue = minValue(doubleValue1, doubleValue2);
    std::cout << "Minimum value of " << doubleValue1 << " and " << doubleValue2 << " is: " << minDoubleValue << std::endl;
    // std::pair<int, int>型の場合
    std::pair<int, int> pairValues = std::make_pair(10, 7);
    std::cout << "Pair values: " << pairValues << std::endl;
    return 0;
}
</syntaxhighlight>
'''1.関数テンプレート minValue の説明:'''
template <typename T>: 関数テンプレートの宣言で、ジェネリックな型 T を導入します。
T minValue(const T& value1, const T& value2): 2つの引数を受け取り、小さい方の値を返す関数です。引数と戻り値の型には T を使用しています。
'''2.<< 演算子のオーバーロードの説明:'''
template <typename T>: 演算子のオーバーロードもテンプレートとして宣言します。
std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values): << 演算子のオーバーロードで、std::pair<T, T> 型のオブジェクトを受け取り、適切な形式で出力ストリームに挿入します。
'''3.main 関数の説明:'''
minValue 関数が、int 型と double 型の2つの異なる型で呼び出されています。
<< 演算子のオーバーロードが、std::pair<int, int> 型のオブジェクトに対して使用されています。
 
=== '''クラステンプレート''' ===
 クラスのテンプレートは以下のような記述形式で定義します。
<syntaxhighlight lang="cpp">
template <class TYPENAME>
class Class_Name {
}
</syntaxhighlight>
 のようにしてTYPENAMEに任意の型名を受け取ることを想定したクラス定義したテンプレートになります。
 そして利用するときに、int型で定義したい場合は
<syntaxhighlight lang="cpp">
Class_Name<int> intPair(10, 20 /*コンストラクタ引数群*/);
</syntaxhighlight>
 のようにします。
 ここからは、サンプルプログラムをまず示して、それについて説明します。ここでは T が任意の型を当てはめることを想定した型名変数に相当します。
<syntaxhighlight lang="cpp">
#include <iostream>
// テンプレートを使用したジェネリックなPairクラスの定義
template <class T>
class Pair {
private:
    T first;
    T second;
public:
    // コンストラクタ: デフォルト引数を使用して初期化
    Pair(const T& initFirst = T(), const T& initSecond = T())
        : first(initFirst), second(initSecond) {}
    // 1番目の要素を返すメソッド
    T getFirst() const {
        return first;
    }
    // 2番目の要素を返すメソッド
    T getSecond() const {
        return second;
    }
    // 1番目の要素への参照を返すメソッド
    T& refFirst() {
        return first;
    }
    // 2番目の要素への参照を返すメソッド
    T& refSecond() {
        return second;
    }
    // 演算子のオーバーロード: Pairオブジェクトの表示
    friend std::ostream& operator<<(std::ostream& os, const Pair<T>& pair) {
        return os << "[" << pair.getFirst() << ", " << pair.getSecond() << "]";
    }
};
int main() {
    // int型のPairオブジェクトを生成
    Pair<int> intPair(10, 20);
    // 値の表示
    std::cout << "Pair of integers: " << intPair << std::endl;
    // 1番目の要素への変更
    intPair.refFirst() = 30;
    // 変更後の値を表示
    std::cout << "Modified pair: " << intPair << std::endl;
    return 0;
}
</syntaxhighlight>
'''1.テンプレートを使用したジェネリックなPairクラス:'''
Pairクラスはテンプレートを使用しており、Tは任意の型を表します。これにより、異なる型のデータを格納することができます。
'''2.デフォルト引数を使用したコンストラクタ:'''
コンストラクタはデフォルト引数を使用して初期化を行います。これにより、引数を省略した場合にはデフォルト値が使用されます。
'''3.メソッドの説明:'''
getFirstおよびgetSecondメソッドは、それぞれ1番目と2番目の要素を取得します。
refFirstおよびrefSecondメソッドは、それぞれ1番目と2番目の要素への参照を返します。
'''4.演算子のオーバーロード:'''
operator<<関数は、Pairオブジェクトを出力ストリームに挿入するための演算子のオーバーロードです。これにより、std::cout << intPairといった形で直接表示できます。
'''5.main関数:'''
Pair<int>型のオブジェクトを生成し、その値を表示します。後に1番目の要素を変更して再び表示します。
 
=== '''演算子のオーバーロードテンプレート''' ===
 チラ見せした通り、演算子をオーバーロードするときにテンプレートを使うこともできます。
<syntaxhighlight lang="cpp">
#include <iostream>
// << 演算子のオーバーロード
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values) {
    return os << "[" << values.first << ", " << values.second << "]";
}
</syntaxhighlight>
 上記のように使います。関数テンプレートの延長線上にある使い方です。演算子のオーバーロードと、標準テンプレートライブラリSTL(Standard Template Library)を理解していれば、スッと理解できるものです。
 


[[C PlusPlus#C++からの技術|C++]]に戻る
[[C PlusPlus#C++からの技術|C++]]に戻る

2024年2月27日 (火) 20:19時点における最新版

C++に戻る


本来の表記は「C++ テンプレート」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC++にのみ存在する機能として、記事タイトルがC++ テンプレートになっています。

テンプレート

 テンプレートは、型定義を伴って宣言する各種関数や、各種クラスにおいて、型を柔軟に入れ替えて、いくつもの関数を形に変身できる機能と言えます。型が少し違うだけでなんども同じ定義を記述するのは面倒であるという部分を補うための仕組みです。

関数テンプレート

 関数テンプレートは以下のように定義します。TYPENAMEに任意の型が割り当てられると想定して考えると良いでしょう。Function_Nameとvalue1とvalue2は好きな名前つまり任意の名前で扱えます。


template <typename TYPENAME>
TYPENAME Function_Name(const TYPENAME& value1, const TYPENAME& value2) {
  
}


 具体的に使うときは


    // int型の場合
    int intValue1 = 5;
    int intValue2 = 8;
    int minIntValue = minValue(intValue1, intValue2);


 のように型を取り決めて使うことができます。クラスのテンプレートの場合はちょっと違いますが、標準関数でもテンプレートで定義されているモノがあり、この項目では詳しい説明はせず、少し後で詳しく説明しますが、std::pair<int, int>のようにしてテンプレートを使います。もちろんここのintを更にテンプレートにして定義することができますので、このあとの実用サンプルでは、ちょっと活用したものをチラ見せしておきます。


 以下に、簡単な関数テンプレートを使用したサンプルプログラムを示します。このプログラムでは、2つの値を比較し、小さい方の値を返す関数テンプレート minValue を定義します。また、比較結果を出力するために << 演算子をオーバーロードします。


#include <iostream>

// 関数テンプレートの定義
template <typename T>
T minValue(const T& value1, const T& value2) {
    return (value1 < value2) ? value1 : value2;
}

// << 演算子のオーバーロード
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values) {
    return os << "[" << values.first << ", " << values.second << "]";
}

int main() {
    // int型の場合
    int intValue1 = 5;
    int intValue2 = 8;
    int minIntValue = minValue(intValue1, intValue2);

    std::cout << "Minimum value of " << intValue1 << " and " << intValue2 << " is: " << minIntValue << std::endl;

    // double型の場合
    double doubleValue1 = 3.14;
    double doubleValue2 = 2.71;
    double minDoubleValue = minValue(doubleValue1, doubleValue2);

    std::cout << "Minimum value of " << doubleValue1 << " and " << doubleValue2 << " is: " << minDoubleValue << std::endl;

    // std::pair<int, int>型の場合
    std::pair<int, int> pairValues = std::make_pair(10, 7);
    std::cout << "Pair values: " << pairValues << std::endl;

    return 0;
}


1.関数テンプレート minValue の説明:

template <typename T>: 関数テンプレートの宣言で、ジェネリックな型 T を導入します。 T minValue(const T& value1, const T& value2): 2つの引数を受け取り、小さい方の値を返す関数です。引数と戻り値の型には T を使用しています。


2.<< 演算子のオーバーロードの説明:

template <typename T>: 演算子のオーバーロードもテンプレートとして宣言します。 std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values): << 演算子のオーバーロードで、std::pair<T, T> 型のオブジェクトを受け取り、適切な形式で出力ストリームに挿入します。


3.main 関数の説明:

minValue 関数が、int 型と double 型の2つの異なる型で呼び出されています。 << 演算子のオーバーロードが、std::pair<int, int> 型のオブジェクトに対して使用されています。

 

クラステンプレート

 クラスのテンプレートは以下のような記述形式で定義します。


template <class TYPENAME>
class Class_Name {

}


 のようにしてTYPENAMEに任意の型名を受け取ることを想定したクラス定義したテンプレートになります。


 そして利用するときに、int型で定義したい場合は


Class_Name<int> intPair(10, 20 /*コンストラクタ引数群*/);


 のようにします。


 ここからは、サンプルプログラムをまず示して、それについて説明します。ここでは T が任意の型を当てはめることを想定した型名変数に相当します。


#include <iostream>

// テンプレートを使用したジェネリックなPairクラスの定義
template <class T>
class Pair {
private:
    T first;
    T second;

public:
    // コンストラクタ: デフォルト引数を使用して初期化
    Pair(const T& initFirst = T(), const T& initSecond = T())
        : first(initFirst), second(initSecond) {}

    // 1番目の要素を返すメソッド
    T getFirst() const {
        return first;
    }

    // 2番目の要素を返すメソッド
    T getSecond() const {
        return second;
    }

    // 1番目の要素への参照を返すメソッド
    T& refFirst() {
        return first;
    }

    // 2番目の要素への参照を返すメソッド
    T& refSecond() {
        return second;
    }

    // 演算子のオーバーロード: Pairオブジェクトの表示
    friend std::ostream& operator<<(std::ostream& os, const Pair<T>& pair) {
        return os << "[" << pair.getFirst() << ", " << pair.getSecond() << "]";
    }
};

int main() {
    // int型のPairオブジェクトを生成
    Pair<int> intPair(10, 20);

    // 値の表示
    std::cout << "Pair of integers: " << intPair << std::endl;

    // 1番目の要素への変更
    intPair.refFirst() = 30;

    // 変更後の値を表示
    std::cout << "Modified pair: " << intPair << std::endl;

    return 0;
}


1.テンプレートを使用したジェネリックなPairクラス:

Pairクラスはテンプレートを使用しており、Tは任意の型を表します。これにより、異なる型のデータを格納することができます。


2.デフォルト引数を使用したコンストラクタ:

コンストラクタはデフォルト引数を使用して初期化を行います。これにより、引数を省略した場合にはデフォルト値が使用されます。


3.メソッドの説明:

getFirstおよびgetSecondメソッドは、それぞれ1番目と2番目の要素を取得します。 refFirstおよびrefSecondメソッドは、それぞれ1番目と2番目の要素への参照を返します。


4.演算子のオーバーロード:

operator<<関数は、Pairオブジェクトを出力ストリームに挿入するための演算子のオーバーロードです。これにより、std::cout << intPairといった形で直接表示できます。


5.main関数:

Pair<int>型のオブジェクトを生成し、その値を表示します。後に1番目の要素を変更して再び表示します。

 

演算子のオーバーロードテンプレート

 チラ見せした通り、演算子をオーバーロードするときにテンプレートを使うこともできます。


#include <iostream>

// << 演算子のオーバーロード
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::pair<T, T>& values) {
    return os << "[" << values.first << ", " << values.second << "]";
}


 上記のように使います。関数テンプレートの延長線上にある使い方です。演算子のオーバーロードと、標準テンプレートライブラリSTL(Standard Template Library)を理解していれば、スッと理解できるものです。

 

C++に戻る