Commit 4fdee04d authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

kill constrained lambdas

fbshipit-source-id: cac70823ef7a6369d0b731edaf621399d49804c0
parent c5555259
...@@ -12,24 +12,33 @@ namespace pushmi { ...@@ -12,24 +12,33 @@ namespace pushmi {
namespace detail { namespace detail {
struct no_fail_fn { struct no_fail_fn {
auto operator()() const { private:
return constrain(lazy::Sender<_1>, [](auto in) { template <class In>
using In = decltype(in); struct out_impl {
return ::pushmi::detail::deferred_from<In, single<>>( PUSHMI_TEMPLATE(class Out)
std::move(in), (requires Receiver<Out>)
::pushmi::detail::submit_transform_out<In>( auto operator()(Out out) const {
constrain(lazy::Receiver<_1>, [](auto out) {
using Out = decltype(out);
return ::pushmi::detail::out_from_fn<In>()( return ::pushmi::detail::out_from_fn<In>()(
std::move(out), std::move(out),
::pushmi::on_error([](auto&, auto&&) noexcept { ::pushmi::on_error([](auto&, auto&&) noexcept {
std::abort(); std::abort();
}) })
); );
}) }
) };
struct in_impl {
PUSHMI_TEMPLATE(class In)
(requires Sender<In>)
auto operator()(In in) const {
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
::pushmi::detail::submit_transform_out<In>(out_impl<In>{})
); );
}); }
};
public:
auto operator()() const {
return in_impl{};
} }
}; };
......
This diff is collapsed.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "concepts.h" #include "concepts.h"
#include "traits.h" #include "traits.h"
#include "detail/functional.h"
namespace pushmi { namespace pushmi {
...@@ -44,13 +45,11 @@ template <template <class...> class T, class... AN> ...@@ -44,13 +45,11 @@ template <template <class...> class T, class... AN>
using deduced_type_t = pushmi::invoke_result_t<construct_deduced<T>, AN...>; using deduced_type_t = pushmi::invoke_result_t<construct_deduced<T>, AN...>;
struct ignoreVF { struct ignoreVF {
template <class V> void operator()(detail::any) {}
void operator()(V&&) {}
}; };
struct abortEF { struct abortEF {
template <class E> void operator()(detail::any) noexcept {
void operator()(E &&) noexcept {
std::abort(); std::abort();
} }
}; };
...@@ -60,21 +59,17 @@ struct ignoreDF { ...@@ -60,21 +59,17 @@ struct ignoreDF {
}; };
struct ignoreNF { struct ignoreNF {
template <class V> void operator()(detail::any) {}
void operator()(V&&) {}
}; };
struct ignoreStrtF { struct ignoreStrtF {
template <class Up> void operator()(detail::any) {}
void operator()(Up&&) {}
}; };
struct ignoreSF { struct ignoreSF {
template <class Out> void operator()(detail::any) {}
void operator()(Out) {} void operator()(detail::any, detail::any) {}
template <class TP, class Out>
void operator()(TP, Out) {}
}; };
struct systemNowF { struct systemNowF {
...@@ -193,15 +188,15 @@ public: ...@@ -193,15 +188,15 @@ public:
constexpr overload_fn(Fn fn, Fns... fns) constexpr overload_fn(Fn fn, Fns... fns)
: fns_{std::move(fn), overload_fn<Fns...>{std::move(fns)...}} {} : fns_{std::move(fn), overload_fn<Fns...>{std::move(fns)...}} {}
PUSHMI_TEMPLATE (class... Args) PUSHMI_TEMPLATE (class... Args)
(requires defer::Invocable<Fn&, Args...> || (requires lazy::Invocable<Fn&, Args...> ||
defer::Invocable<overload_fn<Fns...>&, Args...>) lazy::Invocable<overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) PUSHMI_NOEXCEPT_AUTO( decltype(auto) operator()(Args &&... args) PUSHMI_NOEXCEPT_AUTO(
std::declval<_which_t<Invocable<Fn&, Args...>>&>()(std::declval<Args>()...)) { std::declval<_which_t<Invocable<Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<Fn&, Args...>>(fns_)((Args &&) args...); return std::get<!Invocable<Fn&, Args...>>(fns_)((Args &&) args...);
} }
PUSHMI_TEMPLATE (class... Args) PUSHMI_TEMPLATE (class... Args)
(requires defer::Invocable<const Fn&, Args...> || (requires lazy::Invocable<const Fn&, Args...> ||
defer::Invocable<const overload_fn<Fns...>&, Args...>) lazy::Invocable<const overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) const PUSHMI_NOEXCEPT_AUTO( decltype(auto) operator()(Args &&... args) const PUSHMI_NOEXCEPT_AUTO(
std::declval<const _which_t<Invocable<const Fn&, Args...>>&>()(std::declval<Args>()...)) { std::declval<const _which_t<Invocable<const Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<const Fn&, Args...>>(fns_)((Args &&) args...); return std::get<!Invocable<const Fn&, Args...>>(fns_)((Args &&) args...);
......
...@@ -206,35 +206,7 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -206,35 +206,7 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \ PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
concept bool NAME = PUSHMI_PP_DEF_IMPL(__VA_ARGS__)(__VA_ARGS__); \ concept bool NAME = PUSHMI_PP_DEF_IMPL(__VA_ARGS__)(__VA_ARGS__); \
} \ } \
namespace defer = _eager_; \ namespace lazy = _eager_; \
namespace lazy { \
PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
struct PUSHMI_PP_CAT(NAME, Concept) { \
using Concept = PUSHMI_PP_CAT(NAME, Concept); \
explicit constexpr operator bool() const noexcept { \
return (bool) defer::NAME<PUSHMI_PP_EXPAND ARGS>; \
} \
template <class PMThis = Concept, bool PMB> \
requires PMB == (bool)PMThis{} \
constexpr operator std::integral_constant<bool, PMB>() const noexcept {\
return {}; \
} \
constexpr auto operator!() const noexcept { \
return ::pushmi::concepts::detail::Not<Concept>{}; \
} \
template <class That> \
constexpr auto operator&&(That) const noexcept { \
return ::pushmi::concepts::detail::And<Concept, That>{}; \
} \
template <class That> \
constexpr auto operator||(That) const noexcept { \
return ::pushmi::concepts::detail::Or<Concept, That>{}; \
} \
}; \
PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
PUSHMI_INLINE_VAR constexpr auto NAME = \
PUSHMI_PP_CAT(NAME, Concept)<PUSHMI_PP_EXPAND ARGS>{}; \
} \
/**/ /**/
#else #else
// No requires expression: // No requires expression:
...@@ -301,7 +273,6 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -301,7 +273,6 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
PUSHMI_INLINE_VAR constexpr auto NAME = \ PUSHMI_INLINE_VAR constexpr auto NAME = \
PUSHMI_PP_CAT(NAME, Concept)::Eval<PUSHMI_PP_EXPAND ARGS>{}; \ PUSHMI_PP_CAT(NAME, Concept)::Eval<PUSHMI_PP_EXPAND ARGS>{}; \
} \ } \
namespace defer = lazy; \
/**/ /**/
#endif #endif
......
...@@ -8,91 +8,48 @@ ...@@ -8,91 +8,48 @@
#include <functional> #include <functional>
#include "../traits.h" #include "concept_def.h"
#include "../forwards.h"
namespace pushmi { namespace pushmi {
namespace detail { PUSHMI_INLINE_VAR constexpr struct invoke_fn {
private:
struct placeholder; template <class F>
using mem_fn_t = decltype(std::mem_fn(std::declval<F>()));
#ifndef __has_builtin public:
#define __has_builtin(x) 0 template <class F, class... As>
#endif auto operator()(F&& f, As&&...as) const
noexcept(noexcept(((F&&) f)((As&&) as...))) ->
#if __has_builtin(__type_pack_element) decltype(((F&&) f)((As&&) as...)) {
#define PUSHMI_TYPE_PACK_ELEMENT(...) \ return ((F&&) f)((As&&) as...);
__type_pack_element<__VA_ARGS__>
#else
template <std::size_t I, class... Args>
struct type_pack_element {
};
template <std::size_t I, class A, class... Args>
struct type_pack_element<I, A, Args...> : type_pack_element<I - 1, Args...> {
};
template <class A, class... Args>
struct type_pack_element<0, A, Args...> {
using type = A;
};
#define PUSHMI_TYPE_PACK_ELEMENT(...) \
typename type_pack_element<__VA_ARGS__>::type
#endif
template <class T, class Args, class = void>
struct substitute {
using type = T;
};
template <std::size_t I, class... Args>
struct substitute<placeholder[I], typelist<Args...>,
void_t<PUSHMI_TYPE_PACK_ELEMENT(I-1, Args...)>>
: std::decay<PUSHMI_TYPE_PACK_ELEMENT(I-1, Args...)> {
};
template <std::size_t I, class... Args>
struct substitute<placeholder(&&)[I], typelist<Args...>,
void_t<PUSHMI_TYPE_PACK_ELEMENT(I-1, Args...)>> {
using type = PUSHMI_TYPE_PACK_ELEMENT(I-1, Args...);
};
template <template <class...> class R, class... Ts, class Args>
struct substitute<R<Ts...>, Args,
void_t<R<typename substitute<Ts, Args>::type...>>> {
using type = R<typename substitute<Ts, Args>::type...>;
};
template <class Fn, class Requirements>
struct constrained_fn : Fn {
constrained_fn() = default;
constrained_fn(Fn fn) : Fn(std::move(fn)) {}
PUSHMI_TEMPLATE (class... Ts)
(requires Invocable<Fn&, Ts...> &&
(bool)typename substitute<Requirements, typelist<Ts...>>::type{})
decltype(auto) operator()(Ts&&... ts)
noexcept(noexcept(std::declval<Fn&>()((Ts&&) ts...))) {
return static_cast<Fn&>(*this)((Ts&&) ts...);
} }
PUSHMI_TEMPLATE (class... Ts) template <class F, class... As>
(requires Invocable<const Fn&, Ts...> && auto operator()(F&& f, As&&...as) const
(bool)typename substitute<Requirements, typelist<Ts...>>::type{}) noexcept(noexcept(std::declval<mem_fn_t<F>>()((As&&) as...))) ->
decltype(auto) operator()(Ts&&... ts) const decltype(std::mem_fn(f)((As&&) as...)) {
noexcept(noexcept(std::declval<const Fn&>()((Ts&&) ts...))) { return std::mem_fn(f)((As&&) as...);
return static_cast<const Fn&>(*this)((Ts&&) ts...);
} }
}; } invoke {};
struct constrain_fn { template <class F, class...As>
template <class Requirements, class Fn> using invoke_result_t =
constexpr auto operator()(Requirements, Fn fn) const { decltype(pushmi::invoke(std::declval<F>(), std::declval<As>()...));
return constrained_fn<Fn, Requirements>{std::move(fn)};
} PUSHMI_CONCEPT_DEF(
}; template (class F, class... Args)
(concept Invocable)(F, Args...),
} // namespace detail requires(F&& f) (
pushmi::invoke((F &&) f, std::declval<Args>()...)
using _1 = detail::placeholder[1]; )
using _2 = detail::placeholder[2]; );
using _3 = detail::placeholder[3];
PUSHMI_CONCEPT_DEF(
PUSHMI_INLINE_VAR constexpr const detail::constrain_fn constrain {}; template (class F, class... Args)
(concept NothrowInvocable)(F, Args...),
requires(F&& f) (
requires_<noexcept(pushmi::invoke((F &&) f, std::declval<Args>()...))>
) &&
Invocable<F, Args...>
);
} // namespace pushmi } // namespace pushmi
...@@ -129,8 +129,8 @@ class flow_single_deferred<Data, DSF> { ...@@ -129,8 +129,8 @@ class flow_single_deferred<Data, DSF> {
constexpr flow_single_deferred(Data data, DSF sf) constexpr flow_single_deferred(Data data, DSF sf)
: data_(std::move(data)), sf_(std::move(sf)) {} : data_(std::move(data)), sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires PUSHMI_EXP(defer::Receiver<Out, is_single<>, is_flow<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Out, is_single<>, is_flow<>> PUSHMI_AND
defer::Invocable<DSF&, Data&, Out>)) lazy::Invocable<DSF&, Data&, Out>))
void submit(Out out) { void submit(Out out) {
sf_(data_, std::move(out)); sf_(data_, std::move(out));
} }
......
...@@ -88,4 +88,11 @@ namespace aliases { ...@@ -88,4 +88,11 @@ namespace aliases {
namespace ep = ::pushmi::extension_operators; namespace ep = ::pushmi::extension_operators;
} }
namespace detail {
struct any {
template <class T>
constexpr any(T&&) noexcept {}
};
}
} // namespace pushmi } // namespace pushmi
...@@ -279,7 +279,7 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn { ...@@ -279,7 +279,7 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn {
return many<>{}; return many<>{};
} }
PUSHMI_TEMPLATE(class NF) PUSHMI_TEMPLATE(class NF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF> PUSHMI_AND not defer::Invocable<NF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF> PUSHMI_AND not lazy::Invocable<NF&>)))
auto operator()(NF nf) const { auto operator()(NF nf) const {
return many<NF, abortEF, ignoreDF>{std::move(nf)}; return many<NF, abortEF, ignoreDF>{std::move(nf)};
} }
...@@ -288,57 +288,57 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn { ...@@ -288,57 +288,57 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn {
return many<ignoreNF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)}; return many<ignoreNF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)};
} }
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
auto operator()(DF df) const { auto operator()(DF df) const {
return many<ignoreNF, abortEF, DF>{std::move(df)}; return many<ignoreNF, abortEF, DF>{std::move(df)};
} }
PUSHMI_TEMPLATE(class NF, class EF) PUSHMI_TEMPLATE(class NF, class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF> PUSHMI_AND not lazy::Invocable<EF&>)))
auto operator()(NF nf, EF ef) const { auto operator()(NF nf, EF ef) const {
return many<NF, EF, ignoreDF>{std::move(nf), std::move(ef)}; return many<NF, EF, ignoreDF>{std::move(nf), std::move(ef)};
} }
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
auto operator()(EF ef, DF df) const { auto operator()(EF ef, DF df) const {
return many<ignoreNF, EF, DF>{std::move(ef), std::move(df)}; return many<ignoreNF, EF, DF>{std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class NF, class EF, class DF) PUSHMI_TEMPLATE(class NF, class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF>)))
auto operator()(NF nf, EF ef, DF df) const { auto operator()(NF nf, EF ef, DF df) const {
return many<NF, EF, DF>{std::move(nf), std::move(ef), std::move(df)}; return many<NF, EF, DF>{std::move(nf), std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>>))
auto operator()(Data d) const { auto operator()(Data d) const {
return many<Data, passDNXF, passDEF, passDDF>{std::move(d)}; return many<Data, passDNXF, passDEF, passDDF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DNF) PUSHMI_TEMPLATE(class Data, class DNF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DNF&, Data&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DNF&, Data&>)))
auto operator()(Data d, DNF nf) const { auto operator()(Data d, DNF nf) const {
return many<Data, DNF, passDEF, passDDF>{std::move(d), std::move(nf)}; return many<Data, DNF, passDEF, passDDF>{std::move(d), std::move(nf)};
} }
PUSHMI_TEMPLATE(class Data, class... DEFN) PUSHMI_TEMPLATE(class Data, class... DEFN)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>>))
auto operator()(Data d, on_error_fn<DEFN...> ef) const { auto operator()(Data d, on_error_fn<DEFN...> ef) const {
return many<Data, passDNXF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(ef)}; return many<Data, passDNXF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(ef)};
} }
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DDF df) const { auto operator()(Data d, DDF df) const {
return many<Data, passDNXF, passDEF, DDF>{std::move(d), std::move(df)}; return many<Data, passDNXF, passDEF, DDF>{std::move(d), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data, class DNF, class DEF) PUSHMI_TEMPLATE(class Data, class DNF, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
auto operator()(Data d, DNF nf, DEF ef) const { auto operator()(Data d, DNF nf, DEF ef) const {
return many<Data, DNF, DEF, passDDF>{std::move(d), std::move(nf), std::move(ef)}; return many<Data, DNF, DEF, passDDF>{std::move(d), std::move(nf), std::move(ef)};
} }
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DEF ef, DDF df) const { auto operator()(Data d, DEF ef, DDF df) const {
return many<Data, passDNXF, DEF, DDF>{std::move(d), std::move(ef), std::move(df)}; return many<Data, passDNXF, DEF, DDF>{std::move(d), std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data, class DNF, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DNF, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DNF nf, DEF ef, DDF df) const { auto operator()(Data d, DNF nf, DEF ef, DDF df) const {
return many<Data, DNF, DEF, DDF>{std::move(d), std::move(nf), std::move(ef), std::move(df)}; return many<Data, DNF, DEF, DDF>{std::move(d), std::move(nf), std::move(ef), std::move(df)};
} }
...@@ -350,55 +350,55 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn { ...@@ -350,55 +350,55 @@ PUSHMI_INLINE_VAR constexpr struct make_many_fn {
many() -> many<>; many() -> many<>;
PUSHMI_TEMPLATE(class NF) PUSHMI_TEMPLATE(class NF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF> PUSHMI_AND not defer::Invocable<NF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF> PUSHMI_AND not lazy::Invocable<NF&>)))
many(NF) -> many<NF, abortEF, ignoreDF>; many(NF) -> many<NF, abortEF, ignoreDF>;
template <class... EFN> template <class... EFN>
many(on_error_fn<EFN...>) -> many<ignoreNF, on_error_fn<EFN...>, ignoreDF>; many(on_error_fn<EFN...>) -> many<ignoreNF, on_error_fn<EFN...>, ignoreDF>;
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
many(DF) -> many<ignoreNF, abortEF, DF>; many(DF) -> many<ignoreNF, abortEF, DF>;
PUSHMI_TEMPLATE(class NF, class EF) PUSHMI_TEMPLATE(class NF, class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF> PUSHMI_AND not lazy::Invocable<EF&>)))
many(NF, EF) -> many<NF, EF, ignoreDF>; many(NF, EF) -> many<NF, EF, ignoreDF>;
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
many(EF, DF) -> many<ignoreNF, EF, DF>; many(EF, DF) -> many<ignoreNF, EF, DF>;
PUSHMI_TEMPLATE(class NF, class EF, class DF) PUSHMI_TEMPLATE(class NF, class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<NF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<NF>)))
many(NF, EF, DF) -> many<NF, EF, DF>; many(NF, EF, DF) -> many<NF, EF, DF>;
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>>))
many(Data d) -> many<Data, passDNXF, passDEF, passDDF>; many(Data d) -> many<Data, passDNXF, passDEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DNF) PUSHMI_TEMPLATE(class Data, class DNF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DNF&, Data&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DNF&, Data&>)))
many(Data d, DNF nf) -> many<Data, DNF, passDEF, passDDF>; many(Data d, DNF nf) -> many<Data, DNF, passDEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class... DEFN) PUSHMI_TEMPLATE(class Data, class... DEFN)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>>))
many(Data d, on_error_fn<DEFN...>) -> many(Data d, on_error_fn<DEFN...>) ->
many<Data, passDNXF, on_error_fn<DEFN...>, passDDF>; many<Data, passDNXF, on_error_fn<DEFN...>, passDDF>;
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
many(Data d, DDF) -> many<Data, passDNXF, passDEF, DDF>; many(Data d, DDF) -> many<Data, passDNXF, passDEF, DDF>;
PUSHMI_TEMPLATE(class Data, class DNF, class DEF) PUSHMI_TEMPLATE(class Data, class DNF, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
many(Data d, DNF nf, DEF ef) -> many<Data, DNF, DEF, passDDF>; many(Data d, DNF nf, DEF ef) -> many<Data, DNF, DEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
many(Data d, DEF, DDF) -> many<Data, passDNXF, DEF, DDF>; many(Data d, DEF, DDF) -> many<Data, passDNXF, DEF, DDF>;
PUSHMI_TEMPLATE(class Data, class DNF, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DNF, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_many<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_many<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
many(Data d, DNF nf, DEF ef, DDF df) -> many<Data, DNF, DEF, DDF>; many(Data d, DNF nf, DEF ef, DDF df) -> many<Data, DNF, DEF, DDF>;
#endif #endif
......
...@@ -109,7 +109,7 @@ class many_deferred<SF> { ...@@ -109,7 +109,7 @@ class many_deferred<SF> {
: sf_(std::move(sf)) {} : sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires PUSHMI_EXP(defer::Receiver<Out, is_many<>> PUSHMI_AND defer::Invocable<SF&, Out>)) (requires PUSHMI_EXP(lazy::Receiver<Out, is_many<>> PUSHMI_AND lazy::Invocable<SF&, Out>))
void submit(Out out) { void submit(Out out) {
sf_(std::move(out)); sf_(std::move(out));
} }
...@@ -130,8 +130,8 @@ class many_deferred_2 { ...@@ -130,8 +130,8 @@ class many_deferred_2 {
constexpr many_deferred_2(Data data, DSF sf) constexpr many_deferred_2(Data data, DSF sf)
: data_(std::move(data)), sf_(std::move(sf)) {} : data_(std::move(data)), sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires PUSHMI_EXP(defer::Receiver<Out, is_many<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Out, is_many<>> PUSHMI_AND
defer::Invocable<DSF&, Data&, Out>)) lazy::Invocable<DSF&, Data&, Out>))
void submit(Out out) { void submit(Out out) {
sf_(data_, std::move(out)); sf_(data_, std::move(out));
} }
......
...@@ -208,40 +208,40 @@ PUSHMI_INLINE_VAR constexpr struct make_none_fn { ...@@ -208,40 +208,40 @@ PUSHMI_INLINE_VAR constexpr struct make_none_fn {
return none<>{}; return none<>{};
} }
PUSHMI_TEMPLATE(class EF) PUSHMI_TEMPLATE(class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF> PUSHMI_AND not lazy::Invocable<EF&>)))
auto operator()(EF ef) const { auto operator()(EF ef) const {
return none<EF, ignoreDF>{std::move(ef)}; return none<EF, ignoreDF>{std::move(ef)};
} }
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
auto operator()(DF df) const { auto operator()(DF df) const {
return none<abortEF, DF>{std::move(df)}; return none<abortEF, DF>{std::move(df)};
} }
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
auto operator()(EF ef, DF df) const { auto operator()(EF ef, DF df) const {
return none<EF, DF>{std::move(ef), std::move(df)}; return none<EF, DF>{std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>>))
auto operator()(Data d) const { auto operator()(Data d) const {
return none<Data, passDEF, passDDF>{std::move(d)}; return none<Data, passDEF, passDDF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DEF) PUSHMI_TEMPLATE(class Data, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>>
PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
auto operator()(Data d, DEF ef) const { auto operator()(Data d, DEF ef) const {
return none<Data, DEF, passDDF>{std::move(d), std::move(ef)}; return none<Data, DEF, passDDF>{std::move(d), std::move(ef)};
} }
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>> PUSHMI_AND
defer::Invocable<DDF&, Data&>)) lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DDF df) const { auto operator()(Data d, DDF df) const {
return none<Data, passDEF, DDF>{std::move(d), std::move(df)}; return none<Data, passDEF, DDF>{std::move(d), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>> PUSHMI_AND
defer::Invocable<DDF&, Data&>)) lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DEF ef, DDF df) const { auto operator()(Data d, DEF ef, DDF df) const {
return none<Data, DEF, DDF>{std::move(d), std::move(ef), std::move(df)}; return none<Data, DEF, DDF>{std::move(d), std::move(ef), std::move(df)};
} }
...@@ -253,34 +253,34 @@ PUSHMI_INLINE_VAR constexpr struct make_none_fn { ...@@ -253,34 +253,34 @@ PUSHMI_INLINE_VAR constexpr struct make_none_fn {
none() -> none<>; none() -> none<>;
PUSHMI_TEMPLATE(class EF) PUSHMI_TEMPLATE(class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF> PUSHMI_AND not lazy::Invocable<EF&>)))
none(EF) -> none<EF, ignoreDF>; none(EF) -> none<EF, ignoreDF>;
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
none(DF) -> none<abortEF, DF>; none(DF) -> none<abortEF, DF>;
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
none(EF, DF) -> none<EF, DF>; none(EF, DF) -> none<EF, DF>;
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>>))
none(Data) -> none<Data, passDEF, passDDF>; none(Data) -> none<Data, passDEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DEF) PUSHMI_TEMPLATE(class Data, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>>
PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
none(Data, DEF) -> none<Data, DEF, passDDF>; none(Data, DEF) -> none<Data, DEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>> PUSHMI_AND
defer::Invocable<DDF&, Data&>)) lazy::Invocable<DDF&, Data&>))
none(Data, DDF) -> none<Data, passDEF, DDF>; none(Data, DDF) -> none<Data, passDEF, DDF>;
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Data, is_none<>> PUSHMI_AND not lazy::Receiver<Data, is_single<>> PUSHMI_AND
defer::Invocable<DDF&, Data&>)) lazy::Invocable<DDF&, Data&>))
none(Data, DEF, DDF) -> none<Data, DEF, DDF>; none(Data, DEF, DDF) -> none<Data, DEF, DDF>;
#endif #endif
......
...@@ -11,33 +11,33 @@ ...@@ -11,33 +11,33 @@
#include "submit.h" #include "submit.h"
#include "extension_operators.h" #include "extension_operators.h"
#if __cpp_deduction_guides >= 201703
#define MAKE(x) x MAKE_
#define MAKE_(...) {__VA_ARGS__}
#else
#define MAKE(x) make_ ## x
#endif
namespace pushmi { namespace pushmi {
namespace operators { namespace operators {
PUSHMI_TEMPLATE(class F) PUSHMI_INLINE_VAR constexpr struct defer_fn {
(requires Invocable<F>) private:
auto defer(F f) { template <class F>
return MAKE(single_deferred)( struct impl {
constrain(lazy::Receiver<_1>, F f_;
[f = std::move(f)](auto out) mutable { PUSHMI_TEMPLATE(class Out)
auto sender = f(); (requires Receiver<Out>)
void operator()(Out out) {
auto sender = f_();
PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<decltype(sender)>) ( PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<decltype(sender)>) (
::pushmi::submit(sender, ::pushmi::now(id(sender)), std::move(out)); ::pushmi::submit(sender, ::pushmi::now(id(sender)), std::move(out));
) else ( ) else (
::pushmi::submit(sender, std::move(out)); ::pushmi::submit(sender, std::move(out));
)); ));
} }
) };
); public:
} PUSHMI_TEMPLATE(class F)
(requires Invocable<F&>)
auto operator()(F f) const {
return make_single_deferred(impl<F>{std::move(f)});
}
} defer {};
} // namespace operators } // namespace operators
......
...@@ -11,24 +11,32 @@ ...@@ -11,24 +11,32 @@
#include "../detail/functional.h" #include "../detail/functional.h"
namespace pushmi { namespace pushmi {
namespace detail {
template <class V>
struct single_empty_impl {
PUSHMI_TEMPLATE(class Out)
(requires SingleReceiver<Out, V>)
void operator()(Out out) {
::pushmi::set_done(out);
}
};
struct empty_impl {
PUSHMI_TEMPLATE(class Out)
(requires NoneReceiver<Out>)
void operator()(Out out) {
::pushmi::set_done(out);
}
};
}
namespace operators { namespace operators {
template <class V> template <class V>
auto empty() { auto empty() {
return make_single_deferred( return make_single_deferred(detail::single_empty_impl<V>{});
constrain(lazy::SingleReceiver<_1, V>, [](auto out) mutable {
::pushmi::set_done(out);
})
);
} }
inline auto empty() { inline auto empty() {
return make_deferred( return make_deferred(detail::empty_impl{});
constrain(lazy::NoneReceiver<_1>, [](auto out) mutable {
::pushmi::set_done(out);
})
);
} }
} // namespace operators } // namespace operators
......
...@@ -11,33 +11,40 @@ ...@@ -11,33 +11,40 @@
#include "extension_operators.h" #include "extension_operators.h"
namespace pushmi { namespace pushmi {
namespace detail {
template <class E>
struct error_impl {
E e_;
PUSHMI_TEMPLATE(class Out)
(requires NoneReceiver<Out, E>)
void operator()(Out out) {
::pushmi::set_error(out, std::move(e_));
}
};
template <class V, class E>
struct single_error_impl {
E e_;
PUSHMI_TEMPLATE(class Out)
(requires SingleReceiver<Out, V, E>)
void operator()(Out out) {
::pushmi::set_error(out, std::move(e_));
}
};
}
namespace operators { namespace operators {
PUSHMI_TEMPLATE(class E) PUSHMI_TEMPLATE(class E)
(requires SemiMovable<E>) (requires SemiMovable<E>)
auto error(E e) { auto error(E e) {
return make_deferred( return make_deferred(detail::error_impl<E>{std::move(e)});
constrain(lazy::NoneReceiver<_1, E>,
[e = std::move(e)](auto out) mutable {
::pushmi::set_error(out, std::move(e));
}
)
);
} }
PUSHMI_TEMPLATE(class V, class E) PUSHMI_TEMPLATE(class V, class E)
(requires SemiMovable<V> && SemiMovable<E>) (requires SemiMovable<V> && SemiMovable<E>)
auto error(E e) { auto error(E e) {
return make_single_deferred( return make_single_deferred(detail::single_error_impl<V, E>{std::move(e)});
constrain(lazy::SingleReceiver<_1, V, E>,
[e = std::move(e)](auto out) mutable {
::pushmi::set_error(out, std::move(e));
}
)
);
} }
} // namespace operators } // namespace operators
} // namespace pushmi } // namespace pushmi
...@@ -84,54 +84,67 @@ struct out_from_fn { ...@@ -84,54 +84,67 @@ struct out_from_fn {
} }
}; };
template <class In, class FN>
struct submit_transform_out_1 {
FN fn_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void operator()(In& in, Out out) const {
::pushmi::submit(in, fn_(std::move(out)));
}
};
template <class In, class FN>
struct submit_transform_out_2 {
FN fn_;
PUSHMI_TEMPLATE(class TP, class Out)
(requires Receiver<Out>)
void operator()(In& in, TP tp, Out out) const {
::pushmi::submit(in, tp, fn_(std::move(out)));
}
};
template <class In, class SDSF>
struct submit_transform_out_3 {
SDSF sdsf_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out> && Invocable<const SDSF&, In&, Out>)
void operator()(In& in, Out out) const {
sdsf_(in, std::move(out));
}
};
template <class In, class TSDSF>
struct submit_transform_out_4 {
TSDSF tsdsf_;
PUSHMI_TEMPLATE(class TP, class Out)
(requires Receiver<Out> && Invocable<const TSDSF&, In&, TP, Out>)
void operator()(In& in, TP tp, Out out) const {
tsdsf_(in, tp, std::move(out));
}
};
PUSHMI_TEMPLATE(class In, class FN) PUSHMI_TEMPLATE(class In, class FN)
(requires Sender<In> && SemiMovable<FN> (requires Sender<In> && SemiMovable<FN>
PUSHMI_BROKEN_SUBSUMPTION(&& not TimeSender<In>)) PUSHMI_BROKEN_SUBSUMPTION(&& not TimeSender<In>))
auto submit_transform_out(FN fn){ auto submit_transform_out(FN fn) {
return on_submit( return on_submit(submit_transform_out_1<In, FN>{std::move(fn)});
constrain(lazy::Receiver<_2>,
[fn = std::move(fn)](In& in, auto out) {
::pushmi::submit(in, fn(std::move(out)));
}
)
);
} }
PUSHMI_TEMPLATE(class In, class FN) PUSHMI_TEMPLATE(class In, class FN)
(requires TimeSender<In> && SemiMovable<FN>) (requires TimeSender<In> && SemiMovable<FN>)
auto submit_transform_out(FN fn){ auto submit_transform_out(FN fn){
return on_submit( return on_submit(submit_transform_out_2<In, FN>{std::move(fn)});
constrain(lazy::Receiver<_3>,
[fn = std::move(fn)](In& in, auto tp, auto out) {
::pushmi::submit(in, tp, fn(std::move(out)));
}
)
);
} }
PUSHMI_TEMPLATE(class In, class SDSF, class TSDSF) PUSHMI_TEMPLATE(class In, class SDSF, class TSDSF)
(requires Sender<In> && SemiMovable<SDSF> && SemiMovable<TSDSF> (requires Sender<In> && SemiMovable<SDSF> && SemiMovable<TSDSF>
PUSHMI_BROKEN_SUBSUMPTION(&& not TimeSender<In>)) PUSHMI_BROKEN_SUBSUMPTION(&& not TimeSender<In>))
auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) { auto submit_transform_out(SDSF sdsf, TSDSF) {
return on_submit( return on_submit(submit_transform_out_3<In, SDSF>{std::move(sdsf)});
constrain(lazy::Receiver<_2> && lazy::Invocable<SDSF&, In&, _2>,
[sdsf = std::move(sdsf)](In& in, auto out) {
sdsf(in, std::move(out));
}
)
);
} }
PUSHMI_TEMPLATE(class In, class SDSF, class TSDSF) PUSHMI_TEMPLATE(class In, class SDSF, class TSDSF)
(requires TimeSender<In> && SemiMovable<SDSF> && SemiMovable<TSDSF>) (requires TimeSender<In> && SemiMovable<SDSF> && SemiMovable<TSDSF>)
auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) { auto submit_transform_out(SDSF, TSDSF tsdsf) {
return on_submit( return on_submit(submit_transform_out_4<In, TSDSF>{std::move(tsdsf)});
constrain(lazy::Receiver<_3> && lazy::Invocable<TSDSF&, In&, _2, _3>,
[tsdsf = std::move(tsdsf)](In& in, auto tp, auto out) {
tsdsf(in, tp, std::move(out));
}
)
);
} }
PUSHMI_TEMPLATE(class In) PUSHMI_TEMPLATE(class In)
...@@ -203,89 +216,140 @@ constexpr bool deferred_requires_from() { ...@@ -203,89 +216,140 @@ constexpr bool deferred_requires_from() {
} }
struct set_value_fn { struct set_value_fn {
template<class V> private:
auto operator()(V&& v) const { template <class V>
return constrain(lazy::Receiver<_1, is_single<>>, struct impl {
[v = (V&&) v](auto out) mutable { V v_;
::pushmi::set_value(out, (V&&) v); PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out, is_single<>>)
void operator()(Out out) {
::pushmi::set_value(out, std::move(v_));
} }
); };
public:
template <class V>
auto operator()(V&& v) const {
return impl<std::decay_t<V>>{(V&&) v};
} }
}; };
struct set_error_fn { struct set_error_fn {
private:
template <class E>
struct impl {
E e_;
PUSHMI_TEMPLATE(class Out)
(requires NoneReceiver<Out, E>)
void operator()(Out out) {
::pushmi::set_error(out, std::move(e_));
}
};
public:
PUSHMI_TEMPLATE(class E) PUSHMI_TEMPLATE(class E)
(requires SemiMovable<E>) (requires SemiMovable<E>)
auto operator()(E e) const { auto operator()(E e) const {
return constrain(lazy::NoneReceiver<_1, E>, return impl<E>{std::move(e)};
[e = std::move(e)](auto out) mutable {
::pushmi::set_error(out, std::move(e));
}
);
} }
}; };
struct set_done_fn { struct set_done_fn {
auto operator()() const { private:
return constrain(lazy::Receiver<_1>, struct impl {
[](auto out) { PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void operator()(Out out) {
::pushmi::set_done(out); ::pushmi::set_done(out);
} }
); };
public:
auto operator()() const {
return impl{};
} }
}; };
struct set_next_fn { struct set_next_fn {
template<class V> private:
auto operator()(V&& v) const { template <class V>
return constrain(lazy::Receiver<_1, is_many<>>, struct impl {
[v = (V&&) v](auto out) mutable { V v_;
::pushmi::set_next(out, (V&&) v); PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out, is_many<>>)
void operator()(Out out) {
::pushmi::set_next(out, std::move(v_));
} }
); };
public:
template <class V>
auto operator()(V&& v) const {
return impl<std::decay_t<V>>{(V&&) v};
} }
}; };
struct set_starting_fn { struct set_starting_fn {
private:
template <class Up>
struct impl {
Up up_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void operator()(Out out) {
::pushmi::set_starting(out, std::move(up_));
}
};
public:
PUSHMI_TEMPLATE(class Up) PUSHMI_TEMPLATE(class Up)
(requires Receiver<Up>) (requires Receiver<Up>)
auto operator()(Up up) const { auto operator()(Up up) const {
return constrain(lazy::Receiver<_1>, return impl<Up>{std::move(up)};
[up = std::move(up)](auto out) {
::pushmi::set_starting(out, std::move(up));
}
);
} }
}; };
struct do_submit_fn { struct do_submit_fn {
private:
template <class Out>
struct impl {
Out out_;
PUSHMI_TEMPLATE (class In)
(requires SenderTo<In, Out>)
void operator()(In in) {
::pushmi::submit(in, std::move(out_));
}
};
template <class TP, class Out>
struct time_impl {
TP tp_;
Out out_;
PUSHMI_TEMPLATE (class In)
(requires TimeSenderTo<In, Out>)
void operator()(In in) {
::pushmi::submit(in, std::move(tp_), std::move(out_));
}
};
public:
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>) (requires Receiver<Out>)
auto operator()(Out out) const { auto operator()(Out out) const {
return constrain(lazy::SenderTo<_1, Out>, return impl<Out>{std::move(out)};
[out = std::move(out)](auto in) mutable {
::pushmi::submit(in, std::move(out));
}
);
} }
PUSHMI_TEMPLATE(class TP, class Out) PUSHMI_TEMPLATE(class TP, class Out)
(requires Receiver<Out>) (requires Receiver<Out>)
auto operator()(TP tp, Out out) const { auto operator()(TP tp, Out out) const {
return constrain(lazy::TimeSenderTo<_1, Out>, return time_impl<TP, Out>{std::move(tp), std::move(out)};
[tp = std::move(tp), out = std::move(out)](auto in) mutable {
::pushmi::submit(in, std::move(tp), std::move(out));
}
);
} }
}; };
struct now_fn { struct now_fn {
auto operator()() const { private:
return constrain(lazy::TimeSender<_1>, struct impl {
[](auto in) { PUSHMI_TEMPLATE (class In)
(requires TimeSender<In>)
auto operator()(In in) const {
return ::pushmi::now(in); return ::pushmi::now(in);
} }
); };
public:
auto operator()() const {
return impl{};
} }
}; };
......
...@@ -12,31 +12,49 @@ namespace pushmi { ...@@ -12,31 +12,49 @@ namespace pushmi {
namespace detail { namespace detail {
struct filter_fn { struct filter_fn {
PUSHMI_TEMPLATE(class Predicate) private:
(requires SemiMovable<Predicate>) template <class Predicate>
auto operator()(Predicate p) const { struct on_value_impl {
return constrain(lazy::Sender<_1>, [p = std::move(p)](auto in) { Predicate p_;
using In = decltype(in); template <class Out, class V>
return ::pushmi::detail::deferred_from<In, single<>>( void operator()(Out& out, V&& v) const {
std::move(in), if (p_(as_const(v))) {
::pushmi::detail::submit_transform_out<In>( ::pushmi::set_value(out, (V&&) v);
constrain(lazy::Receiver<_1>, [p](auto out) {
using Out = decltype(out);
return ::pushmi::detail::out_from_fn<In>()(
std::move(out),
// copy 'p' to allow multiple calls to submit
::pushmi::on_value([p](auto& out, auto&& v) {
if (p(as_const(v))) {
::pushmi::set_value(out, std::move(v));
} else { } else {
::pushmi::set_done(out); ::pushmi::set_done(out);
} }
}) }
};
template <class In, class Predicate>
struct out_impl {
Predicate p_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
auto operator()(Out out) const {
return ::pushmi::detail::out_from_fn<In>()(
std::move(out),
// copy 'p' to allow multiple calls to submit
::pushmi::on_value(on_value_impl<Predicate>{p_})
); );
}) }
) };
template <class Predicate>
struct in_impl {
Predicate p_;
PUSHMI_TEMPLATE(class In)
(requires Sender<In>)
auto operator()(In in) const {
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
::pushmi::detail::submit_transform_out<In>(out_impl<In, Predicate>{p_})
); );
}); }
};
public:
PUSHMI_TEMPLATE(class Predicate)
(requires SemiMovable<Predicate>)
auto operator()(Predicate p) const {
return in_impl<Predicate>{std::move(p)};
} }
}; };
......
...@@ -10,36 +10,48 @@ ...@@ -10,36 +10,48 @@
namespace pushmi { namespace pushmi {
PUSHMI_CONCEPT_DEF(
template (class R)
concept Range,
requires (R&& r) (
implicitly_convertible_to<bool>(std::begin(r) == std::end(r))
)
);
namespace operators { namespace operators {
PUSHMI_TEMPLATE(class O, class S) PUSHMI_INLINE_VAR constexpr struct from_fn {
(requires private:
ConvertibleTo< template <class I, class S>
typename std::iterator_traits<O>::iterator_category, struct out_impl {
std::forward_iterator_tag> && I begin_;
ConvertibleTo< S end_;
typename std::iterator_traits<S>::iterator_category, PUSHMI_TEMPLATE(class Out)
std::forward_iterator_tag>) (requires ManyReceiver<Out, typename std::iterator_traits<I>::value_type>)
auto from(O begin, S end) { void operator()(Out out) const {
return make_many_deferred(constrain( auto c = begin_;
lazy::ManyReceiver<_1, typename std::iterator_traits<O>::value_type>, for (; c != end_; ++c) {
[begin = std::move(begin), end = std::move(end)](auto out) {
auto c = begin;
for (; c != end; ++c) {
::pushmi::set_next(out, *c); ::pushmi::set_next(out, *c);
} }
::pushmi::set_done(out); ::pushmi::set_done(out);
})); }
} };
public:
PUSHMI_TEMPLATE(class R) PUSHMI_TEMPLATE(class I, class S)
(requires requires ( (requires
std::begin(std::declval<R&&>()), DerivedFrom<
std::end(std::declval<R&&>()) typename std::iterator_traits<I>::iterator_category,
)) std::forward_iterator_tag>)
auto from(R&& range) { auto operator()(I begin, S end) const {
return from(std::begin(range), std::end(range)); return make_many_deferred(out_impl<I, S>{begin, end});
} }
PUSHMI_TEMPLATE(class R)
(requires Range<R>)
auto operator()(R&& range) const {
return (*this)(std::begin(range), std::end(range));
}
} from {};
} // namespace operators } // namespace operators
......
...@@ -14,18 +14,24 @@ namespace pushmi { ...@@ -14,18 +14,24 @@ namespace pushmi {
namespace operators { namespace operators {
PUSHMI_TEMPLATE(class V) PUSHMI_INLINE_VAR constexpr struct just_fn {
private:
template <class V>
struct impl {
V v_;
PUSHMI_TEMPLATE (class Out)
(requires SingleReceiver<Out, V>)
void operator()(Out out) {
::pushmi::set_value(out, std::move(v_));
}
};
public:
PUSHMI_TEMPLATE(class V)
(requires SemiMovable<V>) (requires SemiMovable<V>)
auto just(V v) { auto operator()(V v) const {
return make_single_deferred( return make_single_deferred(impl<V>{std::move(v)});
constrain(lazy::SingleReceiver<_1, V>,
[v = std::move(v)](auto out) mutable {
::pushmi::set_value(out, std::move(v));
} }
) } just {};
);
}
} // namespace operators } // namespace operators
} // namespace pushmi } // namespace pushmi
...@@ -13,33 +13,70 @@ namespace pushmi { ...@@ -13,33 +13,70 @@ namespace pushmi {
namespace detail { namespace detail {
struct on_fn { struct on_fn {
PUSHMI_TEMPLATE(class ExecutorFactory) private:
(requires Invocable<ExecutorFactory&>) template <class In, class Out>
auto operator()(ExecutorFactory ef) const { struct on_value_impl {
return constrain(lazy::Sender<_1>, [ef = std::move(ef)](auto in) { In in_;
using In = decltype(in); Out out_;
return ::pushmi::detail::deferred_from<In, single<>>( void operator()(any) {
std::move(in), ::pushmi::submit(in_, std::move(out_));
::pushmi::detail::submit_transform_out<In>( }
constrain(lazy::SenderTo<In, _2>, [ef](In& in, auto out) { };
auto exec = ef(); template <class In, class ExecutorFactory>
struct out_impl {
ExecutorFactory ef_;
PUSHMI_TEMPLATE(class Out)
(requires SenderTo<In, Out>)
void operator()(In& in, Out out) const {
auto exec = ef_();
::pushmi::submit(exec, ::pushmi::now(exec), ::pushmi::submit(exec, ::pushmi::now(exec),
::pushmi::make_single([in = in, out = std::move(out)](auto) mutable { ::pushmi::make_single(on_value_impl<In, Out>{in, std::move(out)})
::pushmi::submit(in, std::move(out));
})
); );
}), }
constrain(lazy::TimeSenderTo<In, _3>, [ef](In& in, auto at, auto out) { };
auto exec = ef(); template <class In, class TP, class Out>
struct time_on_value_impl {
In in_;
TP at_;
Out out_;
void operator()(any) {
::pushmi::submit(in_, at_, std::move(out_));
}
};
template <class In, class ExecutorFactory>
struct time_out_impl {
ExecutorFactory ef_;
PUSHMI_TEMPLATE(class TP, class Out)
(requires TimeSenderTo<In, Out>)
void operator()(In& in, TP at, Out out) const {
auto exec = ef_();
::pushmi::submit(exec, at, ::pushmi::submit(exec, at,
::pushmi::on_value([in = in, at, out = std::move(out)](auto) mutable { ::pushmi::make_single(
::pushmi::submit(in, at, std::move(out)); time_on_value_impl<In, TP, Out>{in, at, std::move(out)}
}) )
); );
}) }
};
template <class ExecutorFactory>
struct in_impl {
ExecutorFactory ef_;
PUSHMI_TEMPLATE (class In)
(requires Sender<In>)
auto operator()(In in) const {
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
detail::submit_transform_out<In>(
out_impl<In, ExecutorFactory>{ef_},
time_out_impl<In, ExecutorFactory>{ef_}
) )
); );
}); }
};
public:
PUSHMI_TEMPLATE(class ExecutorFactory)
(requires Invocable<ExecutorFactory&>)
auto operator()(ExecutorFactory ef) const {
return in_impl<ExecutorFactory>{std::move(ef)};
} }
}; };
......
...@@ -25,15 +25,19 @@ struct send_via { ...@@ -25,15 +25,19 @@ struct send_via {
namespace detail { namespace detail {
struct request_via_fn { struct request_via_fn {
inline auto operator()() const; private:
}; struct impl {
PUSHMI_TEMPLATE(class In)
inline auto request_via_fn::operator()() const { (requires Sender<In>)
return constrain(lazy::Sender<_1>, [](auto in) { auto operator()(In in) const {
using In = decltype(in);
return send_via<In>{in}; return send_via<In>{in};
}); }
} };
public:
inline auto operator()() const {
return impl{};
}
};
} // namespace detail } // namespace detail
...@@ -44,7 +48,7 @@ PUSHMI_INLINE_VAR constexpr detail::request_via_fn request_via{}; ...@@ -44,7 +48,7 @@ PUSHMI_INLINE_VAR constexpr detail::request_via_fn request_via{};
} // namespace operators } // namespace operators
PUSHMI_TEMPLATE(class To, class In) PUSHMI_TEMPLATE(class To, class In)
(requires Same<To, is_sender<>> && Sender<_1>) (requires Same<To, is_sender<>> && Sender<In>)
auto via_cast(In in) { auto via_cast(In in) {
return in; return in;
} }
......
...@@ -18,24 +18,25 @@ namespace detail { ...@@ -18,24 +18,25 @@ namespace detail {
template<class T> template<class T>
struct share_fn { struct share_fn {
auto operator()() const; private:
}; struct impl {
PUSHMI_TEMPLATE (class In)
template<class T> (requires Sender<In>)
auto share_fn<T>::operator()() const { auto operator()(In in) const {
return constrain(lazy::Sender<_1>, [](auto in) {
using In = decltype(in);
subject<T, properties_t<In>> sub; subject<T, properties_t<In>> sub;
PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<In>) ( PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<In>) (
::pushmi::submit(in, ::pushmi::now(id(in)), sub.receiver()); ::pushmi::submit(in, ::pushmi::now(id(in)), sub.receiver());
) else ( ) else (
::pushmi::submit(id(in), sub.receiver()); ::pushmi::submit(id(in), sub.receiver());
)); ));
return sub; return sub;
}); }
} };
public:
auto operator()() const {
return impl{};
}
};
} // namespace detail } // namespace detail
......
...@@ -120,23 +120,17 @@ public: ...@@ -120,23 +120,17 @@ public:
struct blocking_submit_fn { struct blocking_submit_fn {
private: private:
// TODO - only move, move-only types.. struct lock_state {
// if out can be copied, then submit can be called multiple
// times..
template <class... AN>
struct fn {
std::tuple<AN...> args_;
template <bool IsTimeSender, class In>
In impl_(In in) {
bool done = false; bool done = false;
std::mutex lock; std::mutex lock;
std::condition_variable signaled; std::condition_variable signaled;
auto out{::pushmi::detail::out_from_fn<In>()( };
std::move(args_), struct on_value_impl {
on_value(constrain(pushmi::lazy::Receiver<_1, is_single<>>, lock_state* state_;
[&](auto out, auto&& v) { PUSHMI_TEMPLATE (class Out, class Value)
using V = remove_cvref_t<decltype(v)>; (requires Receiver<Out, is_single<>>)
void operator()(Out out, Value&& v) const {
using V = remove_cvref_t<Value>;
PUSHMI_IF_CONSTEXPR( ((bool)Time<V>) ( PUSHMI_IF_CONSTEXPR( ((bool)Time<V>) (
// to keep the blocking semantics, make sure that the // to keep the blocking semantics, make sure that the
// nested submits block here to prevent a spurious // nested submits block here to prevent a spurious
...@@ -144,38 +138,59 @@ private: ...@@ -144,38 +138,59 @@ private:
auto nest = ::pushmi::nested_trampoline(); auto nest = ::pushmi::nested_trampoline();
::pushmi::submit(nest, ::pushmi::now(nest), std::move(out)); ::pushmi::submit(nest, ::pushmi::now(nest), std::move(out));
) else ( ) else (
::pushmi::set_value(out, id((V&&) v)); ::pushmi::set_value(out, id((Value&&) v));
)) ))
std::unique_lock<std::mutex> guard{lock}; std::unique_lock<std::mutex> guard{state_->lock};
done = true; state_->done = true;
signaled.notify_all(); state_->signaled.notify_all();
} }
)), };
on_error(constrain(pushmi::lazy::NoneReceiver<_1, _2>, struct on_error_impl {
[&](auto out, auto e) noexcept { lock_state* state_;
PUSHMI_TEMPLATE(class Out, class E)
(requires NoneReceiver<Out, E>)
void operator()(Out out, E e) const noexcept {
::pushmi::set_error(out, std::move(e)); ::pushmi::set_error(out, std::move(e));
std::unique_lock<std::mutex> guard{lock}; std::unique_lock<std::mutex> guard{state_->lock};
done = true; state_->done = true;
signaled.notify_all(); state_->signaled.notify_all();
} }
)), };
on_done(constrain(pushmi::lazy::Receiver<_1>, struct on_done_impl {
[&](auto out){ lock_state* state_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void operator()(Out out) const {
::pushmi::set_done(out); ::pushmi::set_done(out);
std::unique_lock<std::mutex> guard{lock}; std::unique_lock<std::mutex> guard{state_->lock};
done = true; state_->done = true;
signaled.notify_all(); state_->signaled.notify_all();
} }
)) };
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
template <class... AN>
struct fn {
std::tuple<AN...> args_;
template <bool IsTimeSender, class In>
In impl_(In in) {
lock_state state{};
auto out{::pushmi::detail::out_from_fn<In>()(
std::move(args_),
on_value(on_value_impl{&state}),
on_error(on_error_impl{&state}),
on_done(on_done_impl{&state})
)}; )};
PUSHMI_IF_CONSTEXPR( (IsTimeSender) ( PUSHMI_IF_CONSTEXPR( (IsTimeSender) (
id(::pushmi::submit)(in, id(::pushmi::now)(in), std::move(out)); id(::pushmi::submit)(in, id(::pushmi::now)(in), std::move(out));
) else ( ) else (
id(::pushmi::submit)(in, std::move(out)); id(::pushmi::submit)(in, std::move(out));
)) ))
std::unique_lock<std::mutex> guard{lock}; std::unique_lock<std::mutex> guard{state.lock};
signaled.wait(guard, [&]{ state.signaled.wait(guard, [&]{
return done; return state.done;
}); });
return in; return in;
} }
...@@ -200,6 +215,18 @@ public: ...@@ -200,6 +215,18 @@ public:
template <class T> template <class T>
struct get_fn { struct get_fn {
private:
struct on_value_impl {
pushmi::detail::opt<T>* result_;
void operator()(T t) const { *result_ = std::move(t); }
};
struct on_error_impl {
std::exception_ptr* ep_;
template <class E>
void operator()(E e) const noexcept { *ep_ = std::make_exception_ptr(e); }
void operator()(std::exception_ptr ep) const noexcept { *ep_ = ep; }
};
public:
// TODO constrain this better // TODO constrain this better
PUSHMI_TEMPLATE (class In) PUSHMI_TEMPLATE (class In)
(requires Sender<In>) (requires Sender<In>)
...@@ -207,10 +234,8 @@ struct get_fn { ...@@ -207,10 +234,8 @@ struct get_fn {
pushmi::detail::opt<T> result_; pushmi::detail::opt<T> result_;
std::exception_ptr ep_; std::exception_ptr ep_;
auto out = make_single( auto out = make_single(
on_value([&](T t){ result_ = std::move(t); }), on_value(on_value_impl{&result_}),
on_error( on_error(on_error_impl{&ep_})
[&](auto e) noexcept { ep_ = std::make_exception_ptr(e); },
[&](std::exception_ptr ep) noexcept { ep_ = ep; })
); );
using Out = decltype(out); using Out = decltype(out);
static_assert(SenderTo<In, Out, is_single<>> || static_assert(SenderTo<In, Out, is_single<>> ||
......
...@@ -12,30 +12,50 @@ namespace pushmi { ...@@ -12,30 +12,50 @@ namespace pushmi {
namespace detail { namespace detail {
struct switch_on_error_fn { struct switch_on_error_fn {
PUSHMI_TEMPLATE(class ErrorSelector) private:
(requires SemiMovable<ErrorSelector>) template <class ErrorSelector>
auto operator()(ErrorSelector es) const { struct on_error_impl {
return constrain(lazy::Sender<_1>, [es = std::move(es)](auto in) { ErrorSelector es_;
using In = decltype(in); template <class Out, class E>
return ::pushmi::detail::deferred_from<In, single<>>( void operator()(Out& out, E&& e) const noexcept {
std::move(in), static_assert(::pushmi::NothrowInvocable<const ErrorSelector&, E>,
::pushmi::detail::submit_transform_out<In>( "switch_on_error - error selector function must be noexcept");
constrain(lazy::Receiver<_1>, [es](auto out) { auto next = es_((E&&) e);
using Out = decltype(out); ::pushmi::submit(next, out);
}
};
template <class In, class ErrorSelector>
struct out_impl {
ErrorSelector es_;
PUSHMI_TEMPLATE (class Out)
(requires Receiver<Out>)
auto operator()(Out out) const {
return ::pushmi::detail::out_from_fn<In>()( return ::pushmi::detail::out_from_fn<In>()(
std::move(out), std::move(out),
// copy 'es' to allow multiple calls to submit // copy 'es' to allow multiple calls to submit
::pushmi::on_error([es](auto& out, auto&& e) noexcept { ::pushmi::on_error(on_error_impl<ErrorSelector>{es_})
static_assert(::pushmi::NothrowInvocable<ErrorSelector, decltype(e)>,
"switch_on_error - error selector function must be noexcept");
auto next = es(std::move(e));
::pushmi::submit(next, std::move(out));
})
); );
}) }
};
template <class ErrorSelector>
struct in_impl {
ErrorSelector es_;
PUSHMI_TEMPLATE (class In)
(requires Sender<In>)
auto operator()(In in) const {
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
::pushmi::detail::submit_transform_out<In>(
out_impl<In, ErrorSelector>{es_}
) )
); );
}); }
};
public:
PUSHMI_TEMPLATE(class ErrorSelector)
(requires SemiMovable<ErrorSelector>)
auto operator()(ErrorSelector es) const {
return in_impl<ErrorSelector>{std::move(es)};
} }
}; };
......
...@@ -56,15 +56,6 @@ PUSHMI_INLINE_VAR constexpr struct make_tap_fn { ...@@ -56,15 +56,6 @@ PUSHMI_INLINE_VAR constexpr struct make_tap_fn {
} }
} const make_tap {}; } const make_tap {};
struct tap_fn {
private:
template <class In, class SideEffects>
static auto impl(In, SideEffects);
public:
template <class... AN>
auto operator()(AN... an) const;
};
#if __NVCC__ #if __NVCC__
#define PUSHMI_STATIC_ASSERT(...) #define PUSHMI_STATIC_ASSERT(...)
#elif __cpp_if_constexpr >= 201606 #elif __cpp_if_constexpr >= 201606
...@@ -76,19 +67,10 @@ inline void do_assert(bool condition, char const*) { ...@@ -76,19 +67,10 @@ inline void do_assert(bool condition, char const*) {
} }
#endif #endif
template <class... AN> struct tap_fn {
auto tap_fn::operator()(AN... an) const { private:
return constrain(lazy::Sender<_1>, template <class In, class SideEffects>
[args = std::tuple<AN...>{std::move(an)...}](auto in) mutable { static auto impl(In in, SideEffects sideEffects) {
using In = decltype(in);
return tap_fn::impl(
std::move(in),
::pushmi::detail::out_from_fn<In>()(std::move(args)));
});
}
template <class In, class SideEffects>
auto tap_fn::impl(In in, SideEffects sideEffects) {
PUSHMI_STATIC_ASSERT( PUSHMI_STATIC_ASSERT(
::pushmi::detail::deferred_requires_from<In, SideEffects, ::pushmi::detail::deferred_requires_from<In, SideEffects,
SenderTo<In, SideEffects, is_none<>>, SenderTo<In, SideEffects, is_none<>>,
...@@ -99,9 +81,28 @@ auto tap_fn::impl(In in, SideEffects sideEffects) { ...@@ -99,9 +81,28 @@ auto tap_fn::impl(In in, SideEffects sideEffects) {
return ::pushmi::detail::deferred_from<In, SideEffects>( return ::pushmi::detail::deferred_from<In, SideEffects>(
std::move(in), std::move(in),
::pushmi::detail::submit_transform_out<In>( ::pushmi::detail::submit_transform_out<In>(
constrain(lazy::Receiver<_1>, out_impl<In, SideEffects>{std::move(sideEffects)}
[sideEffects_ = std::move(sideEffects)](auto out) { )
using Out = decltype(out); );
}
template <class... AN>
struct in_impl {
std::tuple<AN...> args_;
PUSHMI_TEMPLATE (class In)
(requires Sender<In>)
auto operator()(In in) {
return tap_fn::impl(
std::move(in),
::pushmi::detail::out_from_fn<In>()(std::move(args_)));
}
};
template <class In, class SideEffects>
struct out_impl {
SideEffects sideEffects_;
PUSHMI_TEMPLATE (class Out)
(requires Receiver<Out>)
auto operator()(Out out) const {
PUSHMI_STATIC_ASSERT( PUSHMI_STATIC_ASSERT(
::pushmi::detail::deferred_requires_from<In, SideEffects, ::pushmi::detail::deferred_requires_from<In, SideEffects,
SenderTo<In, Out, is_none<>>, SenderTo<In, Out, is_none<>>,
...@@ -119,10 +120,13 @@ auto tap_fn::impl(In in, SideEffects sideEffects) { ...@@ -119,10 +120,13 @@ auto tap_fn::impl(In in, SideEffects sideEffects) {
"'In' is not deliverable to 'Out' & 'SideEffects'"); "'In' is not deliverable to 'Out' & 'SideEffects'");
return gang; return gang;
} }
) };
) public:
); template <class... AN>
} auto operator()(AN... an) const {
return in_impl<AN...>{{std::move(an)...}};
}
};
} // namespace detail } // namespace detail
......
...@@ -61,26 +61,31 @@ struct transform_on<F, is_many<>> { ...@@ -61,26 +61,31 @@ struct transform_on<F, is_many<>> {
}; };
struct transform_fn { struct transform_fn {
template <class... FN> private:
auto operator()(FN... fn) const; template <class F>
}; struct impl {
F f_;
template <class... FN> PUSHMI_TEMPLATE (class In)
auto transform_fn::operator()(FN... fn) const { (requires Sender<In>)
auto f = ::pushmi::overload(std::move(fn)...); auto operator()(In in) const {
return ::pushmi::constrain(::pushmi::lazy::Sender<::pushmi::_1>, [f = std::move(f)](auto in) {
using In = decltype(in);
// copy 'f' to allow multiple calls to connect to multiple 'in'
using F = decltype(f);
using Cardinality = property_set_index_t<properties_t<In>, is_silent<>>; using Cardinality = property_set_index_t<properties_t<In>, is_silent<>>;
return ::pushmi::detail::deferred_from<In>( return ::pushmi::detail::deferred_from<In>(
std::move(in), std::move(in),
::pushmi::detail::submit_transform_out<In>( ::pushmi::detail::submit_transform_out<In>(
transform_on<F, Cardinality>{f} // copy 'f_' to allow multiple calls to connect to multiple 'in'
transform_on<F, Cardinality>{f_}
) )
); );
}); }
} };
public:
template <class... FN>
auto operator()(FN... fn) const {
auto f = ::pushmi::overload(std::move(fn)...);
using F = decltype(f);
return impl<F>{std::move(f)};
}
};
} // namespace detail } // namespace detail
......
...@@ -26,59 +26,102 @@ auto make_via_fn_data(Out out, Executor ex) -> via_fn_data<Executor, Out> { ...@@ -26,59 +26,102 @@ auto make_via_fn_data(Out out, Executor ex) -> via_fn_data<Executor, Out> {
} }
struct via_fn { struct via_fn {
PUSHMI_TEMPLATE(class ExecutorFactory) private:
(requires Invocable<ExecutorFactory&>) template <class Out>
auto operator()(ExecutorFactory ef) const { struct on_value_impl {
return constrain(lazy::Sender<_1>, [ef = std::move(ef)](auto in) { template <class V>
using In = decltype(in); struct impl {
return ::pushmi::detail::deferred_from<In, single<>>( V v_;
std::move(in), Out out_;
::pushmi::detail::submit_transform_out<In>( void operator()(any) {
constrain(lazy::Receiver<_1>, [ef](auto out) { ::pushmi::set_value(out_, std::move(v_));
using Out = decltype(out); }
auto exec = ef(); };
return ::pushmi::detail::out_from_fn<In>()( template <class Data, class V>
make_via_fn_data(std::move(out), std::move(exec)), void operator()(Data& data, V&& v) const {
// copy 'f' to allow multiple calls to submit
::pushmi::on_value([](auto& data, auto&& v) {
using V = decltype(v);
::pushmi::submit( ::pushmi::submit(
data.exec, data.exec,
::pushmi::now(data.exec), ::pushmi::now(data.exec),
::pushmi::make_single( ::pushmi::make_single(
[v = (V&&)v, out = std::move(static_cast<Out&>(data))](auto) mutable { impl<std::decay_t<V>>{(V&&) v, std::move(static_cast<Out&>(data))}
::pushmi::set_value(out, std::move(v));
}
) )
); );
}), }
::pushmi::on_error([](auto& data, auto e) noexcept { };
template <class Out>
struct on_error_impl {
template <class E>
struct impl {
E e_;
Out out_;
void operator()(any) {
::pushmi::set_error(out_, std::move(e_));
}
};
template <class Data, class E>
void operator()(Data& data, E e) const noexcept {
::pushmi::submit( ::pushmi::submit(
data.exec, data.exec,
::pushmi::now(data.exec), ::pushmi::now(data.exec),
::pushmi::make_single( ::pushmi::make_single(
[e = std::move(e), out = std::move(static_cast<Out&>(data))](auto) mutable { impl<E>{std::move(e), std::move(static_cast<Out&>(data))}
::pushmi::set_error(out, std::move(e));
}
) )
); );
}), }
::pushmi::on_done([](auto& data){ };
template <class Out>
struct on_done_impl {
struct impl {
Out out_;
void operator()(any) {
::pushmi::set_done(out_);
}
};
template <class Data>
void operator()(Data& data) const {
::pushmi::submit( ::pushmi::submit(
data.exec, data.exec,
::pushmi::now(data.exec), ::pushmi::now(data.exec),
::pushmi::make_single( ::pushmi::make_single(
[out = std::move(static_cast<Out&>(data))](auto) mutable { impl{std::move(static_cast<Out&>(data))}
::pushmi::set_done(out);
}
) )
); );
}) }
};
template <class In, class ExecutorFactory>
struct out_impl {
ExecutorFactory ef_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
auto operator()(Out out) const {
auto exec = ef_();
return ::pushmi::detail::out_from_fn<In>()(
make_via_fn_data(std::move(out), std::move(exec)),
::pushmi::on_value(on_value_impl<Out>{}),
::pushmi::on_error(on_error_impl<Out>{}),
::pushmi::on_done(on_done_impl<Out>{})
); );
}) }
};
template <class ExecutorFactory>
struct in_impl {
ExecutorFactory ef_;
PUSHMI_TEMPLATE (class In)
(requires Sender<In>)
auto operator()(In in) const {
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
::pushmi::detail::submit_transform_out<In>(
out_impl<In, ExecutorFactory>{ef_}
) )
); );
}); }
};
public:
PUSHMI_TEMPLATE(class ExecutorFactory)
(requires Invocable<ExecutorFactory&>)
auto operator()(ExecutorFactory ef) const {
return in_impl<ExecutorFactory>{std::move(ef)};
} }
}; };
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
namespace pushmi { namespace pushmi {
PUSHMI_TEMPLATE (class In, class Op) PUSHMI_TEMPLATE (class In, class Op)
(requires defer::Sender<std::decay_t<In>> && defer::Invocable<Op&, In>) (requires lazy::Sender<std::decay_t<In>> && lazy::Invocable<Op&, In>)
decltype(auto) operator|(In&& in, Op op) { decltype(auto) operator|(In&& in, Op op) {
return op((In&&) in); return op((In&&) in);
} }
......
...@@ -283,7 +283,7 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn { ...@@ -283,7 +283,7 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn {
return single<>{}; return single<>{};
} }
PUSHMI_TEMPLATE(class VF) PUSHMI_TEMPLATE(class VF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<VF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF> PUSHMI_AND not lazy::Invocable<VF&>)))
auto operator()(VF vf) const { auto operator()(VF vf) const {
return single<VF, abortEF, ignoreDF>{std::move(vf)}; return single<VF, abortEF, ignoreDF>{std::move(vf)};
} }
...@@ -292,57 +292,57 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn { ...@@ -292,57 +292,57 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn {
return single<ignoreVF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)}; return single<ignoreVF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)};
} }
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
auto operator()(DF df) const { auto operator()(DF df) const {
return single<ignoreVF, abortEF, DF>{std::move(df)}; return single<ignoreVF, abortEF, DF>{std::move(df)};
} }
PUSHMI_TEMPLATE(class VF, class EF) PUSHMI_TEMPLATE(class VF, class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF> PUSHMI_AND not lazy::Invocable<EF&>)))
auto operator()(VF vf, EF ef) const { auto operator()(VF vf, EF ef) const {
return single<VF, EF, ignoreDF>{std::move(vf), std::move(ef)}; return single<VF, EF, ignoreDF>{std::move(vf), std::move(ef)};
} }
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
auto operator()(EF ef, DF df) const { auto operator()(EF ef, DF df) const {
return single<ignoreVF, EF, DF>{std::move(ef), std::move(df)}; return single<ignoreVF, EF, DF>{std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class VF, class EF, class DF) PUSHMI_TEMPLATE(class VF, class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF>)))
auto operator()(VF vf, EF ef, DF df) const { auto operator()(VF vf, EF ef, DF df) const {
return single<VF, EF, DF>{std::move(vf), std::move(ef), std::move(df)}; return single<VF, EF, DF>{std::move(vf), std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>>))
auto operator()(Data d) const { auto operator()(Data d) const {
return single<Data, passDVF, passDEF, passDDF>{std::move(d)}; return single<Data, passDVF, passDEF, passDDF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DVF) PUSHMI_TEMPLATE(class Data, class DVF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DVF&, Data&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DVF&, Data&>)))
auto operator()(Data d, DVF vf) const { auto operator()(Data d, DVF vf) const {
return single<Data, DVF, passDEF, passDDF>{std::move(d), std::move(vf)}; return single<Data, DVF, passDEF, passDDF>{std::move(d), std::move(vf)};
} }
PUSHMI_TEMPLATE(class Data, class... DEFN) PUSHMI_TEMPLATE(class Data, class... DEFN)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>>))
auto operator()(Data d, on_error_fn<DEFN...> ef) const { auto operator()(Data d, on_error_fn<DEFN...> ef) const {
return single<Data, passDVF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(ef)}; return single<Data, passDVF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(ef)};
} }
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DDF df) const { auto operator()(Data d, DDF df) const {
return single<Data, passDVF, passDEF, DDF>{std::move(d), std::move(df)}; return single<Data, passDVF, passDEF, DDF>{std::move(d), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data, class DVF, class DEF) PUSHMI_TEMPLATE(class Data, class DVF, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
auto operator()(Data d, DVF vf, DEF ef) const { auto operator()(Data d, DVF vf, DEF ef) const {
return single<Data, DVF, DEF, passDDF>{std::move(d), std::move(vf), std::move(ef)}; return single<Data, DVF, DEF, passDDF>{std::move(d), std::move(vf), std::move(ef)};
} }
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DEF ef, DDF df) const { auto operator()(Data d, DEF ef, DDF df) const {
return single<Data, passDVF, DEF, DDF>{std::move(d), std::move(ef), std::move(df)}; return single<Data, passDVF, DEF, DDF>{std::move(d), std::move(ef), std::move(df)};
} }
PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
auto operator()(Data d, DVF vf, DEF ef, DDF df) const { auto operator()(Data d, DVF vf, DEF ef, DDF df) const {
return single<Data, DVF, DEF, DDF>{std::move(d), std::move(vf), std::move(ef), std::move(df)}; return single<Data, DVF, DEF, DDF>{std::move(d), std::move(vf), std::move(ef), std::move(df)};
} }
...@@ -354,55 +354,55 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn { ...@@ -354,55 +354,55 @@ PUSHMI_INLINE_VAR constexpr struct make_single_fn {
single() -> single<>; single() -> single<>;
PUSHMI_TEMPLATE(class VF) PUSHMI_TEMPLATE(class VF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<VF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF> PUSHMI_AND not lazy::Invocable<VF&>)))
single(VF) -> single<VF, abortEF, ignoreDF>; single(VF) -> single<VF, abortEF, ignoreDF>;
template <class... EFN> template <class... EFN>
single(on_error_fn<EFN...>) -> single<ignoreVF, on_error_fn<EFN...>, ignoreDF>; single(on_error_fn<EFN...>) -> single<ignoreVF, on_error_fn<EFN...>, ignoreDF>;
PUSHMI_TEMPLATE(class DF) PUSHMI_TEMPLATE(class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<DF>)))
single(DF) -> single<ignoreVF, abortEF, DF>; single(DF) -> single<ignoreVF, abortEF, DF>;
PUSHMI_TEMPLATE(class VF, class EF) PUSHMI_TEMPLATE(class VF, class EF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<EF&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF> PUSHMI_AND not lazy::Invocable<EF&>)))
single(VF, EF) -> single<VF, EF, ignoreDF>; single(VF, EF) -> single<VF, EF, ignoreDF>;
PUSHMI_TEMPLATE(class EF, class DF) PUSHMI_TEMPLATE(class EF, class DF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<EF>)))
single(EF, DF) -> single<ignoreVF, EF, DF>; single(EF, DF) -> single<ignoreVF, EF, DF>;
PUSHMI_TEMPLATE(class VF, class EF, class DF) PUSHMI_TEMPLATE(class VF, class EF, class DF)
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF>))) (requires PUSHMI_EXP(lazy::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF>)))
single(VF, EF, DF) -> single<VF, EF, DF>; single(VF, EF, DF) -> single<VF, EF, DF>;
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>>))
single(Data d) -> single<Data, passDVF, passDEF, passDDF>; single(Data d) -> single<Data, passDVF, passDEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DVF) PUSHMI_TEMPLATE(class Data, class DVF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DVF&, Data&>))) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DVF&, Data&>)))
single(Data d, DVF vf) -> single<Data, DVF, passDEF, passDDF>; single(Data d, DVF vf) -> single<Data, DVF, passDEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class... DEFN) PUSHMI_TEMPLATE(class Data, class... DEFN)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>>))
single(Data d, on_error_fn<DEFN...>) -> single(Data d, on_error_fn<DEFN...>) ->
single<Data, passDVF, on_error_fn<DEFN...>, passDDF>; single<Data, passDVF, on_error_fn<DEFN...>, passDDF>;
PUSHMI_TEMPLATE(class Data, class DDF) PUSHMI_TEMPLATE(class Data, class DDF)
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::True<> PUSHMI_AND lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
single(Data d, DDF) -> single<Data, passDVF, passDEF, DDF>; single(Data d, DDF) -> single<Data, passDVF, passDEF, DDF>;
PUSHMI_TEMPLATE(class Data, class DVF, class DEF) PUSHMI_TEMPLATE(class Data, class DVF, class DEF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
single(Data d, DVF vf, DEF ef) -> single<Data, DVF, DEF, passDDF>; single(Data d, DVF vf, DEF ef) -> single<Data, DVF, DEF, passDDF>;
PUSHMI_TEMPLATE(class Data, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
single(Data d, DEF, DDF) -> single<Data, passDVF, DEF, DDF>; single(Data d, DEF, DDF) -> single<Data, passDVF, DEF, DDF>;
PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF) PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(lazy::Receiver<Data, is_single<>> PUSHMI_AND lazy::Invocable<DDF&, Data&>))
single(Data d, DVF vf, DEF ef, DDF df) -> single<Data, DVF, DEF, DDF>; single(Data d, DVF vf, DEF ef, DDF df) -> single<Data, DVF, DEF, DDF>;
#endif #endif
......
...@@ -109,7 +109,7 @@ class single_deferred<SF> { ...@@ -109,7 +109,7 @@ class single_deferred<SF> {
: sf_(std::move(sf)) {} : sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires PUSHMI_EXP(defer::Receiver<Out, is_single<>> PUSHMI_AND defer::Invocable<SF&, Out>)) (requires PUSHMI_EXP(lazy::Receiver<Out, is_single<>> PUSHMI_AND lazy::Invocable<SF&, Out>))
void submit(Out out) { void submit(Out out) {
sf_(std::move(out)); sf_(std::move(out));
} }
...@@ -130,8 +130,8 @@ class single_deferred_2 { ...@@ -130,8 +130,8 @@ class single_deferred_2 {
constexpr single_deferred_2(Data data, DSF sf) constexpr single_deferred_2(Data data, DSF sf)
: data_(std::move(data)), sf_(std::move(sf)) {} : data_(std::move(data)), sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires PUSHMI_EXP(defer::Receiver<Out, is_single<>> PUSHMI_AND (requires PUSHMI_EXP(lazy::Receiver<Out, is_single<>> PUSHMI_AND
defer::Invocable<DSF&, Data&, Out>)) lazy::Invocable<DSF&, Data&, Out>))
void submit(Out out) { void submit(Out out) {
sf_(data_, std::move(out)); sf_(data_, std::move(out));
} }
......
...@@ -132,7 +132,7 @@ PUSHMI_CONCEPT_DEF( ...@@ -132,7 +132,7 @@ PUSHMI_CONCEPT_DEF(
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template (class A, class B) template (class A, class B)
concept Derived, concept DerivedFrom,
__is_base_of(B, A) __is_base_of(B, A)
); );
...@@ -192,47 +192,6 @@ PUSHMI_CONCEPT_DEF( ...@@ -192,47 +192,6 @@ PUSHMI_CONCEPT_DEF(
Semiregular<T> && EqualityComparable<T> Semiregular<T> && EqualityComparable<T>
); );
#if 0 //__cpp_lib_invoke >= 201411
using std::invoke;
#else
PUSHMI_TEMPLATE (class F, class...As)
(requires requires (
std::declval<F>()(std::declval<As>()...)
))
decltype(auto) invoke(F&& f, As&&...as)
noexcept(noexcept(((F&&) f)((As&&) as...))) {
return ((F&&) f)((As&&) as...);
}
PUSHMI_TEMPLATE (class F, class...As)
(requires requires (
std::mem_fn(std::declval<F>())(std::declval<As>()...)
) && std::is_member_pointer<F>::value)
decltype(auto) invoke(F f, As&&...as)
noexcept(noexcept(std::declval<decltype(std::mem_fn(f))>()((As&&) as...))) {
return std::mem_fn(f)((As&&) as...);
}
#endif
template <class F, class...As>
using invoke_result_t =
decltype(pushmi::invoke(std::declval<F>(), std::declval<As>()...));
PUSHMI_CONCEPT_DEF(
template (class F, class... Args)
(concept Invocable)(F, Args...),
requires(F&& f) (
pushmi::invoke((F &&) f, std::declval<Args>()...)
)
);
PUSHMI_CONCEPT_DEF(
template (class F, class... Args)
(concept NothrowInvocable)(F, Args...),
requires(F&& f) (
requires_<noexcept(pushmi::invoke((F &&) f, std::declval<Args>()...))>
) &&
Invocable<F, Args...>
);
namespace detail { namespace detail {
// is_ taken from meta library // is_ taken from meta library
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment