This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

3889. std::(ranges::)destroy_at should destroy array elements in the decreasing index order

Section: 26.11.9 [specialized.destroy] Status: New Submitter: Jiang An Opened: 2023-02-17 Last modified: 2023-03-22

Priority: 3

View all issues with New status.

Discussion:

Currently, std::(ranges::)destroy_at is specified to destroy array elements in the increasing index order (26.11.9 [specialized.destroy]/1.1), which is inconsistent with the decreasing order specified in the core language (11.4.7 [class.dtor]/13) and the order for arrays created by std::make_shared and std::allocate_shared (mandated by LWG 3005(i)).

Previous resolution [SUPERSEDED]:

This wording is relative to N4928.

  1. Modify 26.11.9 [specialized.destroy] as indicated:

    template<class T>
      constexpr void destroy_at(T* location);
    
    namespace ranges {
      template<destructible T>
        constexpr void destroy_at(T* location) noexcept;
    }
    

    -1- Effects:

    1. (1.1) — If T is an array type, equivalent to destroy(rbeginbegin(*location), rendend(*location)).

    2. (1.2) — Otherwise, equivalent to location->~T().

[2023-02-26; Daniel comments and provides alternative wording]

The suggested fix indeed corrects an inconsistency, but also implies a silent behaviour change at runtime, since at least MSVC STL and libstdc++ implement the array destruction order as specified (others not tested). The below wording therefore suggests to introduce a specific feature macro for this, so that user code can potentially react on this, regardless of potential vendor API breakage hesitations. The natural feature macro to increase would be that which introduced the specific array destruction behavior of destroy_at, which was P0896R4, and which introduced __cpp_lib_ranges, on the other hand the specification change affects both the std::ranges and the std forms of destroy_at, so it seems plausible to suggest a new, specific feature macro for both destroy_at function templates. This is what the proposed wording does.

LWG should clarify whether an entry to C.2 [diff.cpp20] should be added as well.

[2023-03-22; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4928.

  1. Modify 17.3.2 [version.syn], header <version> synopsis, as indicated and replace the placeholder YYYYMML by the year and month of adoption of this issue:

    […]
    #define __cpp_lib_coroutine         201902L  // also in <coroutine>
    #define __cpp_lib_destroy_at        YYYYMML  // also in <memory>
    #define __cpp_lib_destroying_delete 201806L  // also in <new>
    […]
    
  2. Modify 26.11.9 [specialized.destroy] as indicated:

    template<class T>
      constexpr void destroy_at(T* location);
    
    namespace ranges {
      template<destructible T>
        constexpr void destroy_at(T* location) noexcept;
    }
    

    -1- Effects:

    1. (1.1) — If T is an array type, equivalent to destroy(rbeginbegin(*location), rendend(*location)).

    2. (1.2) — Otherwise, equivalent to location->~T().