C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::async_noexcept

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 7 Nov 2023 11:52:08 +0000
On Tue, Nov 7, 2023 at 11:40 AM Frederick Virchanza Gotham wrote:
>
> Actually I might need to add a constraint here to ensure that
> "set_value" won't throw an exception. The return type will need to
> have a move/copy constructor declared as 'noexcept'.


Here it is with template constraints to make sure that the return type
is both nothrow_copy_constructible and othrow_move_constructible.

Not sure whether lambda_default_retval should be a parameter taken by
value, or taken by R-value reference.


#include <functional> // function
#include <future> // async, future, launch, promise
#include <utility> // move, forward
#include <type_traits> // decay, invoke_result,
is_nothrow_copy_constructible, is_nothrow_move_constructible
template<typename FunctorType, typename... Params>
[[nodiscard]]
std::future< std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > >
async_noexcept(
    std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > default_retval,
    std::launch policy,
    FunctorType &&f,
    Params&&... args) noexcept
requires std::is_nothrow_copy_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
      && std::is_nothrow_move_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
{
    typedef std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > R;

    // The lambda on the next line is created on the stack, however
    // there are no captures, so it's OK to invoke the lambda after
    // it has gone out of scope (i.e. from another thread).
    auto const mylambda = [](R lambda_default_retval, FunctorType
&&lambda_f, std::decay_t<Params>... lambda_args) -> R
      {
        try
        {
          return std::forward<FunctorType>(lambda_f)( lambda_args... );
        }
        catch(...)
        {
          return lambda_default_retval;
        }
      };

    try
    {
        return std::async(
          static_cast<std::launch>(policy),
          mylambda,
          default_retval,
          std::forward<FunctorType>(f),
          std::forward<Params>(args)... );
    }
    catch(...)
    {
        std::promise<R> mypromise;
        std::future<R> myfuture = mypromise.get_future();
        mypromise.set_value(default_retval); // This won't throw (see
constraints above)
        return myfuture;
    }
}

Received on 2023-11-07 11:52:20