Created
February 1, 2016 06:22
-
-
Save kimyongin/15d561d24f9094d45c47 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 <boost/range/concepts.hpp> | |
#include <boost/range/iterator_range_core.hpp> | |
#include <algorithm> | |
#include <functional> | |
#include <iostream> | |
#include <vector> | |
// ------------------------------------------------------------- | |
// assign | |
// ------------------------------------------------------------- | |
namespace my | |
{ | |
namespace assign_detail | |
{ | |
template< class C > | |
class call_push_back | |
{ | |
C& c_; | |
public: | |
call_push_back(C& c) : c_(c) | |
{ } | |
template< class T > | |
void operator()(T r) | |
{ | |
c_.push_back(r); | |
} | |
}; | |
struct forward_n_arguments {}; | |
} | |
namespace assign | |
{ | |
template< class Function, class Argument = assign_detail::forward_n_arguments > | |
class list_inserter | |
{ | |
public: | |
list_inserter(Function fun) : insert_(fun) | |
{} | |
template< class T > | |
list_inserter& operator,(const T& r) | |
{ | |
insert_(r); | |
return *this; | |
} | |
template< class T > | |
list_inserter& operator()(const T& t) | |
{ | |
insert_(t); | |
return *this; | |
} | |
private: | |
Function insert_; | |
}; | |
template< class Function, class Argument > | |
inline list_inserter<Function, Argument> | |
make_list_inserter(Function fun, Argument*) | |
{ | |
return list_inserter<Function, Argument>(fun); | |
} | |
template< class C > | |
inline list_inserter< assign_detail::call_push_back<C>, typename C::value_type > | |
push_back(C& c) | |
{ | |
static typename C::value_type* p = 0; | |
return make_list_inserter(assign_detail::call_push_back<C>(c), p); | |
} | |
template< class V, class A, class V2 > | |
inline list_inserter< assign_detail::call_push_back< std::vector<V, A> >, V > | |
operator+=(std::vector<V, A>& c, V2 v) | |
{ | |
return push_back(c)(v); | |
} | |
} | |
} | |
// ------------------------------------------------------------- | |
// holder | |
// ------------------------------------------------------------- | |
namespace my | |
{ | |
namespace range_detail | |
{ | |
template< class T > | |
struct holder | |
{ | |
T val; | |
holder(T t) : val(t) | |
{ } | |
}; | |
template< class T > | |
struct adjacent_holder : holder<T> | |
{ | |
adjacent_holder(T r) : holder<T>(r) | |
{ } | |
}; | |
template< template<class> class Holder > | |
struct forwarder | |
{ | |
template< class T > | |
Holder<T> operator()(T t) const | |
{ | |
return Holder<T>(t); | |
} | |
}; | |
} | |
namespace adaptors | |
{ | |
namespace | |
{ | |
const range_detail::forwarder<range_detail::adjacent_holder> | |
adjacent_filtered = | |
range_detail::forwarder<range_detail::adjacent_holder>(); | |
} | |
} | |
} | |
// ------------------------------------------------------------- | |
// iterator | |
// ------------------------------------------------------------- | |
namespace my | |
{ | |
namespace range_detail | |
{ | |
using namespace boost; | |
// ------------------------------------------------------------- | |
// skip_iterator | |
// ------------------------------------------------------------- | |
template< class Iter, class Pred, bool default_pass > | |
class skip_iterator | |
: public boost::iterator_adaptor< | |
skip_iterator<Iter, Pred, default_pass>, | |
Iter, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type, | |
boost::forward_traversal_tag, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type | |
> | |
, private Pred | |
{ | |
private: | |
typedef boost::iterator_adaptor< | |
skip_iterator<Iter, Pred, default_pass>, | |
Iter, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type, | |
boost::forward_traversal_tag, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference, | |
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type | |
> base_t; | |
public: | |
typedef Pred pred_t; | |
typedef Iter iter_t; | |
skip_iterator() : m_last() {} | |
skip_iterator(iter_t it, iter_t last, const Pred& pred) | |
: base_t(it) | |
, pred_t(pred) | |
, m_last(last) | |
{ | |
} | |
template<class OtherIter> | |
skip_iterator(const skip_iterator<OtherIter, pred_t, default_pass>& other) | |
: base_t(other.base()) | |
, pred_t(other) | |
, m_last(other.m_last) | |
{ | |
} | |
void increment() | |
{ | |
iter_t& it = this->base_reference(); | |
BOOST_ASSERT(it != m_last); | |
pred_t& bi_pred = *this; | |
iter_t prev = it; | |
++it; | |
if (it != m_last) | |
{ | |
if (default_pass) | |
{ | |
while (it != m_last && !bi_pred(*prev, *it)) | |
{ | |
++it; | |
++prev; | |
} | |
} | |
else | |
{ | |
for (; it != m_last; ++it, ++prev) | |
{ | |
if (bi_pred(*prev, *it)) | |
{ | |
break; | |
} | |
} | |
} | |
} | |
} | |
iter_t m_last; | |
}; | |
// ------------------------------------------------------------- | |
// adjacent_filtered_range | |
// ------------------------------------------------------------- | |
template< class P, class R, bool default_pass > | |
struct adjacent_filtered_range | |
: iterator_range< skip_iterator<BOOST_DEDUCED_TYPENAME range_iterator<R>::type, P, default_pass>> | |
{ | |
private: | |
typedef skip_iterator<BOOST_DEDUCED_TYPENAME range_iterator<R>::type, P, default_pass> skip_iter; | |
typedef iterator_range<skip_iter> base_range; | |
typedef BOOST_DEDUCED_TYPENAME range_iterator<R>::type raw_iterator; | |
public: | |
adjacent_filtered_range(const P& p, R& r) | |
: base_range(skip_iter(boost::begin(r), boost::end(r), p), | |
skip_iter(boost::end(r), boost::end(r), p)) | |
{ | |
} | |
}; | |
template< class ForwardRng, class BinPredicate > | |
inline adjacent_filtered_range<BinPredicate, ForwardRng, true> | |
operator|(ForwardRng& r, const adjacent_holder<BinPredicate>& f) | |
{ | |
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>)); | |
return adjacent_filtered_range<BinPredicate, ForwardRng, true>(f.val, r); | |
} | |
} | |
} | |
int main() | |
{ | |
using namespace my::assign; | |
using namespace my::adaptors; | |
// TEST 1 | |
std::cout << "\nTEST 1 ================================" << std::endl; | |
std::vector<int> input; | |
input += 1, 1, 2, 2, 2, 3, 4, 5, 6; | |
for (auto item : input){ | |
std::cout << item << std::endl; | |
} | |
// TEST 2 | |
std::cout << "\nTEST 2 ================================" << std::endl; | |
auto filter = adjacent_filtered(std::not_equal_to<int>()); | |
std::cout << filter.val(1, 1) << std::endl; | |
std::cout << filter.val(0, 1) << std::endl; | |
// TEST 3 | |
std::cout << "\nTEST 3 ================================" << std::endl; | |
auto filtered_output_iterator = input | filter; | |
for (auto filterdItem : filtered_output_iterator) { | |
std::cout << filterdItem << std::endl; | |
} | |
// TEST 4 | |
std::cout << "\nTEST 4 ================================" << std::endl; | |
std::copy(std::begin(filtered_output_iterator), | |
std::end(filtered_output_iterator), | |
std::ostream_iterator<int>(std::cout, ",")); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment