読者です 読者をやめる 読者になる 読者になる

Range-base ライブラリ

C++

PStade.Oven 風の Range-base ライブラリを作ってみました。


怪しいとこもけっこうあるので(transform_ とか tail_ とか)

ちょこちょこ修正・追加すると思います。




実装方法は以下を参照

extension std::map

result_of 関数オブジェクトの戻り値の型をどう書くか

operator| の汎用化



サンプル

#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