Commit 0097bfef authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

support gcc-6.4, fixes #26

fbshipit-source-id: 0ac5905901904ad0853d5df2a29578d13d056e7a
parent af471d0d
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <utility> #include <utility>
#include "concepts.h" #include "concepts.h"
#include "traits.h"
namespace pushmi { namespace pushmi {
...@@ -162,6 +163,7 @@ struct overload_fn<Fn> : Fn { ...@@ -162,6 +163,7 @@ struct overload_fn<Fn> : Fn {
: Fn(std::move(fn)) {} : Fn(std::move(fn)) {}
using Fn::operator(); using Fn::operator();
}; };
#if !defined(__GNUC__) || __GNUC__ >= 8
template <class Fn, class... Fns> template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> { struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> {
constexpr overload_fn() = default; constexpr overload_fn() = default;
...@@ -170,6 +172,33 @@ struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> { ...@@ -170,6 +172,33 @@ struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> {
using Fn::operator(); using Fn::operator();
using overload_fn<Fns...>::operator(); using overload_fn<Fns...>::operator();
}; };
#else
template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> {
private:
std::pair<Fn, overload_fn<Fns...>> fns_;
template <bool B>
using _which_t = std::conditional_t<B, Fn, overload_fn<Fns...>>;
public:
constexpr overload_fn() = default;
constexpr overload_fn(Fn fn, Fns... fns)
: fns_{std::move(fn), overload_fn<Fns...>{std::move(fns)...}} {}
PUSHMI_TEMPLATE (class... Args)
(requires defer::Invocable<Fn&, Args...> ||
defer::Invocable<overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) PUSHMI_NOEXCEPT_AUTO(
std::declval<_which_t<Invocable<Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<Fn&, Args...>>(fns_)((Args &&) args...);
}
PUSHMI_TEMPLATE (class... Args)
(requires defer::Invocable<const Fn&, Args...> ||
defer::Invocable<const overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) const PUSHMI_NOEXCEPT_AUTO(
std::declval<const _which_t<Invocable<const Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<const Fn&, Args...>>(fns_)((Args &&) args...);
}
};
#endif
#endif #endif
template <class... Fns> template <class... Fns>
......
...@@ -25,8 +25,8 @@ class deferred<detail::erase_deferred_t, E> { ...@@ -25,8 +25,8 @@ class deferred<detail::erase_deferred_t, E> {
struct vtable { struct vtable {
static void s_op(data&, data*) {} static void s_op(data&, data*) {}
static void s_submit(data&, any_none<E>) {} static void s_submit(data&, any_none<E>) {}
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
void (*submit_)(data&, any_none<E>) = s_submit; void (*submit_)(data&, any_none<E>) = vtable::s_submit;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -138,24 +138,25 @@ class deferred<Data, DSF> { ...@@ -138,24 +138,25 @@ class deferred<Data, DSF> {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_deferred // make_deferred
inline auto make_deferred() -> deferred<ignoreSF> { PUSHMI_INLINE_VAR constexpr struct make_deferred_fn {
return deferred<ignoreSF>{}; inline auto operator()() const {
} return deferred<ignoreSF>{};
template <class SF> }
auto make_deferred(SF sf) -> deferred<SF> { template <class SF>
return deferred<SF>{std::move(sf)}; auto operator()(SF sf) const {
} return deferred<SF>{std::move(sf)};
PUSHMI_TEMPLATE(class Wrapped) }
(requires Sender<Wrapped, is_none<>>) PUSHMI_TEMPLATE(class Wrapped)
auto make_deferred(Wrapped w) -> (requires Sender<Wrapped, is_none<>>)
deferred<detail::erase_deferred_t, std::exception_ptr> { auto operator()(Wrapped w) const {
return deferred<detail::erase_deferred_t, std::exception_ptr>{std::move(w)}; return deferred<detail::erase_deferred_t, std::exception_ptr>{std::move(w)};
} }
PUSHMI_TEMPLATE(class Data, class DSF) PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_none<>>) (requires Sender<Data, is_none<>>)
auto make_deferred(Data data, DSF sf) -> deferred<Data, DSF> { auto operator()(Data data, DSF sf) const {
return deferred<Data, DSF>{std::move(data), std::move(sf)}; return deferred<Data, DSF>{std::move(data), std::move(sf)};
} }
} const make_deferred {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
#include <type_traits> #include <type_traits>
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
// disable buggy compatibility warning about "requires" and "concept" being // disable buggy compatibility warning about "requires" and "concept" being
// C++20 keywords. // C++20 keywords.
#if defined(__clang__) #if defined(__clang__)
...@@ -210,6 +214,11 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -210,6 +214,11 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
explicit constexpr operator bool() const noexcept { \ explicit constexpr operator bool() const noexcept { \
return (bool) defer::NAME<PUSHMI_PP_EXPAND ARGS>; \ 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 { \ constexpr auto operator!() const noexcept { \
return ::pushmi::concepts::detail::Not<Concept>{}; \ return ::pushmi::concepts::detail::Not<Concept>{}; \
} \ } \
...@@ -217,6 +226,10 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -217,6 +226,10 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
constexpr auto operator&&(That) const noexcept { \ constexpr auto operator&&(That) const noexcept { \
return ::pushmi::concepts::detail::And<Concept, That>{}; \ 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_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
PUSHMI_INLINE_VAR constexpr auto NAME = \ PUSHMI_INLINE_VAR constexpr auto NAME = \
...@@ -255,12 +268,18 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -255,12 +268,18 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
struct Eval { \ struct Eval { \
template <class C_ = Concept> \ template <class C_ = Concept> \
static constexpr decltype( \ static constexpr decltype( \
!&C_::template Requires_<PUSHMI_PP_EXPAND ARGS>) \ ::pushmi::concepts::detail::gcc_bugs( \
&C_::template Requires_<PUSHMI_PP_EXPAND ARGS>)) \
impl(int) noexcept { return true; } \ impl(int) noexcept { return true; } \
static constexpr bool impl(long) noexcept { return false; } \ static constexpr bool impl(long) noexcept { return false; } \
explicit constexpr operator bool() const noexcept { \ explicit constexpr operator bool() const noexcept { \
return Eval::impl(0); \ return Eval::impl(0); \
} \ } \
template <class PMThis = Concept, bool PMB, \
class = std::enable_if_t<PMB == (bool) PMThis{}>> \
constexpr operator std::integral_constant<bool, PMB>() const noexcept {\
return {}; \
} \
constexpr auto operator!() const noexcept { \ constexpr auto operator!() const noexcept { \
return ::pushmi::concepts::detail::Not<Eval>{}; \ return ::pushmi::concepts::detail::Not<Eval>{}; \
} \ } \
...@@ -268,6 +287,10 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN ...@@ -268,6 +287,10 @@ PUSHMI_PP_IGNORE_CXX2A_COMPAT_BEGIN
constexpr auto operator&&(That) const noexcept { \ constexpr auto operator&&(That) const noexcept { \
return ::pushmi::concepts::detail::And<Eval, That>{}; \ return ::pushmi::concepts::detail::And<Eval, That>{}; \
} \ } \
template <class That> \
constexpr auto operator||(That) const noexcept { \
return ::pushmi::concepts::detail::Or<Eval, That>{}; \
} \
}; \ }; \
}; \ }; \
PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \ PUSHMI_PP_CAT(PUSHMI_PP_DEF_, TPARAM) \
...@@ -421,17 +444,28 @@ using bool_ = std::integral_constant<bool, B>; ...@@ -421,17 +444,28 @@ using bool_ = std::integral_constant<bool, B>;
namespace concepts { namespace concepts {
namespace detail { namespace detail {
bool gcc_bugs(...);
template <class> template <class>
inline constexpr bool requires_() { inline constexpr bool requires_() {
return true; return true;
} }
template <class T, class U> template <class T, class U>
struct And; struct And;
template <class T, class U>
struct Or;
template <class T> template <class T>
struct Not { struct Not {
explicit constexpr operator bool() const noexcept { explicit constexpr operator bool() const noexcept {
return !(bool) T{}; return !(bool) T{};
} }
PUSHMI_TEMPLATE (class This = Not, bool B)
(requires B == (bool) This{})
constexpr operator std::integral_constant<bool, B>() const noexcept {
return {};
}
constexpr auto operator!() const noexcept { constexpr auto operator!() const noexcept {
return T{}; return T{};
} }
...@@ -439,23 +473,57 @@ struct Not { ...@@ -439,23 +473,57 @@ struct Not {
constexpr auto operator&&(That) const noexcept { constexpr auto operator&&(That) const noexcept {
return And<Not, That>{}; return And<Not, That>{};
} }
template <class That>
constexpr auto operator||(That) const noexcept {
return Or<Not, That>{};
}
}; };
template <class T, class U> template <class T, class U>
struct And { struct And {
static constexpr bool impl(std::false_type) noexcept { return false; }
static constexpr bool impl(std::true_type) noexcept { return (bool) U{}; }
explicit constexpr operator bool() const noexcept { explicit constexpr operator bool() const noexcept {
return And::impl(bool_<(bool) T{}>{}); return (bool) std::conditional_t<(bool) T{}, U, std::false_type>{};
}
PUSHMI_TEMPLATE (class This = And, bool B)
(requires B == (bool) This{})
constexpr operator std::integral_constant<bool, B>() const noexcept {
return {};
} }
constexpr auto operator!() const noexcept { constexpr auto operator!() const noexcept {
return Not<And>{}; return Not<And>{};
} }
template <class That> template <class That>
constexpr auto operator&&(That) const noexcept { constexpr auto operator&&(That) const noexcept {
return detail::And<And, That>{}; return And<And, That>{};
}
template <class That>
constexpr auto operator||(That) const noexcept {
return Or<And, That>{};
} }
}; };
template <class T, class U>
struct Or {
explicit constexpr operator bool() const noexcept {
return (bool) std::conditional_t<(bool) T{}, std::true_type, U>{};
}
PUSHMI_TEMPLATE (class This = Or, bool B)
(requires B == (bool) This{})
constexpr operator std::integral_constant<bool, B>() const noexcept {
return {};
}
constexpr auto operator!() const noexcept {
return Not<Or>{};
}
template <class That>
constexpr auto operator&&(That) const noexcept {
return And<Or, That>{};
}
template <class That>
constexpr auto operator||(That) const noexcept {
return Or<Or, That>{};
}
};
} // namespace detail } // namespace detail
} // namespace concepts } // namespace concepts
......
...@@ -79,14 +79,16 @@ struct id_fn { ...@@ -79,14 +79,16 @@ struct id_fn {
/**/ /**/
#define PUSHMI_IF_CONSTEXPR_THEN_(...) \ #define PUSHMI_IF_CONSTEXPR_THEN_(...) \
([&](auto id)->decltype(auto){__VA_ARGS__})) PUSHMI_COMMA \ ([&](auto id)mutable->decltype(auto){__VA_ARGS__})) PUSHMI_COMMA \
/**/ /**/
#define PUSHMI_IF_CONSTEXPR_ELSE_(A, B) \ #define PUSHMI_IF_CONSTEXPR_ELSE_(A, B) \
A ->* PUSHMI_IF_CONSTEXPR_ ## B \ A ->* PUSHMI_IF_CONSTEXPR_ ## B \
/**/ /**/
#define PUSHMI_IF_CONSTEXPR_else(...) ([&](auto id)->decltype(auto){__VA_ARGS__}); #define PUSHMI_IF_CONSTEXPR_else(...) \
([&](auto id)mutable->decltype(auto){__VA_ARGS__});\
/**/
namespace pushmi { namespace pushmi {
namespace detail { namespace detail {
......
...@@ -22,8 +22,8 @@ class flow_single_deferred<V, PE, E> { ...@@ -22,8 +22,8 @@ class flow_single_deferred<V, PE, E> {
struct vtable { struct vtable {
static void s_op(data&, data*) {} static void s_op(data&, data*) {}
static void s_submit(data&, flow_single<V, PE, E>) {} static void s_submit(data&, flow_single<V, PE, E>) {}
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
void (*submit_)(data&, flow_single<V, PE, E>) = s_submit; void (*submit_)(data&, flow_single<V, PE, E>) = vtable::s_submit;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -117,13 +117,15 @@ class flow_single_deferred<SF> { ...@@ -117,13 +117,15 @@ class flow_single_deferred<SF> {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_flow_single_deferred // make_flow_single_deferred
inline auto make_flow_single_deferred() -> flow_single_deferred<ignoreSF> { PUSHMI_INLINE_VAR constexpr struct make_flow_single_deferred_fn {
return flow_single_deferred<ignoreSF>{}; inline auto operator()() const {
} return flow_single_deferred<ignoreSF>{};
template <class SF> }
auto make_flow_single_deferred(SF sf) -> flow_single_deferred<SF> { template <class SF>
return flow_single_deferred<SF>(std::move(sf)); auto operator()(SF sf) const {
} return flow_single_deferred<SF>(std::move(sf));
}
} const make_flow_single_deferred {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -24,9 +24,9 @@ class none<E> { ...@@ -24,9 +24,9 @@ class none<E> {
static void s_op(data&, data*) {} static void s_op(data&, data*) {}
static void s_done(data&) {} static void s_done(data&) {}
static void s_error(data&, E) noexcept { std::terminate(); }; static void s_error(data&, E) noexcept { std::terminate(); };
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
void (*done_)(data&) = s_done; void (*done_)(data&) = vtable::s_done;
void (*error_)(data&, E) noexcept = s_error; void (*error_)(data&, E) noexcept = vtable::s_error;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -203,47 +203,49 @@ class none<> ...@@ -203,47 +203,49 @@ class none<>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_flow_single // make_flow_single
inline auto make_none() -> none<> { PUSHMI_INLINE_VAR constexpr struct make_none_fn {
return {}; inline auto operator()() const {
} return none<>{};
PUSHMI_TEMPLATE(class EF) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF> PUSHMI_AND not defer::Invocable<EF&>))) PUSHMI_TEMPLATE(class EF)
auto make_none(EF ef) -> none<EF, ignoreDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF> PUSHMI_AND not defer::Invocable<EF&>)))
return none<EF, ignoreDF>{std::move(ef)}; auto operator()(EF ef) const {
} return none<EF, ignoreDF>{std::move(ef)};
PUSHMI_TEMPLATE(class DF) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) PUSHMI_TEMPLATE(class DF)
auto make_none(DF df) -> none<abortEF, DF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>)))
return none<abortEF, DF>{std::move(df)}; auto operator()(DF df) const {
} return none<abortEF, DF>{std::move(df)};
PUSHMI_TEMPLATE(class EF, class DF) }
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>))) PUSHMI_TEMPLATE(class EF, class DF)
auto make_none(EF ef, DF df) -> none<EF, DF> { (requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>)))
return {std::move(ef), std::move(df)}; auto operator()(EF ef, DF df) const {
} return none<EF, DF>{std::move(ef), std::move(df)};
PUSHMI_TEMPLATE(class Data) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>>)) PUSHMI_TEMPLATE(class Data)
auto make_none(Data d) -> none<Data, passDEF, passDDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>>))
return none<Data, passDEF, passDDF>{std::move(d)}; auto operator()(Data d) const {
} return none<Data, passDEF, passDDF>{std::move(d)};
PUSHMI_TEMPLATE(class Data, class DEF) }
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_TEMPLATE(class Data, class DEF)
PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>))) (requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>>
auto make_none(Data d, DEF ef) -> none<Data, DEF, passDDF> { PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>)))
return {std::move(d), std::move(ef)}; auto operator()(Data d, DEF ef) const {
} return none<Data, DEF, passDDF>{std::move(d), std::move(ef)};
PUSHMI_TEMPLATE(class Data, class DDF) }
(requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND PUSHMI_TEMPLATE(class Data, class DDF)
defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND
auto make_none(Data d, DDF df) -> none<Data, passDEF, DDF> { defer::Invocable<DDF&, Data&>))
return {std::move(d), std::move(df)}; auto operator()(Data d, DDF df) const {
} return none<Data, passDEF, DDF>{std::move(d), std::move(df)};
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 PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
defer::Invocable<DDF&, Data&>)) (requires PUSHMI_EXP(defer::Receiver<Data, is_none<>> PUSHMI_AND not defer::Receiver<Data, is_single<>> PUSHMI_AND
auto make_none(Data d, DEF ef, DDF df) -> none<Data, DEF, DDF> { defer::Invocable<DDF&, Data&>))
return {std::move(d), std::move(ef), std::move(df)}; auto operator()(Data d, DEF ef, DDF df) const {
} return none<Data, DEF, DDF>{std::move(d), std::move(ef), std::move(df)};
}
} const make_none {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include "../piping.h" #include "../piping.h"
#include "../boosters.h" #include "../boosters.h"
#include "../single.h" #include "../single.h"
#include "../deferred.h"
#include "../single_deferred.h"
#include "../time_single_deferred.h"
#include "../detail/if_constexpr.h" #include "../detail/if_constexpr.h"
#include "../detail/functional.h" #include "../detail/functional.h"
...@@ -75,7 +78,7 @@ struct out_from_fn { ...@@ -75,7 +78,7 @@ struct out_from_fn {
PUSHMI_TEMPLATE(class In, class FN) PUSHMI_TEMPLATE(class In, class FN)
(requires Sender<In> && SemiMovable<FN>) (requires Sender<In> && SemiMovable<FN>)
auto submit_transform_out(FN fn){ auto submit_transform_out(FN fn){
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)TimeSender<In>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) TimeSender<In>) (
return on_submit( return on_submit(
constrain(lazy::Receiver<_3>, constrain(lazy::Receiver<_3>,
[fn = std::move(fn)](In& in, auto tp, auto out) { [fn = std::move(fn)](In& in, auto tp, auto out) {
...@@ -97,7 +100,7 @@ auto submit_transform_out(FN fn){ ...@@ -97,7 +100,7 @@ auto submit_transform_out(FN fn){
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>)
auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) { auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)TimeSender<In>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) TimeSender<In>) (
return on_submit( return on_submit(
constrain(lazy::Receiver<_3> && lazy::Invocable<TSDSF&, In&, _2, _3>, constrain(lazy::Receiver<_3> && lazy::Invocable<TSDSF&, In&, _2, _3>,
[tsdsf = std::move(tsdsf)](In& in, auto tp, auto out) { [tsdsf = std::move(tsdsf)](In& in, auto tp, auto out) {
...@@ -116,38 +119,33 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) { ...@@ -116,38 +119,33 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
)) ))
} }
PUSHMI_TEMPLATE(class In, class Out, class... FN) PUSHMI_TEMPLATE(class In, class Out)
(requires Sender<In> && Receiver<Out>) (requires Sender<In> && Receiver<Out>)
auto deferred_from(FN&&... fn) { auto deferred_from_maker() {
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)TimeSenderTo<In, Out, is_single<>>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) TimeSenderTo<In, Out, is_single<>>) (
return make_time_single_deferred((FN&&) fn...); return make_time_single_deferred;
) else ( ) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out, is_single<>>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) SenderTo<In, Out, is_single<>>) (
return make_single_deferred((FN&&) fn...); return make_single_deferred;
) else ( ) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) SenderTo<In, Out>) (
return make_deferred((FN&&) fn...); return make_deferred;
) else ( ) else (
)) ))
)) ))
)) ))
} }
PUSHMI_TEMPLATE(class In, class Out, class... FN)
(requires Sender<In> && Receiver<Out>)
auto deferred_from(FN&&... fn) {
return deferred_from_maker<In, Out>()((FN&&) fn...);
}
PUSHMI_TEMPLATE(class In, class Out, class... FN) PUSHMI_TEMPLATE(class In, class Out, class... FN)
(requires Sender<In> && Receiver<Out>) (requires Sender<In> && Receiver<Out>)
auto deferred_from(In in, FN&&... fn) { auto deferred_from(In in, FN&&... fn) {
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)TimeSenderTo<In, Out, is_single<>>) ( return deferred_from_maker<In, Out>()(std::move(in), (FN&&) fn...);
return make_time_single_deferred(id(std::move(in)), (FN&&) fn...);
) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out, is_single<>>) (
return make_single_deferred(id(std::move(in)), (FN&&) fn...);
) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out>) (
return make_deferred(id(std::move(in)), (FN&&) fn...);
) else (
))
))
))
} }
PUSHMI_TEMPLATE( PUSHMI_TEMPLATE(
...@@ -158,13 +156,13 @@ PUSHMI_TEMPLATE( ...@@ -158,13 +156,13 @@ PUSHMI_TEMPLATE(
bool TimeSingleSenderRequires) bool TimeSingleSenderRequires)
(requires Sender<In> && Receiver<Out>) (requires Sender<In> && Receiver<Out>)
constexpr bool deferred_requires_from() { constexpr bool deferred_requires_from() {
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)TimeSenderTo<In, Out, is_single<>>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) TimeSenderTo<In, Out, is_single<>>) (
return TimeSingleSenderRequires; return TimeSingleSenderRequires;
) else ( ) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out, is_single<>>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) SenderTo<In, Out, is_single<>>) (
return SingleSenderRequires; return SingleSenderRequires;
) else ( ) else (
PUSHMI_IF_CONSTEXPR_RETURN( ((bool)SenderTo<In, Out>) ( PUSHMI_IF_CONSTEXPR_RETURN( ((bool) SenderTo<In, Out>) (
return SenderRequires; return SenderRequires;
) else ( ) else (
)) ))
......
...@@ -47,12 +47,14 @@ struct tap_ { ...@@ -47,12 +47,14 @@ struct tap_ {
} }
}; };
PUSHMI_TEMPLATE(class SideEffects, class Out) PUSHMI_INLINE_VAR constexpr struct make_tap_fn {
(requires Receiver<SideEffects> && Receiver<Out> && PUSHMI_TEMPLATE(class SideEffects, class Out)
Receiver<tap_<SideEffects, Out>, property_set_index_t<properties_t<Out>, is_silent<>>>) (requires Receiver<SideEffects> && Receiver<Out> &&
auto make_tap(SideEffects se, Out out) -> tap_<SideEffects, Out> { Receiver<tap_<SideEffects, Out>, property_set_index_t<properties_t<Out>, is_silent<>>>)
return {std::move(se), std::move(out)}; auto operator()(SideEffects se, Out out) const {
} return tap_<SideEffects, Out>{std::move(se), std::move(out)};
}
} const make_tap {};
struct tap_fn { struct tap_fn {
template <class... AN> template <class... AN>
...@@ -89,7 +91,7 @@ auto tap_fn::operator()(AN... an) const { ...@@ -89,7 +91,7 @@ auto tap_fn::operator()(AN... an) const {
std::move(in), std::move(in),
::pushmi::detail::submit_transform_out<In>( ::pushmi::detail::submit_transform_out<In>(
constrain(lazy::Receiver<_1>, constrain(lazy::Receiver<_1>,
[sideEffects = std::move(sideEffects)](auto out) { [sideEffects_ = std::move(sideEffects)](auto out) {
using Out = decltype(out); using Out = decltype(out);
PUSHMI_STATIC_ASSERT( PUSHMI_STATIC_ASSERT(
::pushmi::detail::deferred_requires_from<In, SideEffects, ::pushmi::detail::deferred_requires_from<In, SideEffects,
...@@ -98,7 +100,7 @@ auto tap_fn::operator()(AN... an) const { ...@@ -98,7 +100,7 @@ auto tap_fn::operator()(AN... an) const {
TimeSenderTo<In, Out, is_single<>> >(), TimeSenderTo<In, Out, is_single<>> >(),
"'In' is not deliverable to 'Out'"); "'In' is not deliverable to 'Out'");
auto gang{::pushmi::detail::out_from_fn<In>()( auto gang{::pushmi::detail::out_from_fn<In>()(
detail::make_tap(sideEffects, std::move(out)))}; detail::make_tap(sideEffects_, std::move(out)))};
using Gang = decltype(gang); using Gang = decltype(gang);
PUSHMI_STATIC_ASSERT( PUSHMI_STATIC_ASSERT(
::pushmi::detail::deferred_requires_from<In, SideEffects, ::pushmi::detail::deferred_requires_from<In, SideEffects,
......
...@@ -14,11 +14,13 @@ namespace pushmi { ...@@ -14,11 +14,13 @@ namespace pushmi {
namespace detail { namespace detail {
// extracted this to workaround cuda compiler failure to compute the static_asserts in the nested lambda context // extracted this to workaround cuda compiler failure to compute the static_asserts in the nested lambda context
template<class F> template<class F>
struct transform_on_value { struct transform_on_value {
F f_; F f_;
transform_on_value() = default;
constexpr explicit transform_on_value(F f)
: f_(std::move(f)) {}
template<class Out, class V> template<class Out, class V>
auto operator()(Out& out, V&& v) { auto operator()(Out& out, V&& v) {
using Result = decltype(f_((V&&) v)); using Result = decltype(f_((V&&) v));
...@@ -38,10 +40,10 @@ struct transform_fn { ...@@ -38,10 +40,10 @@ struct transform_fn {
template <class... FN> template <class... FN>
auto transform_fn::operator()(FN... fn) const { auto transform_fn::operator()(FN... fn) const {
auto f = ::pushmi::overload(std::move(fn)...); auto f = ::pushmi::overload(std::move(fn)...);
using F = decltype(f);
return ::pushmi::constrain(::pushmi::lazy::Sender<::pushmi::_1>, [f = std::move(f)](auto in) { return ::pushmi::constrain(::pushmi::lazy::Sender<::pushmi::_1>, [f = std::move(f)](auto in) {
using In = decltype(in); using In = decltype(in);
// copy 'f' to allow multiple calls to connect to multiple 'in' // copy 'f' to allow multiple calls to connect to multiple 'in'
using F = decltype(f);
return ::pushmi::detail::deferred_from<In, ::pushmi::single<>>( return ::pushmi::detail::deferred_from<In, ::pushmi::single<>>(
std::move(in), std::move(in),
::pushmi::detail::submit_transform_out<In>( ::pushmi::detail::submit_transform_out<In>(
...@@ -51,7 +53,7 @@ auto transform_fn::operator()(FN... fn) const { ...@@ -51,7 +53,7 @@ auto transform_fn::operator()(FN... fn) const {
std::move(out), std::move(out),
// copy 'f' to allow multiple calls to submit // copy 'f' to allow multiple calls to submit
::pushmi::on_value( ::pushmi::on_value(
transform_on_value<F>{f} transform_on_value<F>(f)
// [f](Out& out, auto&& v) { // [f](Out& out, auto&& v) {
// using V = decltype(v); // using V = decltype(v);
// using Result = decltype(f((V&&) v)); // using Result = decltype(f((V&&) v));
......
...@@ -27,11 +27,11 @@ class single<V, E> { ...@@ -27,11 +27,11 @@ class single<V, E> {
static void s_error(data&, E) noexcept { std::terminate(); } static void s_error(data&, E) noexcept { std::terminate(); }
static void s_rvalue(data&, V&&) {} static void s_rvalue(data&, V&&) {}
static void s_lvalue(data&, V&) {} static void s_lvalue(data&, V&) {}
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
void (*done_)(data&) = s_done; void (*done_)(data&) = vtable::s_done;
void (*error_)(data&, E) noexcept = s_error; void (*error_)(data&, E) noexcept = vtable::s_error;
void (*rvalue_)(data&, V&&) = s_rvalue; void (*rvalue_)(data&, V&&) = vtable::s_rvalue;
void (*lvalue_)(data&, V&) = s_lvalue; void (*lvalue_)(data&, V&) = vtable::s_lvalue;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -278,74 +278,75 @@ public: ...@@ -278,74 +278,75 @@ public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_single // make_single
inline auto make_single() -> single<> { PUSHMI_INLINE_VAR constexpr struct make_single_fn {
return {}; inline auto operator()() const {
} return single<>{};
PUSHMI_TEMPLATE(class VF) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<VF&>))) PUSHMI_TEMPLATE(class VF)
auto make_single(VF vf) -> single<VF, abortEF, ignoreDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<VF&>)))
return single<VF, abortEF, ignoreDF>{std::move(vf)}; auto operator()(VF vf) const {
} return single<VF, abortEF, ignoreDF>{std::move(vf)};
template <class... EFN> }
auto make_single(on_error_fn<EFN...> ef) -> single<ignoreVF, on_error_fn<EFN...>, ignoreDF> { template <class... EFN>
return single<ignoreVF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)}; auto operator()(on_error_fn<EFN...> ef) const {
} return single<ignoreVF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)};
PUSHMI_TEMPLATE(class DF) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>))) PUSHMI_TEMPLATE(class DF)
auto make_single(DF df) -> single<ignoreVF, abortEF, DF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<DF>)))
return single<ignoreVF, abortEF, DF>{std::move(df)}; auto operator()(DF df) const {
} return single<ignoreVF, abortEF, DF>{std::move(df)};
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&>))) PUSHMI_TEMPLATE(class VF, class EF)
auto make_single(VF vf, EF ef) -> single<VF, EF, ignoreDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF> PUSHMI_AND not defer::Invocable<EF&>)))
return {std::move(vf), std::move(ef)}; auto operator()(VF vf, EF ef) const {
} return single<VF, EF, ignoreDF>{std::move(vf), std::move(ef)};
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>))) PUSHMI_TEMPLATE(class EF, class DF)
auto make_single(EF ef, DF df) -> single<ignoreVF, EF, DF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<EF>)))
return {std::move(ef), std::move(df)}; auto operator()(EF ef, DF df) const {
} return single<ignoreVF, EF, DF>{std::move(ef), std::move(df)};
PUSHMI_TEMPLATE(class VF, class EF, class DF) }
(requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF>))) PUSHMI_TEMPLATE(class VF, class EF, class DF)
auto make_single(VF vf, EF ef, DF df) -> single<VF, EF, DF> { (requires PUSHMI_EXP(defer::Invocable<DF&> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Receiver<VF>)))
return {std::move(vf), std::move(ef), std::move(df)}; auto operator()(VF vf, EF ef, DF df) const {
} return single<VF, EF, DF>{std::move(vf), std::move(ef), std::move(df)};
PUSHMI_TEMPLATE(class Data) }
(requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>>)) PUSHMI_TEMPLATE(class Data)
auto make_single(Data d) -> single<Data, passDVF, passDEF, passDDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>>))
return single<Data, passDVF, passDEF, passDDF>{std::move(d)}; auto operator()(Data d) const {
} return single<Data, passDVF, passDEF, passDDF>{std::move(d)};
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&>))) PUSHMI_TEMPLATE(class Data, class DVF)
auto make_single(Data d, DVF vf) -> single<Data, DVF, passDEF, passDDF> { (requires PUSHMI_EXP(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DVF&, Data&>)))
return {std::move(d), std::move(vf)}; auto operator()(Data d, DVF vf) const {
} return single<Data, DVF, passDEF, passDDF>{std::move(d), std::move(vf)};
PUSHMI_TEMPLATE(class Data, class... DEFN) }
(requires PUSHMI_EXP(defer::Receiver<Data, is_single<>>)) PUSHMI_TEMPLATE(class Data, class... DEFN)
auto make_single(Data d, on_error_fn<DEFN...> ef) -> (requires PUSHMI_EXP(defer::Receiver<Data, is_single<>>))
single<Data, passDVF, on_error_fn<DEFN...>, passDDF> { auto operator()(Data d, on_error_fn<DEFN...> ef) const {
return {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(defer::True<> PUSHMI_AND defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>))
auto make_single(Data d, DDF df) -> single<Data, passDVF, passDEF, DDF> { auto operator()(Data d, DDF df) const {
return {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(defer::Receiver<Data, is_single<>> PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not defer::Invocable<DEF&, Data&>)))
auto make_single(Data d, DVF vf, DEF ef) -> single<Data, DVF, DEF, passDDF> { auto operator()(Data d, DVF vf, DEF ef) const {
return {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(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>))
auto make_single(Data d, DEF ef, DDF df) -> single<Data, passDVF, DEF, DDF> { auto operator()(Data d, DEF ef, DDF df) const {
return {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(defer::Receiver<Data, is_single<>> PUSHMI_AND defer::Invocable<DDF&, Data&>))
auto make_single(Data d, DVF vf, DEF ef, DDF df) -> single<Data, DVF, DEF, DDF> { auto operator()(Data d, DVF vf, DEF ef, DDF df) const {
return {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)};
} }
} const make_single {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -22,8 +22,8 @@ class any_single_deferred { ...@@ -22,8 +22,8 @@ class any_single_deferred {
struct vtable { struct vtable {
static void s_op(data&, data*) {} static void s_op(data&, data*) {}
static void s_submit(data&, single<V, E>) {} static void s_submit(data&, single<V, E>) {}
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
void (*submit_)(data&, single<V, E>) = s_submit; void (*submit_)(data&, single<V, E>) = vtable::s_submit;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -154,24 +154,26 @@ struct single_deferred<A, B> ...@@ -154,24 +154,26 @@ struct single_deferred<A, B>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_single_deferred // make_single_deferred
inline auto make_single_deferred() -> single_deferred<ignoreSF> { PUSHMI_INLINE_VAR constexpr struct make_single_deferred_fn {
return {}; inline auto operator()() const {
} return single_deferred<ignoreSF>{};
PUSHMI_TEMPLATE(class SF) }
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>)) PUSHMI_TEMPLATE(class SF)
auto make_single_deferred(SF sf) -> single_deferred<SF> { (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
return single_deferred<SF>{std::move(sf)}; auto operator()(SF sf) const {
} return single_deferred<SF>{std::move(sf)};
PUSHMI_TEMPLATE(class Data) }
(requires True<> && Sender<Data, is_single<>>) PUSHMI_TEMPLATE(class Data)
auto make_single_deferred(Data d) -> single_deferred<Data, passDSF> { (requires True<> && Sender<Data, is_single<>>)
return single_deferred<Data, passDSF>{std::move(d)}; auto operator()(Data d) const {
} return single_deferred<Data, passDSF>{std::move(d)};
PUSHMI_TEMPLATE(class Data, class DSF) }
(requires Sender<Data, is_single<>>) PUSHMI_TEMPLATE(class Data, class DSF)
auto make_single_deferred(Data d, DSF sf) -> single_deferred<Data, DSF> { (requires Sender<Data, is_single<>>)
return {std::move(d), std::move(sf)}; auto operator()(Data d, DSF sf) const {
} return single_deferred<Data, DSF>{std::move(d), std::move(sf)};
}
} const make_single_deferred {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -26,9 +26,9 @@ class any_time_single_deferred { ...@@ -26,9 +26,9 @@ class any_time_single_deferred {
static void s_op(data&, data*) {} static void s_op(data&, data*) {}
static TP s_now(data&) { return TP{}; } static TP s_now(data&) { return TP{}; }
static void s_submit(data&, TP, single<V, E>) {} static void s_submit(data&, TP, single<V, E>) {}
void (*op_)(data&, data*) = s_op; void (*op_)(data&, data*) = vtable::s_op;
TP (*now_)(data&) = s_now; TP (*now_)(data&) = vtable::s_now;
void (*submit_)(data&, TP, single<V, E>) = s_submit; void (*submit_)(data&, TP, single<V, E>) = vtable::s_submit;
}; };
static constexpr vtable const noop_ {}; static constexpr vtable const noop_ {};
vtable const* vptr_ = &noop_; vtable const* vptr_ = &noop_;
...@@ -191,31 +191,31 @@ struct time_single_deferred<A, B, C> ...@@ -191,31 +191,31 @@ struct time_single_deferred<A, B, C>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// make_time_single_deferred // make_time_single_deferred
inline auto make_time_single_deferred() -> PUSHMI_INLINE_VAR constexpr struct make_time_single_deferred_fn {
time_single_deferred<ignoreSF, systemNowF> { inline auto operator()() const {
return {}; return time_single_deferred<ignoreSF, systemNowF>{};
} }
template <class SF> template <class SF>
auto make_time_single_deferred(SF sf) -> time_single_deferred<SF, systemNowF> { auto operator()(SF sf) const {
return time_single_deferred<SF, systemNowF>{std::move(sf)}; return time_single_deferred<SF, systemNowF>{std::move(sf)};
} }
PUSHMI_TEMPLATE (class SF, class NF) PUSHMI_TEMPLATE (class SF, class NF)
(requires Invocable<NF&>) (requires Invocable<NF&>)
auto make_time_single_deferred(SF sf, NF nf) -> time_single_deferred<SF, NF> { auto operator()(SF sf, NF nf) const {
return {std::move(sf), std::move(nf)}; return time_single_deferred<SF, NF>{std::move(sf), std::move(nf)};
} }
PUSHMI_TEMPLATE (class Data, class DSF) PUSHMI_TEMPLATE (class Data, class DSF)
(requires TimeSender<Data, is_single<>>) (requires TimeSender<Data, is_single<>>)
auto make_time_single_deferred(Data d, DSF sf) -> auto operator()(Data d, DSF sf) const {
time_single_deferred<Data, DSF, passDNF> { return time_single_deferred<Data, DSF, passDNF>{std::move(d), std::move(sf)};
return {std::move(d), std::move(sf)}; }
} PUSHMI_TEMPLATE (class Data, class DSF, class DNF)
PUSHMI_TEMPLATE (class Data, class DSF, class DNF) (requires TimeSender<Data, is_single<>> && Invocable<DNF&, Data&>)
(requires TimeSender<Data, is_single<>> && Invocable<DNF&, Data&>) auto operator()(Data d, DSF sf, DNF nf) const {
auto make_time_single_deferred(Data d, DSF sf, DNF nf) -> return time_single_deferred<Data, DSF, DNF>{std::move(d), std::move(sf),
time_single_deferred<Data, DSF, DNF> { std::move(nf)};
return {std::move(d), std::move(sf), std::move(nf)}; }
} } const make_time_single_deferred {};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// deduction guides // deduction guides
......
...@@ -9,6 +9,15 @@ ...@@ -9,6 +9,15 @@
#include "detail/concept_def.h" #include "detail/concept_def.h"
#define PUSHMI_NOEXCEPT_AUTO(...) \
noexcept(noexcept(static_cast<decltype((__VA_ARGS__))>(__VA_ARGS__)))\
/**/
#define PUSHMI_NOEXCEPT_RETURN(...) \
PUSHMI_NOEXCEPT_AUTO(__VA_ARGS__) {\
return (__VA_ARGS__);\
}\
/**/
namespace pushmi { namespace pushmi {
#if __cpp_fold_expressions >= 201603 #if __cpp_fold_expressions >= 201603
template <bool...Bs> template <bool...Bs>
......
...@@ -17,8 +17,9 @@ void none_test() { ...@@ -17,8 +17,9 @@ void none_test() {
auto out2 = pushmi::MAKE(none)(pushmi::abortEF{}, pushmi::ignoreDF{}); auto out2 = pushmi::MAKE(none)(pushmi::abortEF{}, pushmi::ignoreDF{});
auto out3 = pushmi::MAKE(none)([](auto e) noexcept{ e.get(); }); auto out3 = pushmi::MAKE(none)([](auto e) noexcept{ e.get(); });
auto out5 = pushmi::MAKE(none)( auto out5 = pushmi::MAKE(none)(
pushmi::on_error([](auto e)noexcept { pushmi::on_error(
e.get(); }, [](std::exception_ptr e) noexcept{} [](std::exception_ptr e) noexcept {},
[](auto e) noexcept { e.get(); }
)); ));
auto out6 = pushmi::MAKE(none)( auto out6 = pushmi::MAKE(none)(
pushmi::on_done([]() { })); pushmi::on_done([]() { }));
...@@ -34,8 +35,10 @@ void none_test() { ...@@ -34,8 +35,10 @@ void none_test() {
}); });
auto proxy5 = pushmi::MAKE(none)( auto proxy5 = pushmi::MAKE(none)(
out0, out0,
pushmi::on_error([](Out0&, auto e) noexcept{ e.get(); }, pushmi::on_error(
[](Out0&, std::exception_ptr e) noexcept{})); [](Out0&, std::exception_ptr e) noexcept{},
[](Out0&, auto e) noexcept{ e.get(); }
));
auto proxy6 = pushmi::MAKE(none)( auto proxy6 = pushmi::MAKE(none)(
out0, out0,
pushmi::on_done([](Out0&) { })); pushmi::on_done([](Out0&) { }));
...@@ -84,12 +87,14 @@ void single_test() { ...@@ -84,12 +87,14 @@ void single_test() {
auto out5 = pushmi::MAKE(single)( auto out5 = pushmi::MAKE(single)(
pushmi::on_value([](auto v) { v.get(); }, [](int v) {}), pushmi::on_value([](auto v) { v.get(); }, [](int v) {}),
pushmi::on_error( pushmi::on_error(
[](auto e)noexcept { e.get(); }, [](std::exception_ptr e) noexcept {},
[](std::exception_ptr e) noexcept{})); [](auto e)noexcept { e.get(); }
));
auto out6 = pushmi::MAKE(single)( auto out6 = pushmi::MAKE(single)(
pushmi::on_error( pushmi::on_error(
[](auto e) noexcept{ e.get(); }, [](std::exception_ptr e) noexcept {},
[](std::exception_ptr e) noexcept{})); [](auto e) noexcept { e.get(); }
));
auto out7 = pushmi::MAKE(single)( auto out7 = pushmi::MAKE(single)(
pushmi::on_done([]() { })); pushmi::on_done([]() { }));
...@@ -106,12 +111,16 @@ void single_test() { ...@@ -106,12 +111,16 @@ void single_test() {
auto proxy5 = pushmi::MAKE(single)( auto proxy5 = pushmi::MAKE(single)(
out0, out0,
pushmi::on_value([](Out0&, auto v) { v.get(); }, [](Out0&, int v) {}), pushmi::on_value([](Out0&, auto v) { v.get(); }, [](Out0&, int v) {}),
pushmi::on_error([](Out0&, auto e) noexcept { e.get(); }, pushmi::on_error(
[](Out0&, std::exception_ptr e) noexcept {})); [](Out0&, std::exception_ptr e) noexcept {},
[](Out0&, auto e) noexcept { e.get(); }
));
auto proxy6 = pushmi::MAKE(single)( auto proxy6 = pushmi::MAKE(single)(
out0, out0,
pushmi::on_error([](Out0&, auto e) noexcept { e.get(); }, pushmi::on_error(
[](Out0&, std::exception_ptr e) noexcept {})); [](Out0&, std::exception_ptr e) noexcept {},
[](Out0&, auto e) noexcept { e.get(); }
));
auto proxy7 = pushmi::MAKE(single)( auto proxy7 = pushmi::MAKE(single)(
out0, out0,
pushmi::on_done([](Out0&) { })); pushmi::on_done([](Out0&) { }));
...@@ -232,12 +241,14 @@ void flow_single_test() { ...@@ -232,12 +241,14 @@ void flow_single_test() {
auto out5 = pushmi::MAKE(flow_single)( auto out5 = pushmi::MAKE(flow_single)(
pushmi::on_value([](auto v) { v.get(); }, [](int v) {}), pushmi::on_value([](auto v) { v.get(); }, [](int v) {}),
pushmi::on_error( pushmi::on_error(
[](auto e)noexcept { e.get(); }, [](std::exception_ptr e) noexcept{},
[](std::exception_ptr e) noexcept{})); [](auto e) noexcept { e.get(); }
));
auto out6 = pushmi::MAKE(flow_single)( auto out6 = pushmi::MAKE(flow_single)(
pushmi::on_error( pushmi::on_error(
[](auto e) noexcept{ e.get(); }, [](std::exception_ptr e) noexcept {},
[](std::exception_ptr e) noexcept{})); [](auto e) noexcept{ e.get(); }
));
auto out7 = pushmi::MAKE(flow_single)( auto out7 = pushmi::MAKE(flow_single)(
pushmi::on_done([]() { })); pushmi::on_done([]() { }));
...@@ -268,12 +279,16 @@ void flow_single_test() { ...@@ -268,12 +279,16 @@ void flow_single_test() {
auto proxy5 = pushmi::MAKE(flow_single)( auto proxy5 = pushmi::MAKE(flow_single)(
out0, out0,
pushmi::on_value([](Out0&, auto v) { v.get(); }, [](Out0&, int v) {}), pushmi::on_value([](Out0&, auto v) { v.get(); }, [](Out0&, int v) {}),
pushmi::on_error([](Out0&, auto e) noexcept { e.get(); }, pushmi::on_error(
[](Out0&, std::exception_ptr e) noexcept {})); [](Out0&, std::exception_ptr e) noexcept {},
[](Out0&, auto e) noexcept { e.get(); }
));
auto proxy6 = pushmi::MAKE(flow_single)( auto proxy6 = pushmi::MAKE(flow_single)(
out0, out0,
pushmi::on_error([](Out0&, auto e) noexcept { e.get(); }, pushmi::on_error(
[](Out0&, std::exception_ptr e) noexcept {})); [](Out0&, std::exception_ptr e) noexcept {},
[](Out0&, auto e) noexcept { e.get(); }
));
auto proxy7 = pushmi::MAKE(flow_single)( auto proxy7 = pushmi::MAKE(flow_single)(
out0, out0,
pushmi::on_done([](Out0&) { })); pushmi::on_done([](Out0&) { }));
......
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