diff --git a/include/stdexec/__detail/__basic_sender.hpp b/include/stdexec/__detail/__basic_sender.hpp index ac552923e..176939e2f 100644 --- a/include/stdexec/__detail/__basic_sender.hpp +++ b/include/stdexec/__detail/__basic_sender.hpp @@ -182,7 +182,7 @@ namespace STDEXEC { using __tag_t = __decay_t<_Sexpr>::__tag_t; using __state_t = __state_type_t<__tag_t, _Sexpr, _Receiver>; - explicit __op_base(_Sexpr&& __sndr, _Receiver&& __rcvr) noexcept(noexcept( + explicit constexpr __op_base(_Sexpr&& __sndr, _Receiver&& __rcvr) noexcept(noexcept( __state_t(__sexpr_impl<__tag_t>::get_state(__declval<_Sexpr>(), __declval<_Receiver>())))) : __state_( __sexpr_impl<__tag_t>::get_state( @@ -220,7 +220,7 @@ namespace STDEXEC { return __impl{__op_}(__indices_for<_Child...>(), static_cast<_Child&&>(__child)...); } - auto operator()(__ignore, __ignore) const noexcept -> __tuple<> { + constexpr auto operator()(__ignore, __ignore) const noexcept -> __tuple<> { return {}; } @@ -290,7 +290,7 @@ namespace STDEXEC { using __state_t = __op_state::__op_base::__state_t; using __inner_ops_t = __apply_result_t<__detail::__connect_fn<_Sexpr, _Receiver>, _Sexpr>; - explicit __op_state(_Sexpr&& __sexpr, _Receiver __rcvr) noexcept( + explicit constexpr __op_state(_Sexpr&& __sexpr, _Receiver __rcvr) noexcept( __nothrow_constructible_from<__detail::__op_base<_Sexpr, _Receiver>, _Sexpr, _Receiver> && __nothrow_applicable<__detail::__connect_fn<_Sexpr, _Receiver>, _Sexpr>) : __op_state::__op_base{static_cast<_Sexpr&&>(__sexpr), static_cast<_Receiver&&>(__rcvr)} @@ -299,7 +299,7 @@ namespace STDEXEC { static_cast<_Sexpr&&>(__sexpr))) { } - STDEXEC_ATTRIBUTE(always_inline) void start() & noexcept { + STDEXEC_ATTRIBUTE(always_inline) constexpr void start() & noexcept { using __tag_t = __op_state::__tag_t; STDEXEC::__apply( [&](auto&... __ops) noexcept { __sexpr_impl<__tag_t>::start(this->__state_, __ops...); }, diff --git a/include/stdexec/__detail/__domain.hpp b/include/stdexec/__detail/__domain.hpp index 9b44ac56c..690aef218 100644 --- a/include/stdexec/__detail/__domain.hpp +++ b/include/stdexec/__detail/__domain.hpp @@ -69,7 +69,7 @@ namespace STDEXEC { template STDEXEC_ATTRIBUTE(always_inline) - auto transform_sender(_OpTag, _Sender&& __sndr, const _Env&) const + constexpr auto transform_sender(_OpTag, _Sender&& __sndr, const _Env&) const noexcept(__nothrow_move_constructible<_Sender>) -> _Sender { return static_cast<_Sender>(static_cast<_Sender&&>(__sndr)); } diff --git a/include/stdexec/__detail/__just.hpp b/include/stdexec/__detail/__just.hpp index fdd20c115..4ffbf350e 100644 --- a/include/stdexec/__detail/__just.hpp +++ b/include/stdexec/__detail/__just.hpp @@ -68,7 +68,7 @@ namespace STDEXEC { template <__movable_value... _Ts> STDEXEC_ATTRIBUTE(host, device) - auto operator()(_Ts&&... __ts) const noexcept(__nothrow_decay_copyable<_Ts...>) { + constexpr auto operator()(_Ts&&... __ts) const noexcept(__nothrow_decay_copyable<_Ts...>) { return __make_sexpr(__tuple{static_cast<_Ts&&>(__ts)...}); } }; diff --git a/include/stdexec/__detail/__operation_states.hpp b/include/stdexec/__detail/__operation_states.hpp index d2dbca969..0ea0123bd 100644 --- a/include/stdexec/__detail/__operation_states.hpp +++ b/include/stdexec/__detail/__operation_states.hpp @@ -37,7 +37,7 @@ namespace STDEXEC { template requires __has_start<_Op> STDEXEC_ATTRIBUTE(always_inline) - void operator()(_Op &__op) const noexcept { + constexpr void operator()(_Op &__op) const noexcept { static_assert(noexcept(__op.start()), "start() members must be noexcept"); static_assert(__same_as, "start() members must return void"); __op.start(); diff --git a/include/stdexec/__detail/__receivers.hpp b/include/stdexec/__detail/__receivers.hpp index 1a01d6a97..a6abdf32b 100644 --- a/include/stdexec/__detail/__receivers.hpp +++ b/include/stdexec/__detail/__receivers.hpp @@ -61,7 +61,7 @@ namespace STDEXEC { template requires __set_value_member<_Receiver, _As...> STDEXEC_ATTRIBUTE(host, device, always_inline) - void operator()(_Receiver &&__rcvr, _As &&...__as) const noexcept { + constexpr void operator()(_Receiver &&__rcvr, _As &&...__as) const noexcept { static_assert( noexcept(static_cast<_Receiver &&>(__rcvr).set_value(static_cast<_As &&>(__as)...)), "set_value member functions must be noexcept"); diff --git a/include/stdexec/__detail/__utility.hpp b/include/stdexec/__detail/__utility.hpp index f45f76b35..f9afcc015 100644 --- a/include/stdexec/__detail/__utility.hpp +++ b/include/stdexec/__detail/__utility.hpp @@ -141,7 +141,7 @@ namespace STDEXEC { // A derived-to-base cast that works even when the base is not accessible from derived. template STDEXEC_ATTRIBUTE(host, device) - auto __c_upcast(_Up&& u) noexcept -> __copy_cvref_t<_Up&&, _Tp> + constexpr auto __c_upcast(_Up&& u) noexcept -> __copy_cvref_t<_Up&&, _Tp> requires __decays_to<_Tp, _Tp> { static_assert(STDEXEC_IS_BASE_OF(_Tp, __decay_t<_Up>)); diff --git a/test/stdexec/algos/factories/test_just.cpp b/test/stdexec/algos/factories/test_just.cpp index a19c34c69..cc2c26f4e 100644 --- a/test/stdexec/algos/factories/test_just.cpp +++ b/test/stdexec/algos/factories/test_just.cpp @@ -181,4 +181,14 @@ namespace { ::STDEXEC::start(op); CHECK(invoked == 1); } + + TEST_CASE("just compile time", "[not][sure]") { + static_assert([](const double value) constexpr -> double { + auto sndr = ::STDEXEC::just(value); + double placeholder = 0; + auto opstate = ::STDEXEC::connect(std::move(sndr), expect_value_receiver_ex{placeholder}); + ::STDEXEC::start(opstate); + return placeholder; + }(42) == 42); + } } // namespace diff --git a/test/test_common/receivers.hpp b/test/test_common/receivers.hpp index 96185526e..e21c246da 100644 --- a/test/test_common/receivers.hpp +++ b/test/test_common/receivers.hpp @@ -218,7 +218,7 @@ namespace { public: using receiver_concept = STDEXEC::receiver_t; - explicit expect_value_receiver_ex(T& dest) + explicit constexpr expect_value_receiver_ex(T& dest) : dest_(&dest) { } @@ -227,7 +227,7 @@ namespace { , env_(std::move(env)) { } - void set_value(T val) noexcept { + constexpr void set_value(T val) noexcept { *dest_ = val; } @@ -244,7 +244,7 @@ namespace { FAIL_CHECK("set_error called on expect_value_receiver_ex"); } - auto get_env() const noexcept -> Env { + constexpr auto get_env() const noexcept -> Env { return env_; } };