Created
July 27, 2014 14:36
-
-
Save ubnt-intrepid/17f5ce786cc52a5df29b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iterator> | |
#include <tuple> | |
template <typename Iterator1, typename Iterator2> | |
struct product2_iterator | |
{ | |
// [first1, last1), [first2, last2) | |
// -> (first1,first2), (first1+1,first2), ... , (last1-1, last2-2), (last1-1, last2-1) | |
private: | |
typedef product2_iterator<Iterator1, Iterator2> self_type ; | |
typedef typename std::iterator_traits<Iterator1>::value_type value1_type; | |
typedef typename std::iterator_traits<Iterator2>::value_type value2_type; | |
typedef std::tuple<Iterator1, Iterator2> iterators ; | |
iterators it_ ; | |
iterators const first_, last_ ; | |
public: | |
explicit product2_iterator( iterators it, iterators first, iterators last ) | |
: it_(it), first_(first), last_(last) | |
{ | |
} | |
inline void operator++() { | |
increment() ; | |
} | |
inline std::tuple<value1_type&, value2_type&> operator*() { | |
return dereference() ; | |
} | |
inline bool operator!=(self_type const& other) const { | |
return compare(other) ; | |
} | |
private: | |
// increment | |
void increment() { | |
if ( ++ std::get<0>(it_) == std::get<0>(last_) ) { | |
if ( ++ std::get<1>(it_) != std::get<1>(last_) ) { | |
std::get<0>(it_) = std::get<0>(first_) ; | |
} | |
} | |
} | |
// dereference | |
std::tuple<value1_type&, value2_type&> dereference() | |
{ | |
return std::tuple<value1_type&, value2_type&>( | |
*std::get<0>(it_), | |
*std::get<1>(it_) | |
); | |
} | |
// compare | |
bool compare(self_type const& other) const { | |
return std::get<0>(it_) != std::get<0>(other.it_) | |
|| std::get<1>(it_) != std::get<1>(other.it_) ; | |
} | |
}; | |
template <typename Iterator1, typename Iterator2> | |
product2_iterator<Iterator1, Iterator2> | |
make_product2_iterator( | |
Iterator1 it1, Iterator2 it2, | |
Iterator1 first1, Iterator2 first2, | |
Iterator1 last1, Iterator2 last2 ) | |
{ | |
return product2_iterator<Iterator1, Iterator2>( | |
std::make_pair(it1, it2), | |
std::make_pair(first1, first2), | |
std::make_pair(last1, last2) | |
) ; | |
} | |
#include <boost/range.hpp> | |
template <typename Range1, typename Range2> | |
class product2_range | |
{ | |
typedef typename boost::range_iterator<Range1>::type iterator1 ; | |
typedef typename boost::range_iterator<Range2>::type iterator2 ; | |
typedef product2_iterator<iterator1, iterator2> iterator_type ; | |
Range1& rng1_ ; | |
Range2& rng2_ ; | |
public: | |
explicit product2_range(Range1& rng1, Range2& rng2) | |
: rng1_(rng1), rng2_(rng2) | |
{ | |
} | |
iterator_type begin() { | |
return make_product2_iterator( | |
std::begin(rng1_), std::begin(rng2_), | |
std::begin(rng1_), std::begin(rng2_), | |
std::end(rng1_), std::end(rng2_)); | |
} | |
iterator_type end() { | |
return make_product2_iterator( | |
std::end(rng1_), std::end(rng2_), | |
std::begin(rng1_), std::begin(rng2_), | |
std::end(rng1_), std::end(rng2_)); | |
} | |
}; | |
template <typename Range1, typename Range2> | |
product2_range<Range1, Range2> product2(Range1& rng1, Range2& rng2) { | |
return product2_range<Range1, Range2>(rng1, rng2) ; | |
} | |
#include <iostream> | |
#include <vector> | |
#include <boost/assign.hpp> | |
int main() | |
{ | |
std::vector<int> a = boost::assign::list_of(1)(2)(3)(4)(5); | |
std::vector<double> b = boost::assign::list_of(6)(7)(8)(9)(10); | |
for (auto item : product2(a, b)) | |
{ | |
std::cout << "(" << std::get<0>(item) << ", " << std::get<1>(item) << ")\n" ; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment