C++ Standard Library Issues to be moved in [INSERT CURRENT MEETING HERE]

Doc. no. R0165???
Date:

Revised 2022-03-04 at 14:55:46 UTC

Project: Programming Language C++
Reply to: Jonathan Wakely <lwgchair@gmail.com>

Ready Issues


3649(i). [fund.ts.v3] Reinstate and bump __cpp_lib_experimental_memory_resource feature test macro

Section: 1.5 [fund.ts.v3::general.feature.test] Status: Tentatively Ready Submitter: Thomas Köppe Opened: 2021-12-03 Last modified: 2022-02-11

Priority: Not Prioritized

View all issues with Tentatively Ready status.

Discussion:

Addresses: fund.ts.v3

The rebase on C++17 in P0996 had the effect of deleting the feature test macro __cpp_lib_experimental_memory_resource: the macro was ostensibly tied to the memory_resource facility that had become part of C++17, but we overlooked that there was a residual piece that has not been adopted in the IS, namely the resource_adaptor class template.

It is still useful to be able to detect the presence of resource_adaptor, so we should reinstate the feature test macro and bump its value.

[2022-01-30; Reflector poll]

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

Proposed resolution:

This wording is relative to N4853.

  1. Modify 1.5 [fund.ts.v3::general.feature.test], Table 2, as indicated:

    Table 2 — Significant features in this technical specification
    Doc. No. Title Primary
    Section
    Macro Name Suffix Value Header
    N3916 Type-erased allocator for std::function 4.2 function_erased_allocator 201406 <experimental/functional>
    N3916 Polymorphic Memory Resources 5.4 [fund.ts.v3::memory.resource.syn] memory_resources [new value] <experimental/memory_resource>
    N4282 The World's Dumbest Smart Pointer 8.12 observer_ptr 201411 <experimental/memory>

3670(i). Cpp17InputIterators don't have integer-class difference types

Section: 24.6.4.3 [range.iota.iterator] Status: Tentatively Ready Submitter: Casey Carter Opened: 2022-02-04 Last modified: 2022-02-09

Priority: Not Prioritized

View all other issues in [range.iota.iterator].

View all issues with Tentatively Ready status.

Discussion:

24.6.4.3 [range.iota.iterator] defines

using iterator_category = input_iterator_tag; // present only if W models incrementable

but when difference_type is an integer-class type the iterator does not meet the Cpp17InputIterator requirements.

[2022-02-07; Daniel comments]

As requested by LWG 3376 and wording implemented by P2393R1, integer-class types are no longer required to have class type.

Previous resolution [SUPERSEDED]:

This wording is relative to N4901.

  1. Modify 24.6.4.3 [range.iota.iterator], class iota_view::iterator synopsis, as indicated:

    namespace std::ranges {
      template<weakly_incrementable W, semiregular Bound>
        requires weakly-equality-comparable-with<W, Bound> && copyable<W>
      struct iota_view<W, Bound>::iterator {
        […]
        using iterator_category = input_iterator_tag; // present only if W models incrementable and 
                                                      // IOTA-DIFF-T(W) is not a class type
        using value_type = W;
        using difference_type = IOTA-DIFF-T(W);
        […]
      };
    }
    

[2022-02-07; Casey Carter provides improved wording]

[2022-03-04; Reflector poll]

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

Proposed resolution:

This wording is relative to N4901.

  1. Modify 24.6.4.3 [range.iota.iterator], class iota_view::iterator synopsis, as indicated:

    namespace std::ranges {
      template<weakly_incrementable W, semiregular Bound>
        requires weakly-equality-comparable-with<W, Bound> && copyable<W>
      struct iota_view<W, Bound>::iterator {
        […]
        using iterator_category = input_iterator_tag; // present only if W models incrementable and 
                                                      // IOTA-DIFF-T(W) is an integral type
        using value_type = W;
        using difference_type = IOTA-DIFF-T(W);
        […]
      };
    }
    

3671(i). atomic_fetch_xor missing from stdatomic.h

Section: 31.12 [stdatomic.h.syn] Status: Tentatively Ready Submitter: Hubert Tong Opened: 2022-02-09 Last modified: 2022-02-10

Priority: Not Prioritized

View all issues with Tentatively Ready status.

Discussion:

C17 subclause 7.17.7.5 provides atomic_fetch_xor and atomic_fetch_xor_explicit. stdatomic.h in the working draft (N4901) does not.

[2022-02-09; Jonathan comments and provides wording]

C++20 31.2 [atomics.syn] has both of them, too, so it should definitely be in the common subset.

[2022-03-04; Reflector poll]

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

Proposed resolution:

This wording is relative to N4901.

  1. Modify 31.12 [stdatomic.h.syn], header <stdatomic.h> synopsis, as indicated:

    [Drafting Note: The editor is kindly requested to reorder these "atomic_fetch_KEY" declarations to match the other synopses in Clause 31 [atomics]: add, sub, and, or, xor.]

    […]
    using std::atomic_fetch_or;                    // see below
    using std::atomic_fetch_or_explicit;           // see below
    using std::atomic_fetch_xor;                   // see below
    using std::atomic_fetch_xor_explicit;          // see below
    using std::atomic_fetch_and;                   // see below
    using std::atomic_fetch_and_explicit;          // see below
    […]
    

3672(i). common_iterator::operator->() should return by value

Section: 23.5.4.4 [common.iter.access] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2022-02-12 Last modified: 2022-03-04

Priority: Not Prioritized

View all other issues in [common.iter.access].

View all issues with Tentatively Ready status.

Discussion:

23.5.4.4 [common.iter.access] p5 (5.1) says that common_iterator<T*, S>::operator->() returns std::get<T*>(v_) which has type T* const&. That means that iterator_traits::pointer is T* const& as well (this was recently clarified by LWG 3660). We have an actual pointer here, why are we returning it by reference?

For the three bullet points in 23.5.4.4 [common.iter.access] p5, the second and third return by value anyway, so decltype(auto) is equivalent to auto. For the first bullet, it would make a lot more sense for raw pointers to be returned by value. That leaves the case where the iterator has an operator->() member, which could potentially benefit from returning by reference. But it must return something that is iterator-like or pointer-like, which we usually just pass by value. Casey suggested we should just change common_iterator<I, S>::operator->() to return by value in all cases.

Libstdc++ has always returned by value, as an unintended consequence of using a union instead of std::variant<I, S>, so that it doesn't use std::get<I> to return the member.

[2022-03-04; Reflector poll]

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

Proposed resolution:

This wording is relative to N4901.

  1. Modify 23.5.4.1 [common.iterator], class template common_iterator synopsis, as indicated:

    […]
    constexpr decltype(auto) operator*();
    constexpr decltype(auto) operator*() const
      requires dereferenceable<const I>;
    constexpr decltype(auto) operator->() const
      requires see below;
    […]
    
  2. Modify 23.5.4.4 [common.iter.access] as indicated:

    constexpr decltype(auto) operator->() const
      requires see below;
    

    -3- The expression in the requires-clause is equivalent to: […]

    -4- Preconditions: holds_alternative<I>(v_) is true.

    -5- Effects:

    1. (5.1) — If I is a pointer type or if the expression get<I>(v_).operator->() is well-formed, equivalent to: return get<I>(v_);

    2. (5.2) — Otherwise, if iter_reference_t<I> is a reference type, equivalent to:

      auto&& tmp = *get<I>  (v_);
      return addressof(tmp);
      
    3. (5.3) — Otherwise, equivalent to: return proxy(*get<I>(v_)); where proxy is the exposition-only class:

      class proxy {
        iter_value_t<I> keep_;
        constexpr proxy(iter_reference_t<I>&& x)
          : keep_(std::move(x)) {}
      public:
        constexpr const iter_value_t<I>* operator->() const noexcept {
          return addressof(keep_);
        }
      };