template <テンプレート引数宣言> 関数宣言または定義
/****************************/
/* 関数テンプレート */
/* coded by Y.Suganuma */
/****************************/
#include <iostream>
/*****************************/
/* 様々な型のデータの比較 */
/* a,b : 比較するデータ */
/*****************************/
template <class cl> cl min(cl a, cl b) {
return a < b ? a : b;
}
/******************/
/* mainプログラム */
/******************/
int main()
{
int i = 0, j = 1, k;
double x = 10.0, y = 5.5, z;
k = min(i, j);
z = min(x, y);
std::cout << k << " " << z << std::endl;
return 0;
}
template <テンプレート引数宣言> class name {
・・・・・
};
// コンストラクタ(デストラクタも同様)
template <テンプレート引数宣言> クラス名 <テンプレート引数> :: クラス名 (引数)
{
・・・・・
};
// メンバー関数
template <テンプレート引数宣言> クラス名 <テンプレート引数> :: メンバー関数名 (引数)
{
・・・・・
};
/******************************/
/* クラステンプレート */
/* coded by Y.Suganuma */
/******************************/
#include <iostream>
using namespace std;
/******************/
/* クラスTpの定義 */
/******************/
template <class Tp, int size> class Vector {
Tp *p;
public:
Vector(); // コンストラクタ
void print(int); // 出力
void input() // 入力
{
int i1;
for (i1 = 0; i1 < size; i1++) {
cout << " " << i1+1 << " 番目の要素は? ";
cin >> p[i1];
}
}
};
/******************/
/* コンストラクタ */
/******************/
template <class Tp, int size> Vector <Tp, size>::Vector()
{
p = new Tp [size];
}
/*****************************/
/* データの出力 */
/* k : 出力する要素番号 */
/*****************************/
template <class Tp, int size> void Vector <Tp, size>::print(int k)
{
if (k < 0 || k > size-1)
cout << " 要素番号が不適当です\n";
else
cout << " " << (k+2) << " 番目の要素は " << p[k] << endl;
}
/************/
/* main関数 */
/************/
int main()
{
int k = 0, sw;
cout << "整数(0) or 実数(1) ? ";
cin >> sw;
/*
整数
*/
if (sw == 0) {
Vector < int, 3 > iv;
cout << "整数ベクトル\n";
iv.input();
while (k >= 0) {
cout << "要素番号は ";
cin >> k;
iv.print(k);
}
}
/*
実数
*/
else {
Vector < double, 3 > dv;
cout << "実数ベクトル\n";
dv.input();
while (k >= 0) {
cout << "要素番号は ";
cin >> k;
dv.print(k);
}
}
return 0;
}
| vector | 動的配列を保持します.C の配列と互換性を持ち,データ領域の連続性が保証されています.通常の動的配列の場合は,宣言時に大きさを宣言しなければなりませんが,vector の場合は必要ありません.また,要素数を途中で変更することも可能です.( STL ) |
|---|---|
| deque | 双方向の待ち行列に対応します.vector と似ていますが,動的配列の前にも要素の挿入や削除を行えるメンバー関数が存在する点が,vector とは異なっています.( STL ) |
| set | 要素を自動的にソートして保持し,要素自身をキーとした探索が可能です.map と似ていますが,map ではキーとデータを別々に保持します.( STL ) |
| multiset | 同じ値を持つ要素許す set です.( STL ) |
| map | 連想配列,つまり,添え字として数値以外(キー)を使用してデータを参照できる配列を保持します.set と同様,データは自動的にソートされます.( STL ) |
| multimap | 同じキーを持つデータ(キーの重複)を許す map です.( STL ) |
| list | 双方向リストを保持します.( STL ) |
| queue | 待ち行列を保持します.STL コンテナの一部を利用して,特別な機能を持たせたクラスであり,コンテナアダプタと呼ばれています. |
| priority_queue | 優先順位付き待ち行列を保持します.要素を追加すると,優先順位に従いソートされます.STL コンテナの一部を利用して,特別な機能を持たせたクラスであり,コンテナアダプタと呼ばれています. |
| stack | スタックを保持します.STL コンテナの一部を利用して,特別な機能を持たせたクラスであり,コンテナアダプタと呼ばれています. |
| bitset | ビットの並びを保持します. |
| pair | 2 つのデータをペアにして扱うためのコンテナです. |
| string | 文字列を保持するクラスです. |
| ランダムアクセスイテレータ | 各要素にランダムにアクセスでき,かつ,要素の参照と設定が可能 |
|---|---|
| 双方向イテレータ | 前方及び後方に移動でき,かつ,要素の参照と設定が可能 |
| 前方イテレータ | 前方だけに移動でき,かつ,要素の参照と設定が可能 |
| 入力イテレータ | 前方だけに移動でき,かつ,要素の設定が可能 |
| 出力イテレータ | 前方だけに移動でき,かつ,要素の参照が可能 |
| ランダムアクセスイテレータ | *, ->, =, +, -, ++, --, [], <, >, <=, >=, -=, +=, ==, != |
|---|---|
| 双方向イテレータ | *, ->, =, ++, --, ==, != |
| 前方イテレータ | *, ->, =, ++, ==, != |
| 入力イテレータ | *, ->, =, ++, ==, != |
| 出力イテレータ | *, =, ++ |
#include <stdio.h>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
vector<int>::iterator it; // イテレータ
vector<int>::reverse_iterator r_it; // 逆方向イテレータ
// 初期設定
printf("**初期設定**\n");
v.push_back(0);
v.push_back(4);
v.push_back(3);
v.push_back(1);
v.push_back(2);
for (it = v.begin(); it != v.end(); it++)
printf(" %d", *it);
printf("\n**後ろの 3 つを出力**\n");
it = v.begin() + 2; // vector の場合,ランダムアクセスイテレータであるため可能
while (it != v.end()) {
printf(" %d", *it);
it++;
}
printf("\n**逆方向に出力**\n");
for (r_it = v.rbegin(); r_it != v.rend(); r_it++)
printf(" %d", *r_it);
return 0;
}
(出力)
**初期設定**
0 4 3 1 2
**後ろの 3 つを出力**
3 1 2
**逆方向に出力**
2 1 3 4 0
| insert_iterator | コンテナに要素を挿入する出力イテレータ.insert_iterator を生成する inserter() 関数を持っています. |
|---|---|
| front_insert_iterator | コンテナの最初に要素を挿入する出力イテレータ.push_front() を使用して実行するため,このメンバー関数を持つコンテナだけに適用できます.front_insert_iterator を生成する front_inserter() 関数を持っています. |
| back_insert_iterator | コンテナの最後に要素を挿入する出力イテレータ.push_back() を使用して実行するため,このメンバー関数を持つコンテナだけに適用できます.back_insert_iterator を生成する back_inserter() 関数を持っています. |
#include <stdio.h>
#include <deque>
using namespace std;
int main()
{
int i1;
deque<int> q1, q2, q3;
deque<int>::iterator it;
// 初期設定
printf("**初期設定 : q1**\n");
for (i1 = 0; i1 < 5; i1++)
q1.push_back(i1);
for (it = q1.begin(); it != q1.end(); it++)
printf(" %d", *it);
printf("\n");
printf("**初期設定 : q2**\n");
for (i1 = 0; i1 < 3; i1++)
q2.push_back(10 * (i1 + 1));
for (it = q2.begin(); it != q2.end(); it++)
printf(" %d", *it);
printf("\n");
// insert_iterator
printf("**2 番目の要素の前に 5 を挿入( insert_iterator )**\n");
it = q1.begin() + 1;
insert_iterator<deque<int> > i_it(q1, it);
*i_it = 5;
for (it = q1.begin(); it != q1.end(); it++)
printf(" %d", *it);
printf("\n");
// inserter
printf("**q1 の 3 番目の要素の前に q2 を挿入( inserter )**\n");
copy(q2.begin(), q2.end(), inserter(q1, q1.begin()+2));
for (it = q1.begin(); it != q1.end(); it++)
printf(" %d", *it);
printf("\n");
// front_insert_iterator, back_insert_iterator
printf("**最初と最後に 20 と 10 を挿入**\n");
printf("**( front_insert_iterator と back_insert_iterator )**\n");
front_insert_iterator<deque<int> > f_it(q1);
*f_it = 20;
back_insert_iterator<deque<int> > b_it(q1);
*b_it = 10;
for (it = q1.begin(); it != q1.end(); it++)
printf(" %d", *it);
printf("\n");
// back_inserter
printf("**q2 を q3 にコピー( back_inserter )**\n");
copy(q2.begin(), q2.end(), back_inserter(q3));
// copy(q2.begin(), q2.end(), q3.begin()); // 挿入タイプでないとだめ
for (it = q3.begin(); it != q3.end(); it++)
printf(" %d", *it);
printf("\n");
// copy
printf("**q2 を q1 に上書きコピー**\n");
copy(q2.begin(), q2.end(), q1.begin()); // 上書きコピー
for (it = q1.begin(); it != q1.end(); it++)
printf(" %d", *it);
printf("\n");
return 0;
}
(出力)
**初期設定 : q1**
0 1 2 3 4
**初期設定 : q2**
10 20 30
**2 番目の要素の前に 5 を挿入( insert_iterator )**
0 5 1 2 3 4
**q1 の 3 番目の要素の前に q2 を挿入( inserter )**
0 5 10 20 30 1 2 3 4
**最初と最後に 20 と 10 を挿入**
**( front_insert_iterator と back_insert_iterator )**
20 0 5 10 20 30 1 2 3 4 10
**q2 を q3 にコピー( back_inserter )**
10 20 30
**q2 を q1 に上書きコピー**
10 20 30 10 20 30 1 2 3 4 10
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
vector<int>::iterator it;
istream_iterator<int> i_it(cin);
ostream_iterator<int> o_it(cout);
*i_it;
while (*i_it != 0) {
v.push_back(*i_it);
i_it++;
}
for (it = v.begin(); it != v.end(); it++) {
cout << " ";
*o_it = *it;
o_it++;
}
return 0;
}
(出力) 10 20 30 0 を入力したとき
10 20 30
| シーケンス変更なし | adjacent_find() | 指定した範囲で,同じ要素が連続している位置,または,連続する 2 つの要素が二項関数オブジェクトで指定された関係にある位置を探します. |
|---|---|---|
| count() | 指定した範囲で,指定した値と一致する要素の数を返します. | |
| count_if() | 指定した範囲で,単項関数オブジェクトが真となる要素の数を返します. | |
| equal() | first1 から last1 で指定した範囲が,first2 で指定された要素列と等しい,または,二項関数オブジェクトで指定した意味で等しい場合に true を返します. | |
| find() | 指定した範囲で,指定した要素を探します. | |
| find_end() | first1 から last1 で指定した範囲で,first2 から last2 で指定された要素列,または,二項関数オブジェクトで指定した意味で等しい要素列が最後に表れた位置を返します. | |
| find_first_of() | first1 から last1 で指定した範囲で,first2 から last2 に含まれるいずれかの要素,または,二項関数オブジェクトで指定した意味で等しいいずれかの要素が最初に表れた位置を返します. | |
| find_if() | 指定した範囲で,単項関数オブジェクトが真になる要素を探します. | |
| for_each() | 指定した範囲に,指定した関数による処理を適用します. | |
| mismatch() | first1 から last1 で指定した範囲が,first2 で指定された要素列と異なる,または,二項関数オブジェクトで指定した意味で異なる位置を返します. | |
| search() | first1 から last1 で指定した範囲で,first2 から last2 で指定された要素列,または,二項関数オブジェクトで指定した意味で等しい要素列が最初に表れた位置を返します. | |
| search_n() | first1 から last1 で指定した範囲で,指定された要素の n 個の要素列,または,二項関数オブジェクトで指定した意味で指定した要素と等しい n 個の要素列が最初に表れた位置を返します. | |
| シーケンス変更あり | copy() | 指定した範囲をコピーします. |
| copy_backward() | 指定した範囲を後方からコピーします. | |
| fill() | 指定した範囲の要素を,指定した要素に設定します. | |
| fill_n() | 指定した位置から始まる指定した数の要素を,指定した要素に設定します. | |
| generate() | 指定した範囲の要素を,指定した関数によって生成された要素に設定します. | |
| generate_n() | 指定した位置から始まる指定した数の要素を,指定した関数によって生成された要素に設定します. | |
| iter_swap() | イテレータで指定した 2 つの要素を交換します. | |
| partition() | 単項述語オブジェクトが真になる要素を偽になる要素の前に移動します.その際,最初の前後関係が維持されるとは限りません. | |
| random_shuffle() | イテレータで指定された範囲の要素をランダムに並び替えます.乱数発生関数を指定することも可能です. | |
| remove() | 指定した範囲の指定した要素を削除します.ただし,コンテナのサイズ自身は変化しません. | |
| remove_copy() | 指定した範囲の指定した要素を削除し,指定した場所にコピーます.ただし,コピー元の要素は変化しません. | |
| remove_copy_if() | 指定した範囲の単項関数オブジェクトが真になる要素を削除し,指定した場所にコピーます.ただし,コピー元の要素は変化しません. | |
| remove_if() | 指定した範囲の単項関数オブジェクトが真になる要素を削除します.ただし,コンテナのサイズ自身は変化しません. | |
| replace() | 指定した範囲の指定した要素を,指定した要素に置き換えます. | |
| replace_copy() | 指定した範囲の指定した要素を,指定した要素に置き換え,指定した場所にコピーします.ただし,コピー元の要素は変化しません. | |
| replace_copy_if() | 指定した範囲の単項関数オブジェクトが真になる要素を,指定した要素に置き換え,指定した場所にコピーます.ただし,コピー元の要素は変化しません. | |
| replace_if() | 指定した範囲の単項関数オブジェクトが真になる要素を,指定した要素に置き換えます. | |
| reverse() | 指定した範囲の要素の並び順を反転します. | |
| reverse_copy() | 指定した範囲の要素の並び順を反転し,指定した場所にコピーします.ただし,コピー元は変化しません. | |
| rotate() | イテレータ middle が指す要素が先頭になるように左方向に回転します. | |
| rotate_copy() | イテレータ middle が指す要素が先頭になるように左方向に回転し,指定した場所にコピーします.ただし,コピー元は変化しません. | |
| stable_partition() | 単項述語オブジェクトが真になる要素を偽になる要素の前に移動します.その際,最初の前後関係が維持されます. | |
| swap() | 指定した 2 つの要素を交換します. | |
| swap_ranges() | イテレータ first1,last1 で指定した範囲を first2 で始まる範囲と交換します. | |
| transform() | イテレータで指定された範囲の要素に対して,1 引数関数,または,2 引数関数の結果を適用し,指定した場所に保存します. | |
| unique() | 指定した範囲の指定した重複した要素,または,二項関数オブジェクトを真にする意味で重複した要素を削除します.ただし,コンテナのサイズ自身は変化しません. | |
| unique_copy() | 指定した範囲の指定した重複した要素,または,二項関数オブジェクトを真にする意味で重複した要素を削除し,指定した位置にコピーします.ただし,コピー元は変化しません. | |
| ソート関係 | binary_search() | ソート済みの系列に対して,指定した範囲で,指定した要素を探します.2 引数の比較関数を指定することも可能です. |
| equal_range() | ソート済みの系列に対して,指定した要素を系列の順序を破壊することなく挿入できる位置( lower_bound と upper_bound )を返します.2 引数の比較関数を指定することも可能です. | |
| includes() | 最初の系列に,後ろの系列のすべての要素が含含まれているとき true を返します.2 引数の比較関数を指定することも可能です. | |
| inplace_merge() | 同じ系列内の first から middle で指定した部分と,middle から last で指定した部分をマージします.2 引数の比較関数を指定することも可能です. | |
| lexicographical_compare() | 2 つの系列をアルファベット順に比較し,先の系列が次の系列より辞書的に前にあれば true を返します.2 引数の比較関数を指定することも可能です. | |
| lower_bound() | ソート済みの系列に対して,指定した要素以上の値を持つ最初の要素を返します.2 引数の比較関数を指定することも可能です. | |
| make_heap() | ヒープを構築します.ヒープとは,系列の中の最大要素をルートとした木構造です.2 引数の比較関数を指定することも可能です. | |
| max() | 2 つの値の内,大きい方の値を返します.2 引数の比較関数を指定することも可能です. | |
| max_element() | 指定した範囲における最大値を返します.2 引数の比較関数を指定することも可能です. | |
| merge() | 2 つの領域をマージします.2 引数の比較関数を指定することも可能です. | |
| min() | 2 つの値の内,小さい方の値を返します.2 引数の比較関数を指定することも可能です. | |
| min_element() | 指定した範囲における最小値を返します.2 引数の比較関数を指定することも可能です. | |
| next_permutation() | 系列の各要素を辞書的順序で並べた場合において,現在の並べ方の次になる並べ方を返します.次の並べ方が存在しない場合,辞書的順序における最初の並べ方に並べ替えます.2 引数の比較関数を指定することも可能です. | |
| nth_element() | first から last によって指定した範囲を対象とし,nth で指定した要素より小さい要素をその前に,大きい要素をその後ろに移動します.2 引数の比較関数を指定することも可能です. | |
| partial_sort() | first から last で,指定した範囲をソートします.その際,ソートされるのは first から middle までであり,それ以降はばらばらとなります.2 引数の比較関数を指定することも可能です. | |
| partial_sort_copy() | first から last で,指定した範囲をソートし,result_first から result_last の間に可能な限りコピーします.2 引数の比較関数を指定することも可能です. | |
| pop_heap() | ヒープの先頭の要素(最大の要素)を系列の最後に移動し,ヒープを再構築します.ヒープとは,系列の中の最大要素をルートとした木構造です.2 引数の比較関数を指定することも可能です. | |
| prev_permutation() | 系列の各要素を辞書的順序で並べた場合において,現在の並べ方の前になる並べ方を返します.前の並べ方が存在しない場合,辞書的順序における最後の並べ方に並べ替えます.2 引数の比較関数を指定することも可能です. | |
| push_heap() | ヒープに要素を追加し,ヒープを再構築します.ヒープとは,系列の中の最大要素をルートとした木構造です.2 引数の比較関数を指定することも可能です. | |
| set_difference() | 系列 1 に含まれ,系列 2 に含まれない要素の集合を出力します.なお,2 つの系列は前もってソートしておく必要があります.2 引数の比較関数を指定することも可能です. | |
| set_intersection() | 系列 1 ,及び,系列 2 の両方に含まれる要素の集合を出力します.なお,2 つの系列は前もってソートしておく必要があります.2 引数の比較関数を指定することも可能です. | |
| set_symmetric_difference() | 系列 1 ,または,系列 2 に含まれない要素の集合を出力します.なお,2 つの系列は前もってソートしておく必要があります.2 引数の比較関数を指定することも可能です. | |
| set_union() | 系列 1 ,または,系列 2 に含まれる要素の集合を出力します.なお,2 つの系列は前もってソートしておく必要があります.2 引数の比較関数を指定することも可能です. | |
| sort() | 指定した範囲をソートします.比較関数を指定することも可能です. | |
| sort_heap() | ヒープをソートします.ヒープとは,系列の中の最大要素をルートとした木構造です.2 引数の比較関数を指定することも可能です. | |
| stable_sort() | 指定した範囲をソートします.その際,等しい要素の並び順が保持されます.2 引数の比較関数を指定することも可能です. | |
| upper_bound() | ソート済みの系列に対して,指定した要素より大きい値を持つ最初の要素を返します.2 引数の比較関数を指定することも可能です. | |
| 数値関係 | accumulate() | イテレータで指定された範囲の総和を計算します.2 引数関数によって,和の計算方法を指定することもできます. |
| adjacent_difference() | 隣接する要素間の差からなる系列を計算します.2 引数関数によって,差の計算方法を指定することもできます. | |
| inner_product() | イテレータで指定された範囲で,2 つのコンテナ v1 と v2 の内積を計算します.2 引数関数によって,和及び積の計算方法を指定することもできます. | |
| partial_sum() | イテレータで指定された範囲の部分和(順番に和を求めながら,その段階までの和をその要素の値とする)を計算します.2 引数関数によって,和の計算方法を指定することもできます. |
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<string, int, greater<string> > m1;
map<string, int, less<string> > m2;
map<string, int, greater<string> >::iterator g_it;
map<string, int, less<string> >::iterator l_it;
cout << "**コンテナ m1 (greater)**\n";
m1.insert(pair<string, int>("suzuki", 40));
m1.insert(pair<string, int>("sato", 60));
m1.insert(pair<string, int>("yamada", 70));
m1.insert(pair<string, int>("tanaka", 50));
m1.insert(pair<string, int>("kato", 90));
for (g_it = m1.begin(); g_it != m1.end(); g_it++)
cout << " " << (*g_it).first << " " << (*g_it).second;
cout << endl;
cout << "**コンテナ m2 (less)**\n";
m2.insert(pair<string, int>("suzuki", 40));
m2.insert(pair<string, int>("sato", 60));
m2.insert(pair<string, int>("yamada", 70));
m2.insert(pair<string, int>("tanaka", 50));
m2.insert(pair<string, int>("kato", 90));
for (l_it = m2.begin(); l_it != m2.end(); l_it++)
cout << " " << (*l_it).first << " " << (*l_it).second;
cout << endl;
return 0;
}
(出力)
**コンテナ m1 (greater)**
yamada 70 tanaka 50 suzuki 40 sato 60 kato 90
**コンテナ m2 (less)**
kato 90 sato 60 suzuki 40 tanaka 50 yamada 70
| 単項関数オブジェクト | logical_not, negate |
|---|---|
| 二項関数オブジェクト | plus, minus, multiplies, divides, modulus, equal_to, not_equal_to, greater, greater_equal, less, less_equal, logical_and, logical_or |
#include <iostream>
#include <list>
#include <functional>
using namespace std;
// 単項関数オブジェクト
template <class T> class is_odd : public unary_function<T, bool>
{
public:
bool operator() (T k)
{
return (bool)(k % 2);
}
};
// 二項関数オブジェクト
class Equal : public binary_function<int, int, bool>
{
public:
result_type operator() (first_argument_type a, second_argument_type b)
{
return (result_type)(a == b);
}
};
int main()
{
list<int> ls;
list<int>::iterator it;
// 初期設定
printf("**初期設定**\n");
ls.push_back(0);
ls.push_back(2);
ls.push_back(3);
ls.push_back(4);
ls.push_back(1);
for (it = ls.begin(); it != ls.end(); it++)
cout << " " << *it;
cout << endl;
// 奇数である要素を削除
Equal eq;
// equal_to<int> eq; // 組み込まれている equal_to を使用する場合
printf("**奇数である要素を削除**\n");
ls.remove_if(is_odd<int>());
for (it = ls.begin(); it != ls.end(); it++) {
if (eq(*it, 2))
cout << " " << *it << " は 2 に等しい" << endl;
else
cout << " " << *it << " は 2 に等しくない" << endl;
}
return 0;
}
(出力)
**初期設定**
0 2 3 4 1
**奇数である要素を削除**
0 は 2 に等しくない
2 は 2 に等しい
4 は 2 に等しくない
| ホームページ | 目次 | 演習解答例目次 | 付録目次 | 索引 |