Created
March 15, 2016 06:55
-
-
Save XeCycle/5d7dd90e4b4e88e512e6 to your computer and use it in GitHub Desktop.
flow-sink style demo
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 <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; | |
} |
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
#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 */ |
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
#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