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

3156. ForwardIterator should only mean forward iterator

Section: 25.11 [specialized.algorithms] Status: Resolved Submitter: Casey Carter Opened: 2018-09-06 Last modified: 2020-05-02

Priority: 3

View other active issues in [specialized.algorithms].

View all other issues in [specialized.algorithms].

View all issues with Resolved status.

Discussion:

25.11 [specialized.algorithms] para 1.2 describes how the specialized algorithms with a template parameter named ForwardIterator impose requirements on the type passed as argument for that parameter: it must meet the Cpp17ForwardIterator requirements, which is consistent with how the rest of the Library uses the template parameter name ForwardIterator, and many of the required operations on that type must not throw exceptions, which is not consistent with how the rest of the Library uses that name.

To avoid confusion and keep the meaning of requirements imposed by template parameter names crisp, the specialized memory algorithms should use a different template parameter name for this different set of requirements.

Note that the proposed change has no normative effect; it's simply a clarification of the existing wording.

[2018-09 Reflector prioritization]

Set Priority to 3

Previous resolution [SUPERSEDED]:

This wording is relative to N4762.

  1. Modify 20.10.2 [memory.syn] as indicated:

    […]
    
    // 25.11 [specialized.algorithms], specialized algorithms
    template<class T>
      constexpr T* addressof(T& r) noexcept;
    template<class T>
      const T* addressof(const T&&) = delete;
    template<class NoThrowForwardIterator>
      void uninitialized_default_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class ExecutionPolicy, class NoThrowForwardIterator>
      void uninitialized_default_construct(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                           NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n);
    template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                                        NoThrowForwardIterator first, Size n);
    template<class NoThrowForwardIterator>
      void uninitialized_value_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class ExecutionPolicy, class NoThrowForwardIterator>
      void uninitialized_value_construct(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                         NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n);
    template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                                      NoThrowForwardIterator first, Size n);
    template<class InputIterator, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
                                         NoThrowForwardIterator result);
    template<class ExecutionPolicy, class InputIterator, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                         InputIterator first, InputIterator last,
                                         NoThrowForwardIterator result);
    template<class InputIterator, class Size, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n,
                                           NoThrowForwardIterator result);
    template<class ExecutionPolicy, class InputIterator, class Size, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                           InputIterator first, Size n,
                                           NoThrowForwardIterator result);
    template<class InputIterator, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last,
                                         NoThrowForwardIterator result);
    template<class ExecutionPolicy, class InputIterator, class NoThrowForwardIterator>
      NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                         InputIterator first, InputIterator last,
                                         NoThrowForwardIterator result);
    template<class InputIterator, class Size, class NoThrowForwardIterator>
      pair<InputIterator, NoThrowForwardIterator> uninitialized_move_n(InputIterator first, Size n,
                                                                NoThrowForwardIterator result);
    template<class ExecutionPolicy, class InputIterator, class Size, class NoThrowForwardIterator>
      pair<InputIterator, NoThrowForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                                                InputIterator first, Size n,
                                                                NoThrowForwardIterator result);
    template<class NoThrowForwardIterator, class T>
      void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x);
    template<class ExecutionPolicy, class NoThrowForwardIterator, class T>
      void uninitialized_fill(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                              NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x);
    template<class NoThrowForwardIterator, class Size, class T>
      NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x);
    template<class ExecutionPolicy, class NoThrowForwardIterator, class Size, class T>
      NoThrowForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                           NoThrowForwardIterator first, Size n, const T& x);
    template<class T>
      void destroy_at(T* location);
    template<class NoThrowForwardIterator>
      void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class ExecutionPolicy, class NoThrowForwardIterator>
      void destroy(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                   NoThrowForwardIterator first, NoThrowForwardIterator last);
    template<class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n);
    template<class ExecutionPolicy, class NoThrowForwardIterator, class Size>
      NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see 25.3.5 [algorithms.parallel.overloads]
                                NoThrowForwardIterator first, Size n);
    
    // 20.11.1 [unique.ptr], class template unique_ptr
    […]
    
  2. Modify 25.11 [specialized.algorithms] as indicated:

    […]

    (1.2) — If an algorithm's template parameter is named NoThrowForwardIterator, the template argument shall satisfy the Cpp17ForwardIterator requirements (23.3.5.4 [forward.iterators]), and is required to have the property that no exceptions are thrown from increment, assignment, comparison, or indirection through valid iterators.

    […]

  3. Modify the declarations of the specialized algorithms in the remainder of 25.11 [specialized.algorithms] to agree with the proposed changes to 20.10.2 [memory.syn] above.

[2020-05-02; Reflector discussions]

The issue has been resolved by accepting P1963R0 in Prague 2020.

Proposed resolution:

Resolved by P1963R0.