要素を一列に並べたデータ構造を「シーケンス (sequence)」とか「列」と呼びます。たとえば、Common Lisp はリスト、一次元配列 (ベクタ)、文字列を列型データとして統一して扱うことができます。列を操作する関数を列関数といい、Common Lisp には便利な列関数が多数用意されています。
C++の場合、vector, array, list, forward_list などのコンテナクラスは、シーケンスとして共通な操作を考えることができます。今回はシーケンスを操作する関数をテンプレートで作ってみましょう。
シーケンスの中から最大値を求める関数 maximum と、最小値を求める関数 minimum を定義してください。引数は先頭と終端を示すイテレータで、返り値は求めた要素へのイテレータとします。
シーケンスを線形探索する関数 member, position, count を定義してください。member の返り値は bool、position の返り値は見つけた位置 (見つからない場合は -1)、count の返り値は見つけた要素の個数です。
引数の叙述関数が真を返すデータを線形探索する高階関数 member_if, position_if, count_if を定義してください。
シーケンスの要素に引数の関数オブジェクト func を適用して、その結果を新しいシーケンスに格納して返す高階関数 mapcar を定義してください。このような操作を「マッピング (写像)」といいます。
引数 x と等しい要素をシーケンスから削除する関数 remove と、叙述関数が真を返す要素をシーケンスから削除する関数 remove_if を定義してください。なお、どちらの関数も引数にはシーケンスのイテレータ (始点と終点) を受け取り、シーケンスを破壊的に修正することにします。返り値は最後に書き込んだ要素の次を示すイテレータです。
シーケンスの要素を先頭から畳み込む高階関数 fold_left と末尾から畳み込む fold_right を定義してください。
シーケンスの要素に叙述関数 p を適用し、一つでも真を返す要素があれば真を返す関数 any と、一つでも偽を返す要素があれば偽を返す (全てが真の場合に真を返す) 関数 every を定義してください。
シーケンスに整数 n から始まる数列をセットする関数 iota と、n から始まる数列の要素に関数 f を適用して、その結果をシーケンスにセットする高階関数 tabulate を定義してください。
引数 x と等しいシーケンスの要素を引数 y に置換する関数 substitute と、叙述関数が真を返す要素を引数 y に置換する関数 substitute_if を定義してください。なお、これらの関数は引数のシーケンスを破壊的に修正するものとします。
「連想リスト (association list : a-list)」は Lisp でよく用いられるデータ構造で、キーとデータの組を要素とする連結リストで実現することができます。
┌────┬────┬────┬──→ データ │ │ │ │ 連想リスト => [("a", 1), ("b", 2), ("c", 3), ("d", 4)] │ │ │ │ └────┴────┴────┴──→ キー 図 : 連想リストの構造
上図の場合、文字列 "a", "b", "c", "d" がキーで、整数 1, 2, 3, 4 がデータとなります。C++の場合、連想リストは list<pair<K, V>> で表すことができます。また、他のコンテナクラスを使っても簡単に実装することができます。
連想リストの先頭にキーと値を追加する関数 acons と、連想リストからキーを線形探索する関数 assoc を定義してください。
リスト : 最大値と最小値 template<class It> It maximum(It first, It last) { if (first == last) return last; It m = first++; while (first != last) { if (*m < *first) m = first; ++first; } return m; } template<class It> It minimum(It first, It last) { if (first == last) return last; It m = first++; while (first != last) { if (*m > *first) m = first; ++first; } return m; }
どちらの関数も引数 first から last までの区間から最大値 (または最小値) を探します。これ以降、シーケンスの区間を [first, last) と記述することにします。first と last が等しい場合は last を返します。そして、先頭要素へのイテレータを変数 m にセットして、first を次の要素へ進めます。あとは、while ループで要素を順番にチェックしていき、*m よりも *frist が大きい (または小さい) 場合は m を first に書き換えます。最後に m を返すだけです。
なお、STL の algorithm には同等の機能を持つ関数 max_element と min_element が用意されています。
探索する区間をイテレータ [first, last) で渡すことにすると、プログラムは次のようになります。
リスト : シーケンスの線形探索 (1) template<class It, class T> bool member(It first, It last, const T& val) { while (first != last) if (*first++ == val) return true; return false; } template<class It, class T> int position(It first, It last, const T& val) { int i = 0; while (first != last) { if (*first++ == val) return i; i++; } return -1; } template<class It, class T> int count(It first, It last, const T& val) { int c = 0; while (first != last) if (*first++ == val) c++; return c; }
テンプレート仮引数の It がイテレータ、T が探索するデータの型を表します。member は *first と val が等しければ true を返します。postion は位置 (添字) i を返します。count は *first と val が等しければ変数 c を +1 して、最後に c を返します。
シーケンス自身をそのまま渡すこともできます。次のリストを見てください。
リスト : シーケンスの線形探索 (2) template<class T, class U> bool member(const T& seq, const U& val) { for (auto& x : seq) if (x == val) return true; return false; } template<class T, class U> int position(const T& seq, const U& val) { int i = 0; for (auto& x : seq) { if (x == val) return i; i++; } return -1; } template<class T, class U> int count(const T& seq, const U& val) { int c = 0; for (auto& x : seq) if (x == val) c++; return c; }
T がシーケンスのデータ型を表す仮引数で、U が探索するデータの型です。シーケンスの要素は範囲 for 文で順番に取り出すことができます。データ型の指定も auto を使えば簡単です。関数型言語の場合、このような仕様が一般的ですが、C++ではイテレータを渡すのが普通のようです。
リスト : 線形探索 (高階関数版) template<class It, class F> bool member_if(It first, It last, F func) { while (first != last) if (func(*first++)) return true; return false; } template<class It, class F> int position_if(It first, It last, F func) { int i = 0; while (first != last) { if (func(*first++)) return i; i++; } return -1; } template<class It, class F> int count_if(It first, It last, F func) { int c = 0; while (first != last) if (func(*first++)) c++; return c; }
It がイテレータを表す仮引数、F が関数オブジェクトを表す仮引数です。区間 [first, last) から叙述関数 func が真を返す要素を探索します。member_if は func(*first) が真ならば true を返します。positon_if は位置 (添字) i を返します。count_if は変数 c の値を +1 して、最後に c を返します。
シーケンス自身を渡す場合は次のようになります。
リスト : 線形探索 (高階関数版) template<class T, class F> bool member_if(const T& seq, F func) { for (auto& x : seq) if (func(x)) return true; return false; } template<class T, class F> int position_if(const T& seq, F func) { int i = 0; for (auto& x : seq) if (func(x)) return i; return -1; } template<class T, class F> int count_if(const T& seq, F func) { int c = 0; for (auto& x : seq) if (func(x)) c++; return c; }
func(x) が真を返すとき、member_if は true を返し、position_if は変数 i を返し、count_if は変数 c を +1 して、最後に c を返します。
リスト : マッピング template<class T, class F> T mapcar(const T& seq, F func) { T new_seq(seq.size()); auto iter = new_seq.begin(); for (auto& x : seq) *iter++ = func(x); return new_seq; }
最初に、コンストラクタで大きさ seq.size() の新しいシーケンス new_seq を生成します。そして、新しいシーケンスの先頭要素を示すイテレータ iter を生成します。あとは範囲 for 文でシーケンス seq から要素 x を取り出し、*iter に func(x) の返り値をセットします。最後に new_seq を返します。
メンバ関数に push_back があるならば、空の新しいシーケンスを生成して、そこに push_back で追加していく方法もあります。ただし、forward_list には push_back がないので、今回はこのようなプログラムにしてみました。
シーケンスをイテレータで渡す場合は次のようになります。
リスト : マッピングの別解 template<class It, class F> It mapcar(It first, It last, F func, It result) { while (first != last) *result++ = func(*first++); return result; }
引数 result は結果を格納するシーケンスへのイテレータです。この場合、mapcar を呼び出す前に出力先のシーケンスを生成しておいてください。
リスト : 要素の削除 template<class It, class U> It remove(It first, It last, const U& val) { It result = first; while (first != last) { if (*first != val) *result++ = *first; ++first; } return result; }
remove は区間 [first, last) の中から val と等しい要素を削除します。変数 result は書き込む位置を表すイテレータで、first に初期化します。あとは、*first と val が等しくなければ、*resulte に *first をセットするだけです。区間を上書きすることに注意してください。最後に result を返します。つまり、区間 [first, result) に要素を削除した結果がセットされます。
リスト : 要素の削除 (高階関数版) template<class It, class F> It remove_if(It first, It last, F func) { It result = first; while (first != last) { if (!func(*first)) *result++ = *first; ++first; } return result; }
remove_if は叙述関数 func が真を返す要素を削除します。処理は remove とほとんど同じです。なお、STL の algorithm には同等の機能を持つ関数 remove, remove_if が用意されています。
リスト : 畳み込み template<class T, class U, class F> U fold_left(const T& seq, U init, F func) { for (auto& x : seq) init = func(init, x); return init; } template<class T, class U, class F> U fold_right(const T& seq, U init, F func) { for (auto iter = seq.crbegin(); iter != seq.crend(); ++iter) init = func(*iter, init); return init; }
テンプレート仮引数 T がシーケンスのデータ型、U が初期値のデータ型、F が 2 引数の関数オブジェクトを表します。fold_left は範囲 for 文を使えば簡単です。init の値を func(init, x) で書き換えていくだけです。fold_right は reverse イテレータを使います。なお、forward_list は reverse イテレータをサポートしていないので、fold_right を適用することはできません。
func の引数は fold_left と fold_right で逆になっていることに注意してください。なお、畳み込み fold_left と fold_right の仕様は、プログラミング言語によって異なります。関数型言語でも統一されているわけではありません。ご注意くださいませ。
イテレータを渡す場合は次のようになります。
リスト : 別解 template<class It, class T, class F> T fold(It first, It last, T init, F func) { while (first != last) init = func(init, *first++); return init; }
とくに難しいところはないと思います。
リスト : any と every template<class It, class F> bool any(It first, It last, F func) { while (first != last) if (func(*first++)) return true; return false; } template<class It, class F> bool every(It first, It last, F func) { while (first != last) if (!func(*first++)) return false; return true; }
どちらの関数もイテレータ [first, last) が表す区間の要素に関数オブジェクト func を適用し、any は真を返す要素がひとつでもあれば true を返します。every は偽を返す要素が一つでもあれば false を返します。C++の algorithm には同等の機能を持つ関数 any_of と all_of が用意されています。
シーケンス自身を渡す場合は次のようになります。
リスト : 別解 template<class T, class F> bool any(const T& seq, F func) { for (auto& x : seq) if (func(x)) return true; return false; } template<class T, class F> bool every(const T& seq, F func) { for (auto& x : seq) if (!func(x)) return false; return true; }
範囲 for 文を使えば簡単にプログラムすることができます。
リスト : iota と tabulate template<class T> void iota(T& seq, int n) { for (auto& x : seq) x = n++; } template<class T, class F> void tabulate(T& seq, int n, F func) { for (auto& x : seq) x = func(n++); }
iota は範囲 for 文で要素への参照 x に整数値 n をセットしていくだけです。tabulate は func(n++) をセットしていくだけです。なお、C++ (C++11) の STL numeric には同等の機能を持つ関数 iota が用意されています。
シーケンスをイテレータ [first, last) で渡す場合は次のようになります。
リスト : シーケンスの置換 template<class It, class U> void substitute(const U& x, const U& y, It first, It last) { while (first != last) { if (*first == x) *first = y; first++; } } template<class It, class U, class F> void substitute_if(F func, const U& y, It first, It last) { while (first != last) { if (func(*first)) *first = y; first++; } }
substitute は *frist と引数 x が等しいとき、*first に引数 y を代入します。substitute_if は func(*first) が真を返すとき、*first に y を代入します。
シーケンス自身を渡す場合は次のようになります。
リスト : 別解 template<class T, class U> void substitute(const U& x, const U& y, T& seq) { for (auto& z : seq) { if (z == x) z = y; } } template<class T, class U, class F> void substitute_if(F func, const U& y, T& seq) { for (auto& x : seq) { if (func(x)) x = y; } }
どちらの関数も範囲 for 文を使うと簡単にプログラムすることができます。
リスト : 連想リスト template<class K, class V, class T> void acons(const K& key, const V& val, T& seq) { seq.emplace_front(key, val); } template<class K, class It> It assoc(const K& key, It first, It last) { while (first != last) { if (first->first == key) return first; ++first; } return first; }
テンプレート仮引数の K がキーを、V が値を表します。acons は emplace_front を使うと簡単です。これで、シーケンスの先頭にキーと値の組を追加することができます。assoc はイテレータ [first, last) の中からキー key を探索し、見つけたらその組を指し示すイテレータを返します。見つからない場合は last を返します。
// // yacp3.cpp : Yet Another C++ Problems (3) // // Copyright (C) 2015-2023 Makoto Hiroi // #include <iostream> #include <vector> #include <list> using namespace std; // Q21 最大値と最小値 template<class It> It maximum(It first, It last) { if (first == last) return last; It m = first++; while (first != last) { if (*m < *first) m = first; ++first; } return m; } template<class It> It minimum(It first, It last) { if (first == last) return last; It m = first++; while (first != last) { if (*m > *first) m = first; ++first; } return m; } // Q22 template<class T, class U> bool member(const T& seq, const U& val) { for (auto& x : seq) if (x == val) return true; return false; } template<class It, class T> bool member(It first, It last, const T& val) { while (first != last) if (*first++ == val) return true; return false; } template<class T, class U> int position(const T& seq, const U& val) { int i = 0; for (auto& x : seq) { if (x == val) return i; i++; } return -1; } template<class It, class T> int position(It first, It last, const T& val) { int i = 0; while (first != last) { if (*first++ == val) return i; i++; } return -1; } template<class T, class U> int count(const T& seq, const U& val) { int c = 0; for (auto& x : seq) if (x == val) c++; return c; } template<class It, class T> int count(It first, It last, const T& val) { int c = 0; while (first != last) if (*first++ == val) c++; return c; } // Q23 template<class T, class F> bool member_if(const T& seq, F func) { for (auto& x : seq) if (func(x)) return true; return false; } template<class It, class F> bool member_if(It first, It last, F func) { while (first != last) if (func(*first++)) return true; return false; } template<class T, class F> int position_if(const T& seq, F func) { int i = 0; for (auto& x : seq) if (func(x)) return i; return -1; } template<class It, class F> int position_if(It first, It last, F func) { int i = 0; while (first != last) { if (func(*first++)) return i; i++; } return -1; } template<class T, class F> int count_if(const T& seq, F func) { int c = 0; for (auto& x : seq) if (func(x)) c++; return c; } template<class It, class F> int count_if(It first, It last, F func) { int c = 0; while (first != last) if (func(*first++)) c++; return c; } // Q24 template<class T, class F> T mapcar(const T& seq, F func) { T new_seq(seq.size()); auto iter = new_seq.begin(); for (auto& x : seq) *iter++ = func(x); return new_seq; } template<class It, class F> It mapcar(It first, It last, F func, It result) { while (first != last) *result++ = func(*first++); return result; } // Q25 template<class It, class U> It remove(It first, It last, const U& val) { It result = first; while (first != last) { if (*first != val) *result++ = *first; ++first; } return result; } template<class It, class F> It remove_if(It first, It last, F func) { It result = first; while (first != last) { if (!func(*first)) *result++ = *first; ++first; } return result; } // Q26 template<class T, class U, class F> U fold_left(const T& seq, U init, F func) { for (auto& x : seq) init = func(init, x); return init; } template<class T, class U, class F> U fold_right(const T& seq, U init, F func) { for (auto iter = seq.crbegin(); iter != seq.crend(); ++iter) init = func(*iter, init); return init; } template<class It, class T, class F> T fold(It first, It last, T init, F func) { while (first != last) init = func(init, *first++); return init; } // Q27 template<class T, class F> bool any(const T& seq, F func) { for (auto& x : seq) if (func(x)) return true; return false; } template<class It, class F> bool any(It first, It last, F func) { while (first != last) if (func(*first++)) return true; return false; } template<class T, class F> bool every(const T& seq, F func) { for (auto& x : seq) if (!func(x)) return false; return true; } template<class It, class F> bool every(It first, It last, F func) { while (first != last) if (!func(*first++)) return false; return true; } // Q28 template<class T> void iota(T& seq, int n) { for (auto& x : seq) x = n++; } template<class T, class F> void tabulate(T& seq, int n, F func) { for (auto& x : seq) x = func(n++); } // Q29 template<class T, class U> void substitute(const U& x, const U& y, T& seq) { for (auto& z : seq) { if (z == x) z = y; } } template<class It, class U> void substitute(const U& x, const U& y, It first, It last) { while (first != last) { if (*first == x) *first = y; first++; } } template<class T, class U, class F> void substitute_if(F func, const U& y, T& seq) { for (auto& x : seq) { if (func(x)) x = y; } } template<class It, class U, class F> void substitute_if(F func, const U& y, It first, It last) { while (first != last) { if (func(*first)) *first = y; first++; } } // Q30 連想リスト (emplace_front が必要) template<class K, class V, class T> void acons(const K& key, const V& val, T& seq) { seq.emplace_front(key, val); } template<class K, class It> It assoc(const K& key, It first, It last) { while (first != last) { if (first->first == key) return first; ++first; } return first; } template<class T> void print_seq(const T& seq) { for (auto& x : seq) cout << x << " "; cout << endl; } bool is_even(int x) { return x % 2 == 0; } bool is_odd(int x) { return x % 2 != 0; } int square(int x) { return x * x; } int main() { vector<int> a = {1, 3, 5, 7, 9}; list<int> b = {2, 4, 6, 8, 10}; cout << "-- maximum --\n"; auto m1 = maximum(a.begin(), a.end()); cout << *m1 << endl; auto m2 = maximum(b.begin(), b.end()); cout << *m2 << endl; cout << "-- minimum --\n"; auto m3 = minimum(a.begin(), a.end()); cout << *m3 << endl; auto m4 = minimum(b.begin(), b.end()); cout << *m4 << endl; cout << "-- member --\n"; cout << member(a, 1) << endl; cout << member(a, 10) << endl; cout << member(b, 1) << endl; cout << member(b, 10) << endl; cout << member(a.begin(), a.end(), 1) << endl; cout << member(a.begin(), a.end(), 10) << endl; cout << member(b.begin(), b.end(), 1) << endl; cout << member(b.begin(), b.end(), 10) << endl; cout << "-- position--\n"; cout << position(a, 1) << endl; cout << position(a, 10) << endl; cout << position(b, 1) << endl; cout << position(b, 10) << endl; cout << position(a.begin(), a.end(), 1) << endl; cout << position(a.begin(), a.end(), 10) << endl; cout << position(b.begin(), b.end(), 1) << endl; cout << position(b.begin(), b.end(), 10) << endl; cout << "-- count --\n"; cout << count(a, 1) << endl; cout << count(a, 10) << endl; cout << count(b, 1) << endl; cout << count(b, 10) << endl; cout << count(a.begin(), a.end(), 1) << endl; cout << count(a.begin(), a.end(), 10) << endl; cout << count(b.begin(), b.end(), 1) << endl; cout << count(b.begin(), b.end(), 10) << endl; cout << "-- member_if --\n"; cout << member_if(a, is_even) << endl; cout << member_if(a, is_odd) << endl; cout << member_if(b, is_even) << endl; cout << member_if(b, is_odd) << endl; cout << member_if(a.begin(), a.end(), is_even) << endl; cout << member_if(a.begin(), a.end(), is_odd) << endl; cout << member_if(b.begin(), b.end(), is_even) << endl; cout << member_if(b.begin(), b.end(), is_odd) << endl; cout << "-- position_if --\n"; cout << position_if(a, is_even) << endl; cout << position_if(a, is_odd) << endl; cout << position_if(b, is_even) << endl; cout << position_if(b, is_odd) << endl; cout << position_if(a.begin(), a.end(), is_even) << endl; cout << position_if(a.begin(), a.end(), is_odd) << endl; cout << position_if(b.begin(), b.end(), is_even) << endl; cout << position_if(b.begin(), b.end(), is_odd) << endl; cout << "-- count_if --\n"; cout << count_if(a, is_even) << endl; cout << count_if(a, is_odd) << endl; cout << count_if(b, is_even) << endl; cout << count_if(b, is_odd) << endl; cout << count_if(a.begin(), a.end(), is_even) << endl; cout << count_if(a.begin(), a.end(), is_odd) << endl; cout << count_if(b.begin(), b.end(), is_even) << endl; cout << count_if(b.begin(), b.end(), is_odd) << endl; cout << "-- mapcar --\n"; vector<int> c1 = mapcar(a, square); print_seq(c1); list<int> c2 = mapcar(b, square); print_seq(c2); vector<int> d1(a.size()); mapcar(a.begin(), a.end(), square, d1.begin()); print_seq(d1); list<int> d2(b.size()); mapcar(b.begin(), b.end(), square, d2.begin()); print_seq(d2); cout << "-- remove --\n"; vector<int> e1 = {1, 2, 3, 4, 5, 6, 7, 8}; auto iter1 = remove(e1.begin(), e1.end(), 5); for (auto iter = e1.begin(); iter != iter1; ++iter) cout << *iter << " "; cout << endl; auto iter2 = remove_if(e1.begin(), e1.end(), is_even); for (auto iter = e1.begin(); iter != iter2; ++iter) cout << *iter << " "; cout << endl; list<int> e2 = {1, 2, 3, 4, 5, 6, 7, 8}; auto iter3 = remove(e2.begin(), e2.end(), 5); for (auto iter = e2.begin(); iter != iter3; ++iter) cout << *iter << " "; cout << endl; auto iter4 = remove_if(e2.begin(), e2.end(), is_even); for (auto iter = e2.begin(); iter != iter4; ++iter) cout << *iter << " "; cout << endl; cout << "-- fold --\n"; cout << fold_left(a, 0, plus<int>()) << endl; cout << fold_right(a, 0, plus<int>()) << endl; cout << fold_left(b, 0, plus<int>()) << endl; cout << fold_right(b, 0, plus<int>()) << endl; cout << fold(a.begin(), a.end(), 0, plus<int>()) << endl; cout << fold(b.begin(), b.end(), 0, plus<int>()) << endl; cout << "-- any --\n"; cout << any(a, is_even) << endl; cout << any(a, is_odd) << endl; cout << any(b, is_even) << endl; cout << any(b, is_odd) << endl; cout << any(a.begin(), a.end(), is_even) << endl; cout << any(a.begin(), a.end(), is_odd) << endl; cout << any(b.begin(), b.end(), is_even) << endl; cout << any(b.begin(), b.end(), is_odd) << endl; cout << "-- every --\n"; cout << every(a, is_even) << endl; cout << every(a, is_odd) << endl; cout << every(b, is_even) << endl; cout << every(b, is_odd) << endl; cout << every(a.begin(), a.end(), is_even) << endl; cout << every(a.begin(), a.end(), is_odd) << endl; cout << every(b.begin(), b.end(), is_even) << endl; cout << every(b.begin(), b.end(), is_odd) << endl; cout << "-- iota --\n"; vector<int> h1(10); iota(h1, 1); for (int x : h1) cout << x << " "; cout << endl; list<int> h2(10); iota(h2, 11); for (int x : h2) cout << x << " "; cout << endl; cout << "-- tabulate --\n"; vector<int> i1(10); tabulate(i1, 1, square); for (int x : i1) cout << x << " "; cout << endl; list<int> i2(10); tabulate(i2, 11, square); for (int x : i2) cout << x << " "; cout << endl; cout << "-- substitute --\n"; vector<int> j1 = {1, 2, 3, 1, 2, 3, 1, 2, 3}; substitute(2, 4, j1); for (int x : j1) cout << x << " "; cout << endl; substitute(1, 10, j1.begin(), j1.end()); for (int x : j1) cout << x << " "; cout << endl; list<int> j2 = {1, 2, 3, 1, 2, 3, 1, 2, 3}; substitute(2, 4, j2); for (int x : j2) cout << x << " "; cout << endl; substitute(1, 10, j2.begin(), j2.end()); for (int x : j2) cout << x << " "; cout << endl; cout << "-- substitute_if --\n"; vector<int> k1 = {1,2,3,4,5,6,7,8}; substitute_if(is_even, 0, k1); for (int x : k1) cout << x << " "; cout << endl; substitute_if(is_odd, 1, k1.begin(), k1.end()); for (int x : k1) cout << x << " "; cout << endl; list<int> k2 = {1,2,3,4,5,6,7,8}; substitute_if(is_even, 0, k2); for (int x : k2) cout << x << " "; cout << endl; substitute_if(is_odd, 1, k2.begin(), k2.end()); for (int x : k2) cout << x << " "; cout << endl; cout << "-- acons --\n"; list<pair<string, int>> alist; acons("foo", 1, alist); acons("bar", 2, alist); acons("baz", 3, alist); for (auto& p : alist) cout << p.first << "," << p.second << " "; cout << endl; auto aiter1 = assoc("foo", alist.begin(), alist.end()); if (aiter1 != alist.end()) cout << aiter1->second << endl; else cout << "not found\n"; auto aiter2 = assoc("oops", alist.begin(), alist.end()); if (aiter2 != alist.end()) cout << aiter2->second << endl; else cout << "not found\n"; }
$ clang++ yacp3.cpp $ ./a.out -- maximum -- 9 10 -- minimum -- 1 2 -- member -- 1 0 0 1 1 0 0 1 -- position-- 0 -1 -1 4 0 -1 -1 4 -- count -- 1 0 0 1 1 0 0 1 -- member_if -- 0 1 1 0 0 1 1 0 -- position_if -- -1 0 0 -1 -1 0 0 -1 -- count_if -- 0 5 5 0 0 5 5 0 -- mapcar -- 1 9 25 49 81 4 16 36 64 100 1 9 25 49 81 4 16 36 64 100 -- remove -- 1 2 3 4 6 7 8 1 3 7 1 2 3 4 6 7 8 1 3 7 -- fold -- 25 25 30 30 25 30 -- any -- 0 1 1 0 0 1 1 0 -- every -- 0 1 1 0 0 1 1 0 -- iota -- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -- tabulate -- 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 -- substitute -- 1 4 3 1 4 3 1 4 3 10 4 3 10 4 3 10 4 3 1 4 3 1 4 3 1 4 3 10 4 3 10 4 3 10 4 3 -- substitute_if -- 1 0 3 0 5 0 7 0 1 0 1 0 1 0 1 0 1 0 3 0 5 0 7 0 1 0 1 0 1 0 1 0 -- acons -- baz,3 bar,2 foo,1 1 not found