Skip to content

Instantly share code, notes, and snippets.

@XeCycle
Created March 15, 2016 06:55
Show Gist options
  • Save XeCycle/5d7dd90e4b4e88e512e6 to your computer and use it in GitHub Desktop.
Save XeCycle/5d7dd90e4b4e88e512e6 to your computer and use it in GitHub Desktop.
flow-sink style demo
#include <iostream>
#include "output-iterator-adaptor.hh"
#include "map.hh"
int main()
{
auto f = [](auto x) { return x+1; };
double xs[100];
using namespace flows;
{
auto sink = map(f).cmap(wrap_output_iterator(xs)).bind<int>();
for (int i=0; i<100; ++i)
sink.push(i);
sink.finish();
}
for (auto x : xs)
std::cout << x << '\n';
return 0;
}
#ifndef FLOWS_MAP_HH
#define FLOWS_MAP_HH
namespace flows {
template <class F, class Sink, class T>
struct map_sink_t {
using value_type = T;
F f;
Sink ds;
auto push(const T& v)
noexcept(noexcept(ds.push(f(v))))
-> decltype(ds.push(f(v)), void())
{
ds.push(f(v));
}
auto push(T&& v)
noexcept(noexcept(ds.push(f((T&&)v))))
-> decltype(ds.push(f((T&&)v)), void())
{
ds.push(f((T&&)v));
}
void finish()
noexcept(noexcept(ds.finish()))
{
ds.finish();
}
};
template <class F, class DS>
struct unbound_map_sink_t {
F f;
DS ds;
private:
template <class T>
using out_t = typename std::result_of<F(T)>::type;
public:
template <class T, class=void>
struct bind_t {};
template <class T>
struct bind_t<
T,
decltype(std::declval<DS>().template bind<out_t<T> >(), void())>
{
using type = map_sink_t<
F,
typename DS::template bind_t<out_t<T> >::type, T>;
};
template <class T>
typename bind_t<T>::type
constexpr bind() const&
{
return { f, ds.template bind<out_t<T> >() };
}
template <class T>
typename bind_t<T>::type
constexpr bind() &&
{
return { (F&&)f, ((DS&&)ds).template bind<out_t<T> >() };
}
};
template <class F>
struct map_flow_t {
F f;
template <class In>
struct out_type {
using type = typename std::result_of<F(In)>::type;
};
template <class UnboundSink>
unbound_map_sink_t<F, typename std::decay<UnboundSink>::type>
constexpr cmap(UnboundSink&& usink) const&
{
return { f, (UnboundSink&&)usink };
}
template <class UnboundSink>
unbound_map_sink_t<F, typename std::decay<UnboundSink>::type>
constexpr cmap(UnboundSink&& usink) &&
{
return { (F&&)f, (UnboundSink&&)usink };
}
};
template <class F>
map_flow_t<typename std::decay<F>::type>
constexpr map(F&& f)
{
return { (F&&)f };
}
} // namespace flows
#endif /* FLOWS_MAP_HH */
#ifndef FLOWS_OUTPUT_ITERATOR_ADAPTOR_HH
#define FLOWS_OUTPUT_ITERATOR_ADAPTOR_HH
#include <utility>
namespace flows {
template <class OutputIterator, class T>
struct output_iterator_adaptor {
using value_type = T;
OutputIterator it;
void push(const T& v)
noexcept(noexcept(*it = v, ++it))
{
*it = v, ++it;
}
void push(T&& v)
noexcept(noexcept(*it = (T&&)v, ++it))
{
*it = (T&&)v, ++it;
}
void finish() noexcept
{}
};
template <class OutputIterator>
struct unbound_output_iterator_adaptor {
OutputIterator it;
template <class T, class=void>
struct bind_t {};
template <class T>
struct bind_t<T, decltype(*std::declval<OutputIterator&>() = std::declval<T>(), void())> {
using type = output_iterator_adaptor<OutputIterator, T>;
};
template <class T>
typename bind_t<T>::type
constexpr bind() const
{
return { it };
}
};
template <class OutputIterator>
unbound_output_iterator_adaptor<typename std::decay<OutputIterator>::type>
constexpr wrap_output_iterator(OutputIterator&& i)
{
return { (OutputIterator&&)i };
}
} // namespace flows
#endif /* FLOWS_OUTPUT_ITERATOR_ADAPTOR_HH */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment