関数オブジェクト @ C++
C++には関数オブジェクトというものがある.
class に operator()
を適当に定義してやれば作ることができ,
これを用いるとパラメタつき関数みたいなものが実現できる.
ここではパラメタつき比較関数(二つの引数をとって,前者が後者より厳密に小さいときtrue
を返す )を実装している.この比較関数は int
型の「大小」を比較するもので,
パラメタeven_regarded_smaller
がtrue
であれば,偶数は奇数より小さいと判断され,偶奇が一致するものは普通の大小関係で比較される.false
であれば奇数が偶数より小さいと判断され,偶奇が一致するものは普通の大小関係で比較される.
下記のコードはC++11で書かれているので, 古いコンパイラで怒られるようであれば適当な書き換えが必要.
#include <iostream> #include <vector> #include <algorithm> #include <numeric> #define say(smth) std::cout << smth << std::endl using namespace std; class ParityFirstComp{ //static public: static bool is_even(const int& n) {return n%2==0;} static bool is_odd (const int& n) {return n%2!=0;} //n%2 can be -1 static bool have_same_parity(const int& m, const int& n){return (n-m)%2==0;} //non-static private: bool even_regarded_smaller; public: ParityFirstComp(bool even_regarded_smaller): even_regarded_smaller(even_regarded_smaller) {} bool compare_by_parity(const int &l, const int& r) const{ if(even_regarded_smaller) return is_even(l) && is_odd (r); else return is_odd (l) && is_even(r); } bool operator()(const int &l, const int& r) const{ if(have_same_parity(l, r)) return l < r; else return compare_by_parity(l, r); } }; template<class T> ostream& operator<< (ostream& strm, const vector<T>& v){ for(auto&& elm : v) strm << elm << ", "; return strm; } int main(){ vector<int> v(10); iota(v.begin(), v.end(), -4); random_shuffle(v.begin(), v.end()); vector<int> u(v); say("original:"); say(v); say("even_regarded_smaller:"); ParityFirstComp even_first_comp(true); sort(v.begin(), v.end(), even_first_comp); say(v); say("odd_regarded_smaller:"); ParityFirstComp odd_first_comp(false); sort(u.begin(), u.end(), odd_first_comp); say(u); return 0; }
出力は次のようになる.(未ソートの結果はrandom_shuffleの実装に依存すると思う)
original: 6, 0, 3, 5, 7, 8, 4, 1, 2, 9, even_regarded_smaller: 0, 2, 4, 6, 8, 1, 3, 5, 7, 9, odd_regarded_smaller: 1, 3, 5, 7, 9, 0, 2, 4, 6, 8,
それっぽい挙動をしている.
2015/8/23 負の整数にも対応できるよう is_odd
を書き換えた.