Skip to content

Instantly share code, notes, and snippets.

@VeganPower
Last active May 5, 2018 14:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VeganPower/b5055d9e746b49ba3201f81470c077fc to your computer and use it in GitHub Desktop.
Save VeganPower/b5055d9e746b49ba3201f81470c077fc to your computer and use it in GitHub Desktop.
operator = inheritance
#pragma once
#include <type_traits>
#include <functional>
#include "function_traits.hpp"
template<typename T>
struct ViewTraits
{
typedef decltype(std::declval<T>().read()) ViewValue_t;
};
template<typename T>
void advance_to_first_valid(T& f)
{
while(!f.done() && !std::invoke(f.pred, f.read()))
{
f.next();
}
}
template<typename View_t, typename Pred_t>
struct FilterFun : View_t
{
typedef typename ViewTraits<View_t>::ViewValue_t ViewValue_t;
// typedef typename std::function<bool(ViewValue_t)> Pred_t;
FilterFun(View_t const& v, Pred_t p)
: View_t(v)
, pred(p)
{
advance_to_first_valid(*this);
}
void next()
{
View_t::next();
advance_to_first_valid(*this);
}
Pred_t pred;
};
template<typename T>
struct FilterOp
{
std::function<bool(T)> params;
};
template<typename T>
auto filter(T const& p)
{
// static_assert(std::is_convertible_v<T, std::function>);
// static_assert(std::is_function_v<T>); // doesn't works with lambdas
typedef function_traits<T> PredTraits;
static_assert(PredTraits::arity == 1);
typedef typename PredTraits::template arg<0>::type Filter_type;
return FilterOp<Filter_type> { p };
}
template<typename View_t, typename T>
auto operator |(View_t const& right, FilterOp<T> const& left)
{
return FilterFun<View_t, decltype(left.params)>(right, left.params);
}
#pragma once
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
#include "containers/static_array.h"
#include <iostream>
#include <functional>
#include "filter.hpp"
template<typename T>
struct ValueRef
{
ValueRef& operator =(T x){
v = x;
return *this;
}
T& v;
};
template<typename T>
struct PlainView
{
T* cursor = nullptr;
T const* sentinel = nullptr;
void next()
{
cursor++;
}
PlainView& operator =(int x)
{
*cursor = x;
return *this;
}
operator ValueRef<T>()
{
return ValueRef<T> {*cursor};
}
operator T() const
{
return *cursor;
}
T& read()
{
return *cursor;
}
T const& read() const
{
return *cursor;
}
bool done() const
{
return cursor == sentinel;
}
};
// zip
template<typename V1, typename V2>
struct ZipView
{
V1& first;
V2& second;
void next()
{
first.next();
second.next();
}
auto read()
{
return std::make_tuple(first.read(), second.read());
}
bool done()
{
return first.done() || second.done();
}
};
template<typename View_t, typename result_type, typename filter_type>
struct TransformFun : public View_t
{
TransformFun(View_t const&v, std::function<result_type(filter_type)> p)
: View_t(v)
, pred(p)
{}
result_type read() const
{
return pred(View_t::read());
}
std::function<result_type(filter_type)> pred;
};
template<typename T>
struct TransformOp
{
T pred;
};
template<typename View_t, typename T>
auto operator |(View_t const& right, TransformOp<T> const& left)
{
using PredTraits = function_traits<T>;
static_assert(PredTraits::arity == 1);
using filter_type = typename PredTraits::template arg<0>::type;
using result_type = typename PredTraits::result_type;
return TransformFun<View_t, result_type, filter_type>(right, left.pred);
}
template<typename T>
TransformOp<T> transform(T const& p)
{
return TransformOp<T>{ p };
}
template<typename View_t>
struct TakeFun : public View_t
{
TakeFun(View_t const& v, int c)
: View_t(v)
, count(c)
{}
int count = 0;
void next()
{
count--;
View_t::next();
}
bool done()
{
return (count == 0) || View_t::done();
}
};
struct TakeOp
{
int param;
};
template<typename View_t>
TakeFun<View_t> operator |(View_t const& right, TakeOp const& left)
{
return TakeFun<View_t>(right, left.param);
}
TakeOp take(int p)
{
return TakeOp{ p };
}
int main()
{
std::vector<int> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
// a.iter() | filter(x>3) | transform(x*x) | take(4)
PlainView<int> view = { &a[0], &a[a.size()] };
for (auto t = view
| filter( [](int x) { return x > 3; })
| transform( [](int x) -> float { return x*x+0.5f; })
| take(4)
;
!t.done(); t.next()
)
{
int x = t;
std::cout << x << "->" << t.read() << ' ';
(ValueRef<int>)t = 0;
// t = 0;
}
vstl::StaticArray<int> b = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
PlainView<int> view_b = { &b[0], &b[b.size()] };
ZipView<PlainView<int>, PlainView<int>> zip = { view, view_b};
for (auto z = zip | take(8); !z.done(); z.next())
{
auto t = z.read();
std::cout << "\n ";
std::cout << "{ " << std::get<0>(t) << ", " << std::get<1>(t) << " }";
}
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment