8 template<
typename FutType,
typename FutVariant>
9 struct future_variant_getter {
11 using RetVal = decltype(get<FutType>(*owner).get());
13 auto &ft = get<FutType>(*owner);
18 template<
typename FutVariant>
19 struct future_variant_getter<void, FutVariant> {
23 if (holds_alternative<deferred_future<T> >(*owner)) {
24 return get<deferred_future<T> >(*owner).get();
26 return get<future<T> >(*owner).get();
32 class future_variant_interface {
36 std::coroutine_handle<> (*on_suspend)(
void *ptr, std::coroutine_handle<> h);
37 bool await_ready()
const {
return ptr ==
nullptr;}
38 std::coroutine_handle<> await_suspend(std::coroutine_handle<> h) {
39 return on_suspend(ptr, h);
41 void await_resume() noexcept {}
44 constexpr
virtual ~future_variant_interface() =
default;
45 virtual void destroy_at(
void *ptr)
const = 0;
46 virtual awaiter on_await(
void *ptr)
const = 0;
47 virtual void on_wait(
void *ptr)
const = 0;
50 template<
typename Fut>
51 class future_variant_impl :
public future_variant_interface{
53 virtual void destroy_at(
void *ptr)
const override {
54 std::destroy_at(
reinterpret_cast<Fut *
>(ptr));
56 virtual awaiter on_await(
void *ptr)
const override{
57 return {ptr, [](
void *ptr, std::coroutine_handle<> h){
58 return reinterpret_cast<Fut *
>(ptr)->await_suspend(h);
61 virtual void on_wait(
void *ptr)
const override{
62 reinterpret_cast<Fut *
>(ptr)->wait();
67 class future_variant_impl<std::nullptr_t> :
public future_variant_interface{
69 virtual void destroy_at(
void *)
const override{}
70 virtual awaiter on_await(
void *)
const override{
return {}; }
71 virtual void on_wait(
void *)
const override{}
74 template<
typename Fut>
75 inline constexpr future_variant_impl<Fut> future_variant_control = {};
105 template<
typename ... Types>
113 control->destroy_at(buffer);
123 template<std::invocable<> Fn>
125 control->destroy_at(buffer);
126 using fut_type = std::invoke_result_t<Fn>;
127 static_assert(
sizeof(fut_type) <= buffer_size,
"Returned future is not expected");
128 fut_type *ptr =
new(buffer) fut_type(fn());
129 control = &_details::future_variant_control<fut_type>;
135 control->destroy_at(buffer);
136 control = &_details::future_variant_control<std::nullptr_t>;
144 template<
typename promise_type>
146 using fut_type =
typename promise_type::FutureType;
147 static_assert(
sizeof(fut_type) <= buffer_size,
"Future type is not expected");
148 fut_type *ptr =
new(buffer) fut_type;
149 p = ptr->get_promise();
150 control = &_details::future_variant_control<fut_type>;
160 template<
typename fut_type,
typename ... X>
169 template<
typename fut_type,
typename ... X>
181 template<
typename fut_type,
typename ... X>
184 template<
typename FutType,
typename FutVariant>
185 friend struct future_variant_getter;
196 template<
typename fut_type =
void>
197 _details::future_variant_getter<fut_type, future_variant>
get() {
201 using awaiter = _details::future_variant_interface::awaiter;
211 awaiter
operator co_await() {
212 return control->on_await(buffer);
217 return control->on_wait(buffer);
222 static constexpr
auto buffer_size = std::max({
sizeof(
future<Types>)...});
223 const _details::future_variant_interface *control = &_details::future_variant_control<std::nullptr_t>;
224 char buffer[buffer_size];
227 template<
typename fut_type,
typename ... Types>
228 const fut_type &get(
const future_variant<Types...> &me) {
229 if (me.control != &_details::future_variant_control<fut_type>) {
230 throw std::bad_variant_access();
232 return *
reinterpret_cast<const fut_type *
>(me.buffer);
235 template<
typename fut_type,
typename ... Types>
236 fut_type &get( future_variant<Types...> &me) {
237 if (me.control != &_details::future_variant_control<fut_type>) {
238 throw std::bad_variant_access();
240 return *
reinterpret_cast<fut_type *
>(me.buffer);
243 template<
typename fut_type,
typename ... Types>
244 bool holds_alternative(future_variant<Types...> &me) {
245 return (me.control == &_details::future_variant_control<fut_type>);
auto & operator<<(Fn &&fn)
Redirect return value to future object.
auto & get_promise(promise_type &p)
Initialize underlying future and retrieves promise.
void wait()
Helps to wait on future regardless on which variant is active.
friend fut_type & get(future_variant< X... > &me)
Retrieve reference to future - if it is current variant.
friend bool holds_alternative(future_variant< X... > &me)
tests whether holds given variant
_details::future_variant_getter< fut_type, future_variant > get()
Retrieve result of the future.
void reset()
Delete any underlying future and return object into uninitalized state.
friend const fut_type & get(const future_variant< X... > &me)
Retrieve reference to future - if it is current variant.
makes a variant future - multiple futures shares single space
Contains future value of T, can be co_awaited in coroutine.