Last active
August 29, 2015 14:07
-
-
Save jbandela/25d85e8b5aba31c1a4cd to your computer and use it in GitHub Desktop.
set_iterators
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 <boost/iterator/iterator_facade.hpp> | |
#include <boost/range/iterator_range.hpp> | |
#include <iterator> | |
#include <utility> | |
template<class Iter1, class Iter2,class Comp> | |
struct set_intersection_iterator:public boost::iterator_facade<set_intersection_iterator<Iter1,Iter2,Comp>,const typename std::iterator_traits<Iter1>::value_type,std::forward_iterator_tag> | |
{ | |
Iter1 begin1_; | |
Iter1 end1_; | |
Iter2 begin2_; | |
Iter2 end2_; | |
Comp comp_; | |
bool at_end_; | |
typedef const typename std::iterator_traits<Iter1>::value_type value_type; | |
set_intersection_iterator(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Comp c = Comp()) :begin1_{ b1 }, end1_{ e1 }, begin2_{ b2 }, end2_{ e2 }, comp_{ c }, at_end_{ false } | |
{ | |
increment(); | |
} | |
set_intersection_iterator() :begin1_{ }, end1_{ }, begin2_{ }, end2_{ }, comp_{ }, at_end_{ true }{} | |
bool equal(const set_intersection_iterator& other) const{ | |
if (at_end_ || other.at_end_){ | |
return other.at_end_ && at_end_; | |
} | |
return begin1_ == other.begin1_ && end1_ == other.end1_ && begin2_ == other.begin2_ && end2_ == other.end2_; | |
} | |
bool check_end()const{ | |
return begin1_ == end1_ || begin2_ == end2_; | |
} | |
void increment(){ | |
if (check_end()){ | |
at_end_ = true; | |
return; | |
} | |
do{ | |
while (!check_end() && comp_(*begin1_, *begin2_)){ | |
++begin1_; | |
} | |
while (!check_end() && comp_(*begin2_, *begin1_)){ | |
++begin2_; | |
} | |
if (check_end()){ | |
at_end_ = true; | |
} | |
} while (!at_end_ && comp_(*begin1_, *begin2_)); | |
assert(at_end_ || *begin1_ == *begin2_); | |
if (check_end()){ | |
at_end_ = true; | |
} | |
else{ | |
++begin2_; | |
} | |
} | |
value_type& dereference()const{ | |
assert(!at_end_); | |
assert(!check_end()); | |
return *begin1_; | |
} | |
}; | |
template<class Iter1, class Iter2, class Comp> | |
struct set_union_iterator :public boost::iterator_facade<set_union_iterator<Iter1, Iter2, Comp>, const typename std::iterator_traits<Iter1>::value_type, std::forward_iterator_tag> | |
{ | |
Iter1 begin1_; | |
Iter1 end1_; | |
Iter2 begin2_; | |
Iter2 end2_; | |
Comp comp_; | |
int select_ = -1; | |
typedef const typename std::iterator_traits<Iter1>::value_type value_type; | |
set_union_iterator(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, Comp c = Comp()) :begin1_{ b1 }, end1_{ e1 }, begin2_{ b2 }, end2_{ e2 }, comp_{ c } | |
{ | |
set_select(); | |
} | |
void set_select(){ | |
if (!check_end()){ | |
if (begin1_ == end1_){ | |
select_ = 2; | |
} | |
else if (begin2_ == end2_){ | |
select_ = 1; | |
} | |
else if (comp_(*begin1_, *begin2_)){ | |
select_ = 1; | |
} | |
else if (comp_(*begin2_, *begin1_)){ | |
select_ = 2; | |
} | |
else{ | |
select_ = 3; | |
} | |
} | |
else{ | |
select_ = -1; | |
} | |
} | |
set_union_iterator() :begin1_{}, end1_{}, begin2_{}, end2_{}, comp_{}{} | |
bool equal(const set_union_iterator& other) const{ | |
if (select_ == -1 || other.select_ == -1){ | |
return other.select_ == select_; | |
} | |
return begin1_ == other.begin1_ && end1_ == other.end1_ && begin2_ == other.begin2_ && end2_ == other.end2_ && select_ == other.select_; | |
} | |
bool check_end()const{ | |
return begin1_ == end1_ && begin2_ == end2_; | |
} | |
void increment(){ | |
if (select_ == 1){ | |
++begin1_; | |
} | |
else if (select_ == 2){ | |
++begin2_; | |
} | |
else if (select_ == 3){ | |
++begin1_; ++begin2_; | |
} | |
set_select(); | |
} | |
value_type& dereference()const{ | |
assert(select_ != -1); | |
assert(!check_end()); | |
if (select_ == 1 || select_ == 3){ | |
return *begin1_; | |
} | |
else{ | |
return *begin2_; | |
} | |
} | |
}; | |
template<class Iter1, class Iter2> | |
boost::iterator_range<set_intersection_iterator<Iter1, Iter2,std::less<typename std::iterator_traits<Iter1>::value_type>>> make_set_intersection_range(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2){ | |
typedef set_intersection_iterator<Iter1, Iter2, std::less<typename std::iterator_traits<Iter1>::value_type>> iter_t; | |
return boost::make_iterator_range(iter_t {b1, e1, b2, e2}, iter_t{}); | |
} | |
template<class C1, class C2> | |
auto make_set_intersection_range(const C1& c1, const C2& c2)->decltype(make_set_intersection_range(c1.begin(),c1.end(),c2.begin(),c2.end())){ | |
return make_set_intersection_range(c1.begin(), c1.end(), c2.begin(), c2.end()); | |
} | |
template<class Iter1, class Iter2> | |
boost::iterator_range<set_union_iterator<Iter1, Iter2, std::less<typename std::iterator_traits<Iter1>::value_type>>> make_set_union_range(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2){ | |
typedef set_union_iterator<Iter1, Iter2, std::less<typename std::iterator_traits<Iter1>::value_type>> iter_t; | |
return boost::make_iterator_range(iter_t{ b1, e1, b2, e2 }, iter_t{}); | |
} | |
template<class C1, class C2> | |
auto make_set_union_range(const C1& c1, const C2& c2)->decltype(make_set_union_range(c1.begin(), c1.end(), c2.begin(), c2.end())){ | |
return make_set_union_range(c1.begin(), c1.end(), c2.begin(), c2.end()); | |
} | |
#include <vector> | |
#include <iostream> | |
template<class V> | |
void print_range(const V& vec){ | |
std::cout << "Printing range\n"; | |
for (auto& v : vec){ | |
std::cout << v << "\n"; | |
} | |
} | |
int main(){ | |
std::vector<int> v1{ 1, 2, 3, 4, 5 }; | |
std::vector<int> v2{ 2, 4, 6, 8 }; | |
std::vector<int> v3{ 1, 3, 5, 9 }; | |
std::vector<int> v4; | |
std::vector<int> v5; | |
auto rng = make_set_intersection_range(v1, v2); | |
auto rng2 = make_set_intersection_range(v1, v3); | |
auto rng3 = make_set_intersection_range(v2, v3); | |
auto rng4 = make_set_union_range(v2, v3); | |
auto rng5 = make_set_union_range(v4, v5); | |
print_range(rng); | |
print_range(rng2); | |
print_range(rng3); | |
print_range(rng4); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment