最近心血来潮想在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;
	}
}