3764. reference_wrapper::operator() should propagate noexcept

Section: 22.10.6.5 [refwrap.invoke] Status: C++23 Submitter: Zhihao Yuan Opened: 2022-08-31 Last modified: 2023-11-22

Priority: Not Prioritized

View all other issues in [refwrap.invoke].

View all issues with C++23 status.

Discussion:

The following assertion does not hold, making the type less capable than the function pointers.

void f() noexcept;

std::reference_wrapper fn = f;
static_assert(std::is_nothrow_invocable_v<decltype(fn)>);

[2022-09-23; Reflector poll]

Set status to Tentatively Ready after six votes in favour during reflector poll.

Already implemented in MSVC and libstdc++.

[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4910.

  1. Modify 22.10.6.1 [refwrap.general], class template reference_wrapper synopsis, as indicated:

    // 22.10.6.5 [refwrap.invoke], invocation
    template<class... ArgTypes>
      constexpr invoke_result_t<T&, ArgTypes...> operator()(ArgTypes&&...) const 
        noexcept(is_nothrow_invocable_v<T&, ArgTypes...>);
    
  2. Modify 22.10.6.5 [refwrap.invoke] as indicated:

    template<class... ArgTypes>
      constexpr invoke_result_t<T&, ArgTypes...>
        operator()(ArgTypes&&... args) const noexcept(is_nothrow_invocable_v<T&, ArgTypes...>);
    

    -1- Mandates: T is a complete type.

    -2- Returns: INVOKE(get(), std::forward<ArgTypes>(args)...). (22.10.4 [func.require])