PStade.Oven 風の Range-base ライブラリを作ってみました。
怪しいとこもけっこうあるので(transform_ とか tail_ とか)
ちょこちょこ修正・追加すると思います。
実装方法は以下を参照
result_of 関数オブジェクトの戻り値の型をどう書くか
サンプル
#include <iostream> #include <vector> #include <list> #include <string> #include <sstream> #include <shand/range.hpp> #include <boost/lambda/lambda.hpp> using namespace std; using namespace shand; using namespace boost::lambda; // transform_用 string to_string(int value) { stringstream ss; ss << value; return ss.str(); } int main() { vector<int> v; v.push_back(3); v.push_back(1); v.push_back(2); v.push_back(1); // for_each_ : 全要素に処理 v|for_each_(cout << _1 << "\n"); // 3, 1, 2, 1 // sort_ : 並び替え v|sort_|for_each_(cout << _1 << "\n"); // 1, 1, 2, 3 // sort_(Compare) : 並び替え(高階関数) v|sort_(_1 < _2)|for_each_(cout << _1 << "\n"); // 1, 1, 2, 3 // reverse_ : 逆順 v|reverse_|for_each_(cout << _1 << "\n"); // 1, 2, 1, 3 // transform_ : 全要素に操作, 変換 v|transform_(to_string)|for_each_(cout << _1 << "\n"); // 3, 1, 2, 1 // v|transform_(_1 + 1)|for_each_(cout << _1 << "\n"); // 4, 2, 3, 2 ...今はまだできない // filter_ : 条件一致した要素を抽出 v|filter_(_1 % 2 != 0)|for_each_(cout << _1 << "\n"); // 3, 1, 1 // take_ : 先頭 N 個の要素取得 v|take_(3)|for_each_(cout << _1 << "\n"); // 3, 1, 2 // take_while_ : 先頭から条件一致している間の要素取得 v|take_while_(_1 % 2 != 0)|for_each_(cout << _1 << "\n"); // 3, 1 // drop_ : 先頭 N 個を読み飛ばす v|drop_(1)|for_each_(cout << _1 << "\n"); // 1, 2, 1 // drop_while_ : 先頭から条件一致している間の要素を読み飛ばす v|drop_while_(_1 % 2 != 0)|for_each_(cout << _1 << "\n"); // 2, 1 // unique_ : 重複なしリスト作成 v|sort_|unique_|for_each_(cout << _1 << "\n"); // 1, 2, 3 // copy_ : 他のコンテナへ変換 list<int> ls = v|copy_; ls|for_each_(cout << _1 << "\n"); // 3, 1, 2, 1 // find_ : 検索 const vector<int>& cv = v; vector<int>::iterator pos = v|find_(1); vector<int>::const_iterator cpos = cv|find_(1); // find_if_ : 検索(高階関数) vector<int>::iterator pos_if = v|find_if_(_1 == 1); vector<int>::const_iterator cpos_if = cv|find_if_(_1 == 1); // has_ : 検索 bool has_one = v|has_(1); cout << has_one << endl; // true // has_if_ : 検索(高階関数) bool has_one_if = v|has_if_(_1 == 1); cout << has_one_if << endl; // true // head_, front_ : 先頭要素取得 cout << (v|head_) << endl; // 3 cout << (v|front_) << endl; // 3 // tail_ : 先頭以外のリスト取得 v|tail_|for_each_(cout << _1 << "\n"); // 1, 2, 1 // back_ : 最後尾要素取得 cout << (v|back_) << endl; // 1 // count_ : 要素数取得 int count = v|count_; cout << count << endl; // 4 // is_empty_ : リストが空か判断 bool is_empty = v|is_empty_; cout << is_empty << endl; // false // sum_ : 合計値計算 int sum = v|sum_; cout << sum << endl; // 7 // average_ : 平均値計算 double average = v|average_; cout << average << endl; // 1.75 // max_ : 最大値取得 cout << (v|max_) << endl; // 3 // min_ : 最小値取得 cout << (v|min_) << endl; // 1 // make_range : range 作成 make_range(0, 10)|for_each_(cout << _1 << "\n"); // 0, 1, ... 9 return 0; }
以下、ソース
#ifndef SHAND_RANGE_INCLUDE #define SHAND_RANGE_INCLUDE #include <functional> // std::tr1::result_of #include <type_traits> // std::tr1::remove_cv, std::tr1::remove_reference // TR1ライブラリがない環境では↑の代わりにこっち //#include <boost/tr1/functional.hpp> //#include <boost/tr1/type_traits.hpp> #include <numeric> // std::accumulate #include <algorithm> #include <vector> namespace shand { namespace range { // range_iterator template <class Container> struct range_iterator { typedef typename Container::iterator type; }; template <class Container> struct range_iterator< const Container > { typedef typename Container::const_iterator type; }; template <class T, std::size_t N> struct range_iterator< T[N] > { typedef T* type; }; template <class T, std::size_t N> struct range_iterator< const T[N] > { typedef const T* type; }; template<> struct range_iterator< char* > { typedef char* type; }; // range_value template <class Container> struct range_value { typedef typename Container::value_type type; }; template <class T, std::size_t N> struct range_value< T[N] > { typedef T type; }; // begin template <class Container> inline typename Container::iterator begin(Container& c) { return c.begin(); } template <class Container> inline typename Container::const_iterator begin(const Container& c) { return c.begin(); } template <class T, int N> inline T* begin(T (&ar)[N]) { return ar; } // end template <class Container> inline typename Container::iterator end(Container& c) { return c.end(); } template <class Container> inline typename Container::const_iterator end(const Container& c) { return c.end(); } template <class T, std::size_t N> inline T* end(T (&ar)[N]) { return ar + N; } // result_type template <class Signature> struct argument_of; template <class R, class Arg> struct argument_of<R(Arg)> { typedef Arg type; }; template <class T> class copy_argument { typedef typename argument_of<T>::type argument_type; typedef typename std::tr1::remove_cv<argument_type>::type non_cv_type; typedef typename std::tr1::remove_reference<non_cv_type>::type non_reference_type; public: typedef non_reference_type type; }; template <class Signature> struct argument_vector { typedef std::vector<typename range_value<typename copy_argument<Signature>::type>::type> type; }; template <class Range> struct result_vector { typedef std::vector<typename range_value<Range>::type> type; }; // count_ struct count_t { typedef std::size_t result_type; template <class Range> std::size_t call(const Range& r) const { return std::distance(begin(r), end(r)); } }; const count_t count_ = {}; // is_empty_ struct is_empty_t { typedef bool result_type; template <class Range> bool call(const Range& r) const { return (r|count_) == 0; } }; const is_empty_t is_empty_ = {}; // sort_ template <class Compare> class comp_sort_t { Compare comp_; public: template <class Signature> struct result : public copy_argument<Signature> {}; comp_sort_t(Compare comp) : comp_(comp) {} template <class Range> Range call(const Range& r) const { Range result(r); std::sort(begin(result), end(result), comp_); return result; } }; class sort_t { public: template <class Signature> struct result : public copy_argument<Signature> {}; template <class Range> Range call(const Range& r) const { Range result(r); std::sort(begin(result), end(result)); return result; } template <class Compare> comp_sort_t<Compare> operator()(Compare comp) const { return comp_sort_t<Compare>(comp); } }; const sort_t sort_ = {}; // reverse struct reverse_t { template <class Signature> struct result : public copy_argument<Signature> {}; template <class Range> Range call(const Range& r) const { Range result(r); std::reverse(begin(result), end(result)); return result; } }; const reverse_t reverse_ = {}; // transform_ template <class Range, class Func> class transform_result { typedef typename range_value<Range>::type argument_type; typedef typename std::tr1::result_of<Func(argument_type)>::type func_result_type; public: typedef std::vector<func_result_type> type; }; template <class Func> class transform_t { Func func_; public: transform_t(Func func) : func_(func) {} template <class Signature> struct result : public transform_result<typename copy_argument<Signature>::type, Func> {}; template <class Range> typename transform_result<Range, Func>::type call(const Range& r) const { typename transform_result<Range, Func>::type result; std::transform(begin(r), end(r), std::back_inserter(result), func_); return result; } }; template <class Func> inline transform_t<Func> transform_(Func func) { return func; } // for_each_ template <class Func> class for_each_t { Func func_; public: for_each_t(Func func) : func_(func) {} typedef void result_type; template <class Range> void call(const Range& r) const { for_each(begin(r), end(r), func_); } template <class Range> void call(Range& r) const { for_each(begin(r), end(r), func_); } }; template <class Func> inline for_each_t<Func> for_each_(Func func) { return func; } // filter_ template <class Predicate> class filter_t { Predicate pred_; public: filter_t(Predicate pred) : pred_(pred) {} template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; for (typename range_iterator<const Range>::type first = begin(r), last = end(r); first != last; ++first) { if (pred_(*first)) result.push_back(*first); } return result; } }; template <class Predicate> inline filter_t<Predicate> filter_(Predicate pred) { return pred; } // take_ class take_ { std::size_t count_; public: explicit take_(std::size_t count) : count_(count) {} template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; take(begin(r), end(r), std::back_inserter(result), count_); return result; } template <class InputIterator, class OutputIterator> static void take(InputIterator first, InputIterator last, OutputIterator result, std::size_t count) { while (first != last && count-- > 0) { *result = *first; ++result; ++first; } } }; // take_while_ template <class Predicate> class take_while_t { Predicate pred_; public: take_while_t(Predicate pred) : pred_(pred) {} template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; take_while(begin(r), end(r), std::back_inserter(result), pred_); return result; } template <class InputIterator, class OutputIterator, class Predicate_> static void take_while(InputIterator first, InputIterator last, OutputIterator result, Predicate_ pred) { while (first != last && pred(*first)) { *result = *first; ++result; ++first; } } }; template <class Predicate> inline take_while_t<Predicate> take_while_(Predicate pred) { return pred; } // drop_ class drop_ { std::size_t count_; public: explicit drop_(std::size_t count) : count_(count) {} template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; drop(begin(r), end(r), std::back_inserter(result), count_); return result; } template <class InputIterator, class OutputIterator> static void drop(InputIterator first, InputIterator last, OutputIterator result, std::size_t count) { while (first != last && count > 0) { ++first; --count; } while (first != last) { *result = *first; ++result; ++first; } } }; // drop_while_ template <class Predicate> class drop_while_t { Predicate pred_; public: drop_while_t(Predicate pred) : pred_(pred) {} template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; drop_while(begin(r), end(r), std::back_inserter(result), pred_); return result; } template <class InputIterator, class OutputIterator, class Predicate_> static void drop_while(InputIterator first, InputIterator last, OutputIterator result, Predicate_ pred) { while (first != last && pred(*first)) { ++first; } while (first != last) { *result = *first; ++result; ++first; } } }; template <class Predicate> inline drop_while_t<Predicate> drop_while_(Predicate pred) { return pred; } // unique_ struct unique_t { template <class Signature> struct result : public argument_vector<Signature> {}; template <class Range> typename result_vector<Range>::type call(const Range& r) const { typename result_vector<Range>::type result; std::unique_copy(begin(r), end(r), std::back_inserter(result)); return result; } }; const unique_t unique_ = {}; // copy_ template <class T> class container_converter { std::vector<T> elements_; public: typedef T value_type; typedef T& reference; typedef const T& const_reference; void push_back(const T& value) { elements_.push_back(value); } template <class U> operator U() const { return U(elements_.begin(), elements_.end()); } }; struct copy_t { template <class Signature> class result { typedef typename copy_argument<Signature>::type range_type; public: typedef container_converter<typename range_value<range_type>::type> type; }; template <class Range> container_converter<typename range_value<Range>::type> call(const Range& r) const { container_converter<typename range_value<Range>::type> result; std::copy(begin(r), end(r), std::back_inserter(result)); return result; } }; const copy_t copy_ = {}; // find_ template <class T> class find_t { const T& value_; public: find_t(const T& value) : value_(value) {} template <class Signature> class result { typedef typename argument_of<Signature>::type argument_type; typedef typename std::tr1::remove_reference<argument_type>::type non_ref_type; public: typedef typename range_iterator<non_ref_type>::type type; }; template <class Range> typename range_iterator<Range>::type call(Range& r) const { return std::find(begin(r), end(r), value_); } template <class Range> typename range_iterator<const Range>::type call(const Range& r) const { return std::find(begin(r), end(r), value_); } }; template <class T> inline find_t<T> find_(const T& value) { return value; } // find_if_ template <class Predicate> class find_if_t { Predicate pred_; public: find_if_t(Predicate pred) : pred_(pred) {} template <class Signature> class result { typedef typename argument_of<Signature>::type argument_type; typedef typename std::tr1::remove_reference<argument_type>::type non_ref_type; public: typedef typename range_iterator<non_ref_type>::type type; }; template <class Range> typename range_iterator<Range>::type call(Range& r) const { return std::find_if(begin(r), end(r), pred_); } template <class Range> typename range_iterator<const Range>::type call(const Range& r) const { return std::find_if(begin(r), end(r), pred_); } }; template <class Predicate> inline find_if_t<Predicate> find_if_(Predicate pred) { return pred; } // has_ template <class T> class has_t { const T& value_; public: has_t(const T& value) : value_(value) {} typedef bool result_type; template <class Range> bool call(const Range& r) const { return std::find(begin(r), end(r), value_) != end(r); } }; template <class T> inline has_t<T> has_(const T& value) { return value; } // has_if_ template <class Predicate> class has_if_t { Predicate pred_; public: has_if_t(Predicate pred) : pred_(pred) {} typedef bool result_type; template <class Range> bool call(const Range& r) const { return std::find_if(begin(r), end(r), pred_) != end(r); } }; template <class Predicate> inline has_if_t<Predicate> has_if_(Predicate pred) { return pred; } // tail_ struct tail_t { template <class Signature> struct result : public copy_argument<Signature> {}; template <class Range> Range call(const Range& r) const { if (r|is_empty_) return r; Range result(r); result.erase(begin(result)); return result; } }; const tail_t tail_ = {}; // front_ struct front_t { template <class Signature> struct result { typedef typename range_value<typename copy_argument<Signature>::type>::type type; }; template <class Range> typename range_value<Range>::type call(const Range& r) const { return *begin(r); } }; const front_t front_ = {}; const front_t head_ = {}; // back_ struct back_t { template <class Signature> struct result { typedef typename range_value<typename copy_argument<Signature>::type>::type type; }; template <class Range> typename range_value<Range>::type call(const Range& r) const { return *back_iterator(begin(r), end(r)); } template <class Iterator> static Iterator back_iterator(Iterator first, Iterator last) { std::size_t size = std::distance(first, last); for (std::size_t i = 0; i < size -1; ++i) { ++first; } return first; } }; const back_t back_ = {}; // sum_ struct sum_t { template <class Signature> struct result { typedef typename range_value<typename copy_argument<Signature>::type>::type type; }; template <class Range> typename range_value<Range>::type call(const Range& r) const { return std::accumulate(begin(r), end(r), range_value<Range>::type()); } }; const sum_t sum_ = {}; // average_ struct average_t { typedef double result_type; template <class Range> double call(const Range& r) const { std::size_t size = r|count_; return size == 0 ? 0 : static_cast<double>((r|sum_)) / size; } }; const average_t average_ = {}; // min_ struct min_t { template <class Signature> struct result { typedef typename range_value<typename copy_argument<Signature>::type>::type type; }; template <class Range> typename range_value<Range>::type call(const Range& r) const { return *std::min_element(begin(r), end(r)); } }; const min_t min_ = {}; // max_ struct max_t { template <class Signature> struct result { typedef typename range_value<typename copy_argument<Signature>::type>::type type; }; template <class Range> typename range_value<Range>::type call(const Range& r) const { return *std::max_element(begin(r), end(r)); } }; const max_t max_ = {}; // make_range template <class Incrementable> inline std::vector<Incrementable> make_range(Incrementable from, Incrementable to) { std::vector<Incrementable> result; while (from != to) { result.push_back(from++); } return result; } // operator| template <class Range, class Func> inline typename std::tr1::result_of<Func(Range&)>::type operator|(Range& r, Func f) { return f.call(r); } template <class Range, class Func> inline typename std::tr1::result_of<Func(const Range&)>::type operator|(const Range& r, Func f) { return f.call(r); } } // namespace range using range::count_; using range::is_empty_; using range::sort_; using range::reverse_; using range::transform_; using range::for_each_; using range::filter_; using range::take_; using range::take_while_; using range::drop_; using range::drop_while_; using range::unique_; using range::copy_; using range::find_; using range::find_if_; using range::has_; using range::has_if_; using range::head_; using range::tail_; using range::front_; using range::back_; using range::sum_; using range::average_; using range::min_; using range::max_; using range::make_range; } // namespace shand #endif // SHAND_RANGE_INCLUDE