Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++23 status.

3460. Unimplementablenoop_coroutine_handle guarantees

Section: 17.13.5.2.4[coroutine.handle.noop.resumption]Status:C++23Submitter: Casey CarterOpened: 2020-07-01Last modified: 2023-11-22

Priority:2

View all issues withC++23 status.

Discussion:

17.13.5.2.4[coroutine.handle.noop.resumption]/2 states "Remarks: Ifnoop_coroutine_handle is converted tocoroutine_handle<>, calls tooperator(),resume anddestroy on that handle will also have no observable effects." This suggests that e.g. in this function:

void f(coroutine_handle<> meow) {  auto woof = noop_coroutine();  static_cast<coroutine_handle<>&>(woof) = meow;  static_cast<coroutine_handle<>&>(woof).resume();}

the final call tocoroutine_handle<>::resume must have no effect regardless of what coroutine (if any)meow refers to, contradicting the specification ofcoroutine_handle<>::resume. Even absent this contradiction, implementing the specification requirescoroutine_handle<>::resume to determine if*this is a base subobject of anoop_coroutine_handle, which seems pointlessly expensive to implement.

17.13.5.2.6[coroutine.handle.noop.address]/2 states "Remarks: Anoop_coroutine_handle'sptr is always a non-null pointer value." Similar to the above case, a slicing assignment of a default-initializedcoroutine_handle<> to anoop_coroutine_handle must result inptr having a null pointer value — another contradiction between the requirements ofnoop_coroutine_handle andcoroutine_handle<>.

[2020-07-12; Reflector prioritization]

Set priority to 2 after reflector discussions.

[2020-07-29 Tim adds PR and comments]

The root cause for this issue as well as issue3469(i) is the unnecessary public derivation fromcoroutine_handle<void>. The proposed resolution belowreplaces the derivation with a conversion function and adds explicit declarations formembers that were previously inherited. It also modifies the preconditionsonfrom_address with goal of making it impossible to obtain acoroutine_handle<P>to a coroutine whose promise type is notP in well-defined code.

[2020-08-21; Issue processing telecon: moved to Tentatively Ready]

[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative toN4861 and also resolvesLWG issue3469(i).

  1. Edit 17.13.4[coroutine.handle] as indicated:

    namespace std {  […]  template<class Promise>  struct coroutine_handle: coroutine_handle<>  {    // [coroutine.handle.con], construct/reset    using coroutine_handle<>::coroutine_handle;    constexpr coroutine_handle() noexcept;    constexpr coroutine_handle(nullptr_t) noexcept;    static coroutine_handle from_promise(Promise&);    coroutine_handle& operator=(nullptr_t) noexcept;      // [coroutine.handle.export.import], export/import    constexpr void* address() const noexcept;    static constexpr coroutine_handle from_address(void* addr);    // [coroutine.handle.conv], conversion    constexpr operator coroutine_handle<>() const noexcept;      // [coroutine.handle.observers], observers    constexpr explicit operator bool() const noexcept;    bool done() const;      // [coroutine.handle.resumption], resumption    void operator()() const;    void resume() const;    void destroy() const;      // [coroutine.handle.promise], promise access    Promise& promise() const;  private:    void* ptr;  //exposition only  };}

    -1- An object of typecoroutine_­handle<T> is called acoroutine handleand can be used to refer to a suspended or executing coroutine.Adefault-constructedcoroutine_­handle objectwhose memberaddress()returns a null pointer value does not refer to any coroutine.Twocoroutine_handle objects refer to the same coroutine if and only if theirmemberaddress() returns the same value.

  2. Add the following subclause under 17.13.4[coroutine.handle], immediately after 17.13.4.2[coroutine.handle.con]:

    ?.?.?.? Conversion [coroutine.handle.conv]

    constexpr operator coroutine_handle<>() const noexcept;

    -1-Effects: Equivalent to:return coroutine_handle<>::from_address(address());.

  3. Edit 17.13.4.4[coroutine.handle.export.import] as indicated, splitting the two versions:

    static constexpr coroutine_handle<> coroutine_handle<>::from_address(void* addr);

    -?-Preconditions:addr was obtained via a prior call toaddress onan object whose type is a specialization ofcoroutine_handle.

    -?-Postconditions:from_­address(address()) == *this.

    static constexpr coroutine_handle<Promise> coroutine_handle<Promise>::from_address(void* addr);

    -2-Preconditions:addr was obtained via a prior call toaddresson an object of typecvcoroutine_handle<Promise>.

    -3-Postconditions:from_­address(address()) == *this.

  4. Edit 17.13.5.2[coroutine.handle.noop] as indicated:

    namespace std {  template<>  struct coroutine_handle<noop_coroutine_promise>: coroutine_handle<>  {    // [coroutine.handle.noop.conv], conversion    constexpr operator coroutine_handle<>() const noexcept;    // [coroutine.handle.noop.observers], observers    constexpr explicit operator bool() const noexcept;    constexpr bool done() const noexcept;    // [coroutine.handle.noop.resumption], resumption    constexpr void operator()() const noexcept;    constexpr void resume() const noexcept;    constexpr void destroy() const noexcept;    // [coroutine.handle.noop.promise], promise access    noop_coroutine_promise& promise() const noexcept;    // [coroutine.handle.noop.address], address    constexpr void* address() const noexcept;    private:    coroutine_handle(unspecified);    void* ptr; //exposition only  };}
  5. Add the following subclause under 17.13.5.2[coroutine.handle.noop], immediately before 17.13.5.2.3[coroutine.handle.noop.observers]:

    ?.?.?.?.? Conversion [coroutine.handle.noop.conv]

    constexpr operator coroutine_handle<>() const noexcept;

    -1-Effects: Equivalent to:return coroutine_handle<>::from_address(address());.


[8]ページ先頭

©2009-2025 Movatter.jp