what to `co_return` when I don't need to return anything?

230 views Asked by At

I have a specific use case:

In my library, concurrencpp, I want to implement the function make_exceptional_lazy_result which is basically like the C# method Task.FromException.

Inside the implementation of this function, I will always throw an exception, I will never co_return a valid object.

My current implementation looks like this:

template<class type, class exception_type>
lazy_result<type> make_exceptional_lazy_result(exception_type exception) {
    throw exception;
    co_return *static_cast<type*>(std::malloc(sizeof(type)));
}

I'm grossed by the malloc hack - In one hand, I have to co_return something, on the other hand, the program will never actually reach this line.

Can I do better? I'm worried about returning a reference to an uninitialized local memory (I don't know if according to the language it's ok).

What other options can I do here that look better? Note that type is not necessarily default-constructable, so returning a type{} is not an option.

3

There are 3 answers

2
Caleth On BEST ANSWER

You can write your own awaitable type which throws the exception when co_awaited.

template<class type, class exception_type>
lazy_result<type> make_exceptional_lazy_result(exception_type exception) {
    struct awaitable {
        exception_type exception;
        bool await_ready() { return true; }
        void await_suspend(std::coroutine_handle<> h)
        {}
        void await_resume() 
        {
            throw exception;
        }
    };
    co_await awaitable{ exception };
}
1
ecatmur On

You already have a function (OK, a coroutine) that can produce a type, so use it:

template<class type, class exception_type>
lazy_result<type> make_exceptional_lazy_result(exception_type exception) {
    throw exception;
    co_return co_await make_exceptional_lazy_result<type>(exception);
}
0
David Haim On

I went with @Caleth solution, only simplified:

    template<class type, class exception_type>
    lazy_result<type> make_exceptional_lazy_result(exception_type exception) {
        throw exception;
        co_await std::suspend_never {};
    }