C++ zip实现

最近心血来潮想在C++里实现一些像在python里一样好用的小组件,主要是希望充分发挥C++11for循环的威力。在完成了enumerate之后,在zip的完成上用了比较久的时间。

在这里记录下来自己对zip的简单实现。

主要就用了模板递归,结合了一些C++11的新特性完成的。

#pragma once

namespace twistoy {
    template<typename first, typename... last>
    class zip_iterator {
    public:
        using value_type = std::tuple<typename first::reference, typename last::reference...>;
        using rebind = zip_iterator<first, last...>;
        using sub_iterator = zip_iterator<last...>;
    private:
        first it_;
        sub_iterator sub_it_;
    public:

        zip_iterator(first it, sub_iterator sub_it) : it_(it), sub_it_(sub_it) {}

        rebind& operator++() {
            ++it_;
            ++sub_it_;
            return *this;
        }

        value_type operator *() {
            return std::tuple_cat(std::tuple<typename first::reference>(*it_), *sub_it_);
        }

        bool operator != (const rebind& others) const {
            return (it_ != others.it_) && (sub_it_ != others.sub_it_);
        }

    };

    template<typename first>
    class zip_iterator<first> {
    public:
        using value_type = std::tuple<typename first::reference>;
        using rebind = zip_iterator<first>;
    private:
        first it_;
    public:
        zip_iterator(first it) : it_(it) {}
        value_type operator *() {
            return value_type(*it_);
        }
        rebind& operator++() {
            ++it_;
            return *this;
        }
        bool operator != (const rebind& others) const {
            return it_ != others.it_;
        }
    };

    template<typename first, typename... last>
    class zip_impl : zip_impl<last...> {
    public:
        using iterator = zip_iterator<typename first::iterator, typename last::iterator...>;
    private:
        first& value_;
    public:
        zip_impl(first& value, last&... args) : value_(value), zip_impl<last...>(args...) {}
        iterator begin() {
            return iterator(value_.begin(), zip_impl<last...>::begin());
        }
        iterator end() {
            return iterator(value_.end(), zip_impl<last...>::end());
        }
    };

    template<typename first>
    class zip_impl<first> {
    public:
        using iterator = zip_iterator<typename first::iterator>;
    private:
        first& value_;
    public:
        zip_impl(first& value) : value_(value) {}
        iterator begin() {
            return iterator(value_.begin());
        }
        iterator end() {
            return iterator(value_.end());
        }
    };

    template<typename... args_t>
    zip_impl<typename std::decay<args_t>::type...> zip(args_t&... args) {
        zip_impl<typename std::decay<args_t>::type...> tmp(args...);
        return tmp;
    }
}
Comments
Write a Comment