Skip to content

Instantly share code, notes, and snippets.

@hidez8891
Created January 22, 2016 11:10
Show Gist options
  • Save hidez8891/c9c7acc423f2475a6dec to your computer and use it in GitHub Desktop.
Save hidez8891/c9c7acc423f2475a6dec to your computer and use it in GitHub Desktop.
C++ pipe stream
#include <iterator>
#include <type_traits>
#include <vector>
#include <algorithm>
// operator
template <typename C, typename F>
auto operator| (C c, F f)
{
return f(c.begin(), c.end());
}
// accumulator
template <template <class E, class A = std::allocator<E>> class C>
struct to_
{
template <typename Itr, typename T = typename Itr::value_type>
C<T> operator() (Itr begin, Itr end)
{
C<T> container;
std::back_insert_iterator<C<T>> it(container);
std::copy(begin, end, it);
return container;
}
};
// accumulator to vector
auto to_vec()
{
return to_<std::vector>();
}
// range :: generator
template <typename T>
struct range_stream_iterator
: public std::iterator<std::input_iterator_tag, T>
{
range_stream_iterator(T s, T e)
: s(s), e(e) {}
range_stream_iterator(const range_stream_iterator& obj)
: s(obj.s), e(obj.e) {}
auto& operator++() { if(s <= e) ++s; return *this; }
auto operator* () { return s; }
bool operator== (const range_stream_iterator& obj) { return s == obj.s; }
bool operator!= (const range_stream_iterator& obj) { return !(*this == obj); }
private:
T s, e;
};
template <typename T>
struct range_stream
{
range_stream(T s, T e)
: s(s), e(e) {}
auto begin() const { return range_stream_iterator<T>(s, e); }
auto end() const { return range_stream_iterator<T>(e+1, e); }
private:
T s, e;
};
template <typename T>
auto range_(T start, T end)
{
return range_stream<T>(start, end);
}
// map :: partial evaluater
template <typename F, typename Itr>
struct map_stream_iterator
: public std::iterator<
std::input_iterator_tag,
typename std::result_of<F(typename Itr::value_type)>::type>
{
map_stream_iterator(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) {}
map_stream_iterator(const map_stream_iterator& obj)
: f(obj.f), itr1(obj.itr1), itr2(obj.itr2) {}
auto& operator++() { if(itr1 != itr2) ++itr1; return *this; }
auto operator* () { return f(*itr1); }
bool operator== (const map_stream_iterator& obj) { return itr1 == obj.itr1; }
bool operator!= (const map_stream_iterator& obj) { return !(*this == obj); }
private:
F f;
Itr itr1, itr2;
};
template <typename F, typename Itr>
struct map_stream
{
map_stream(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) {}
auto begin() const { return map_stream_iterator<F, Itr>(f, itr1, itr2); }
auto end() const { return map_stream_iterator<F, Itr>(f, itr2, itr2); }
private:
F f;
Itr itr1, itr2;
};
template <typename F>
auto map_(F f)
{
return [f](auto itr1, auto itr2) {
return map_stream<F, decltype(itr1)>(f, itr1, itr2);
};
}
// select :: partial evaluater
template <typename F, typename Itr>
struct select_stream_iterator
: public std::iterator<std::input_iterator_tag, typename Itr::value_type>
{
select_stream_iterator(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) { valid(); }
select_stream_iterator(const select_stream_iterator& obj)
: f(obj.f), itr1(obj.itr1), itr2(obj.itr2) { valid(); }
auto& operator++() { if(itr1 != itr2) { ++itr1; valid(); } return *this; }
auto operator* () { return *itr1; }
bool operator== (const select_stream_iterator& obj) { return itr1 == obj.itr1; }
bool operator!= (const select_stream_iterator& obj) { return !(*this == obj); }
void valid() { while (itr1 != itr2 && !f(*itr1)) ++itr1; }
private:
F f;
Itr itr1, itr2;
};
template <typename F, typename Itr>
struct select_stream
{
select_stream(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) {}
auto begin() const { return select_stream_iterator<F, Itr>(f, itr1, itr2); }
auto end() const { return select_stream_iterator<F, Itr>(f, itr2, itr2); }
private:
F f;
Itr itr1, itr2;
};
template <typename F>
auto select_(F f)
{
return [f](auto itr1, auto itr2) {
return select_stream<F, decltype(itr1)>(f, itr1, itr2);
};
}
// head :: partial evaluater
template <typename Itr>
struct head_stream
{
head_stream(unsigned n, Itr itr1, Itr itr2)
: n(n), itr1(itr1), itr2(itr2) {}
auto begin() const { return itr1; }
auto end() const {
auto itr(itr1);
for (int i = 0; i < n && itr != itr2; ++i, ++itr);
return itr;
}
private:
unsigned n;
Itr itr1, itr2;
};
auto head_(unsigned n)
{
return [n](auto itr1, auto itr2) {
return head_stream<decltype(itr1)>(n, itr1, itr2);
};
}
// take :: partial evaluater
auto take_(unsigned n)
{
return head_(n);
}
// take_while :: partial evaluater
template <typename F, typename Itr>
struct take_while_stream
{
take_while_stream(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) {}
auto begin() const { return itr1; }
auto end() const {
auto itr(itr1);
while (itr != itr2 && f(*itr)) ++itr;
return itr;
}
private:
F f;
Itr itr1, itr2;
};
template <typename F>
auto take_while_(F f)
{
return [f](auto itr1, auto itr2) {
return take_while_stream<F, decltype(itr1)>(f, itr1, itr2);
};
}
// drop :: partial evaluater
template <typename Itr>
struct drop_stream
{
drop_stream(unsigned n, Itr itr1, Itr itr2)
: n(n), itr1(itr1), itr2(itr2) {}
auto begin() const {
auto itr(itr1);
for (int i = 0; i < n && itr != itr2; ++i, ++itr);
return itr;
}
auto end() const { return itr2; }
private:
unsigned n;
Itr itr1, itr2;
};
auto drop_(unsigned n)
{
return [n](auto itr1, auto itr2) {
return drop_stream<decltype(itr1)>(n, itr1, itr2);
};
}
// drop_while :: partial evaluater
template <typename F, typename Itr>
struct drop_while_stream
{
drop_while_stream(F f, Itr itr1, Itr itr2)
: f(f), itr1(itr1), itr2(itr2) {}
auto begin() const {
auto itr(itr1);
while (itr != itr2 && f(*itr)) ++itr;
return itr;
}
auto end() const { return itr2; }
private:
F f;
Itr itr1, itr2;
};
template <typename F>
auto drop_while_(F f)
{
return [f](auto itr1, auto itr2) {
return drop_while_stream<F, decltype(itr1)>(f, itr1, itr2);
};
}
// tail :: partial evaluater
auto tail_(unsigned n)
{
return [n](auto itr1, auto itr2) {
auto n2 = std::distance(itr1, itr2) - n;
if (n2 < 0) n2 = 0;
return drop_stream<decltype(itr1)>(n2, itr1, itr2);
};
}
// each :: whole evaluater
template <typename F>
auto each_(F f)
{
return [f](auto itr1, auto itr2) {
std::vector<typename decltype(itr1)::value_type> v(itr1, itr2);
std::for_each(v.begin(), v.end(), f);
return v;
};
}
// sort :: whole evaluater
auto sort_()
{
return [](auto itr1, auto itr2) {
std::vector<typename decltype(itr1)::value_type> v(itr1, itr2);
std::sort(v.begin(), v.end());
return v;
};
}
// reverse :: whole evaluater
auto reverse_()
{
return [](auto itr1, auto itr2) {
std::vector<typename decltype(itr1)::value_type> v(itr1, itr2);
std::reverse(v.begin(), v.end());
return v;
};
}
/**************************************
test code
***************************************/
#include <boost/lambda/lambda.hpp>
#include <iostream>
using boost::lambda::_1;
int main()
{
// select odd, take 5
range_(1, 10000)
| select_(_1 % 2 == 1)
| take_(5)
| each_(std::cout << _1 << "\n");
// get 5th - 9th number
range_(1, 10000)
| map_(_1 * 2)
| head_(9)
| drop_(4)
| each_(std::cout << _1 << "\n");
// use foreach
auto r = range_(1, 10000)
| map_(_1 * 2)
| head_(9)
| drop_(4);
std::for_each(r.begin(), r.end(), std::cout << _1 << "\n");
// to save vector
auto v = r | to_vec();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment