diff --git a/include/seastar/core/coroutine.hh b/include/seastar/core/coroutine.hh index 4373db5cdc4..a25bb7f19aa 100644 --- a/include/seastar/core/coroutine.hh +++ b/include/seastar/core/coroutine.hh @@ -49,9 +49,9 @@ public: promise_type(promise_type&&) = delete; promise_type(const promise_type&) = delete; - template - void return_value(U&&... value) { - _promise.set_value(std::forward(value)...); + template + void return_value(U&& value) { + _promise.set_value(internal::implicit_tag{}, std::forward(value)); } void return_value(coroutine::exception ce) noexcept { diff --git a/include/seastar/core/future.hh b/include/seastar/core/future.hh index 47519581aa6..d6e5f293a80 100644 --- a/include/seastar/core/future.hh +++ b/include/seastar/core/future.hh @@ -282,6 +282,13 @@ struct get0_return_type { template using maybe_wrap_ref = std::conditional_t, std::reference_wrapper>, T>; +// indicate that a single parameter is used and only implicit conversions should be considered +struct implicit_tag {}; +template +T id(U &&v) { + return std::forward(v); +} + /// \brief Wrapper for keeping uninitialized values of non default constructible types. /// /// This is similar to a std::optional, but it doesn't know if it is holding a value or not, so the user is @@ -304,6 +311,10 @@ struct uninitialized_wrapper_base { public: uninitialized_wrapper_base() noexcept = default; + template + void uninitialized_set(implicit_tag, U&& v) { + new (&_v.value) maybe_wrap_ref(id(std::forward(v))); + } template std::enable_if_t...>, std::tuple>, void> uninitialized_set(U&&... vs) { @@ -326,6 +337,10 @@ public: template struct uninitialized_wrapper_base : private T { using tuple_type = future_tuple_type_t; uninitialized_wrapper_base() noexcept = default; + template + void uninitialized_set(implicit_tag, U&& v) { + new (this) T(id(std::forward(v))); + } template std::enable_if_t...>, std::tuple>, void> uninitialized_set(U&&... vs) {