404 Not Found

404 Not Found


nginx

C++のテンプレート

[これまでのレッスンでは]、[私たちが作成した]関数[や]クラスは[いずれも][1つの]型しか処理できませんでした。

[しかし、もしあなたが]「intdoublestring [を処理できる] max 関数」[を書こうとするなら]?

テンプレート[はこの問題を解決する]――[関数]と[クラス]が[任意の]型をサポートできるようにする。


1. テンプレートとは何ですか?

(1) 1.1 [生活の中の]テンプレート*

[生活シーン] 番組[での対応]
[ケーキ型]([異なる味の生地を流し込める]) テンプレート
Word [差し込み印刷]([1つの]テンプレート、[異なる受信者を挿入]) テンプレート

テンプレートの本質: [コンパイラに][使用時の]型に基づいて、[対応するバージョンの]関数[または]クラスを[自動的に生成させる]こと

(2) 1.2 なぜテンプレートが必要なのか?

[不要]テンプレート([重複]コード):

CPP
#include iostream

// int max
int max(int a, int b) {
 return a > b ? a : b;
}

// double max
double max(double a, double b) {
 return a > b ? a : b;
}
// ... write N!

[用]テンプレート(コード[再利用]):

CPP
#include iostream

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

int main() {
 std::cout << max(3, 5) << std::endl; // int
 std::cout << max(3.14, 2.72) << std::endl; // double
 return 0;
}


2. functiontemplate*

(1) 2.1 [基本構文]*

CPP
template <typename >
 () {
 // ...
}

💡 [ポイント]: typename [は] class と書くこともできます([両者は同等]ですが)、typename を使うことをお勧めします([より直感的]だからです)。

▶ サンプル 1: functiontemplate (難易度 ⭐)

CPP
#include iostream

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

int main() {
 std::cout << "max(3, 5) = " << max(3, 5) << std::endl;
 std::cout << "max(3.14, 2.72) = " << max(3.14, 2.72) << std::endl;
 
 // ...
 std::cout << "maxint(3, 5) = " << maxint(3, 5) << std::endl;
 
 return 0;
}
▶ 試してみよう

出力:

TEXT
max(3, 5) = 5
max(3.14, 2.72) = 3.14
maxint(3, 5) = 5


3. クラステンプレート*

(1) 3.1 [基本構文]*

CPP
template <typename >
class {
 // ...
};

▶ サンプル 2: クラステンプレート Pair (難易度 ⭐⭐)

CPP
#include iostream
#include string

//:
template <typename T1, typename T2>
class Pair {
private:
 T1 first;
 T2 second;
 
public:
 Pair(const T1& a, const T2& b) : first(a), second(b) {}
 
 void print() {
 std::cout << "(" << first << ", " << second << ")" << std::endl;
 }
};

int main() {
 Pair<int, double> p1(3, 3.14);
 Pair<std::string, int> p2("Alice", 20);
 
 p1.print(); // (3, 3.14)
 p2.print(); // (Alice, 20)
 
 return 0;
}
▶ 試してみよう

💡 [重要]: クラステンプレート[を使用する際は][明示的に]型を指定する必要があります([ただし]コンストラクタ[によって型が推論される]場合を除く)。



4. テンプレートの宣言と定義*

(1) 4.1 [質問]:template[はどこに置くべきか]?*

[もし]template[の宣言を] .hに、[定義を] .cppに置くと、[[リンク]エラー]が発生します!

[原因]: テンプレートは[真の]関数やクラスではなく、[それは]コンパイル時に[生成される]コード[である]「[テンプレート]」です。

(2) 4.2 [解決策]:宣言と定義を一緒にする*

[推奨される書き方]: [template]の宣言と定義をすべて.hファイル[に]記述します。

CPP
// pair.h(file)
#ifndef PAIR_H
#define PAIR_H

template <typename T1, typename T2>
class Pair {
private:
 T1 first;
 T2 second;
 
public:
 Pair(const T1& a, const T2& b);
 void print();
};

//!
template <typename T1, typename T2>
Pair<T1, T2>::Pair(const T1& a, const T2& b) : first(a), second(b) {}

template <typename T1, typename T2>
void Pair<T1, T2>::print() {
 std::cout << "(" << first << ", " << second << ")" << std::endl;
}

#endif

💡 [ヒント]: [これは]テンプレートと[汎用]関数/クラスの[最大]の違い——テンプレートは[通常、宣言と定義が一緒に行われる]



5. 演習:[簡単]arraytemplate*

▶ サンプル 3: [実装] Array クラステンプレート (難易度 ⭐⭐⭐)

CPP
#include iostream
#include cassert

template <typename T>
class Array {
private:
 T* data;
 int size;
 
public:
 Array(int sz) : size(sz) {
 data = new T[size];
 }
 
 ~Array() {
 delete data;
 }
 
 // ()
 Array(const Array& other) : size(other.size) {
 data = new T[size];
 for (int i = 0; i < size; i++) {
 data[i] = other.data[i];
 }
 }
 
 // 
 T& operator(int index) {
 assert(index >= 0 && index < size);
 return data[index];
 }
 
 int getSize() const {
 return size;
 }
};

int main() {
 Arrayint arr(5);
 for (int i = 0; i < arr.getSize(); i++) {
 arr[i] = (i + 1) * 10;
 }
 
 for (int i = 0; i < arr.getSize(); i++) {
 std::cout << arr[i] << " ";
 }
 std::cout << std::endl;
 
 return 0;
}
▶ 試してみよう

❓ よくある質問

Q:テンプレート[と]関数のオーバーロード[にはどのような違いがありますか]? A:> - 関数のオーバーロード:[複数の同名の]関数で、[引数の]型が[異なる](コンパイル時に[どの関数を呼び出すかが]決定される) > - 関数テンプレート:[1つの]「[型]」、コンパイラが[使用時の]型[に基づいて][対応するバージョン]を[自動的に生成する] > > [推奨]: [ロジックが完全に同じ場合]([単に]型が[異なる]場合)、[テンプレート]を使用します。[ロジックが異なる場合]は、[オーバーロード]を使用します。 Q:テンプレートは[すべての]型を[サポートできますか]? A:[できません]!テンプレートは、型が[特定の演算をサポートしていること]を[要求]します。 > > template<typename T> > T add(T a, T b) { > return a + b; // [Tが] operator+ [をサポートしていること] [が要件] > } > > // [もし] T [がカスタム]クラスであり、[かつ] operator+ のオーバーロードがない場合、[コンパイル時に]エラー[が発生する]。 > Q:[いつ]template[を使うべきか]? A:[関数や]クラス[の][ロジックが]type[とは無関係][な場合]。 > > [典型的なシナリオ]: > - コンテナクラス(std::vectorstd::array) > - アルゴリズム(std::sortstd::find) > - [ユーティリティ]関数(std::maxstd::minstd::swap


Q:templates basicsについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。

📖 まとめ


📝 練習問題

  1. 初心者(難易度 ⭐): [1つの]関数テンプレート T min(T a, T b) を記述し、[2つの]値のうち[小さい方の]値を返す。

  2. 中級(難易度 ⭐⭐): [1つの]クラステンプレート BoxT を記述し、[1つの] T 型のメンバ、[および] void set(T val) [と] T get() のメンバ関数を含める。

  3. 上級(難易度 ⭐⭐⭐): [上記の] Array クラステンプレートを[拡張]し、[追加]:


6. 🚀 次は

[「テンプレート」の基礎を学びました]。[次は] STLコンテナ([第]34[回])を学びましょう―― C++の標準ライブラリが提供する既製のコンテナを[利用]し、[自分で一から作る必要はありません]!

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%