Movatterモバイル変換


[0]ホーム

URL:



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

3918.std::uninitialized_move/_n and guaranteed copy elision

Section: 26.11.6[uninitialized.move]Status:WPSubmitter: Jiang AnOpened: 2023-04-04Last modified: 2024-11-28

Priority:3

View all issues withWP status.

Discussion:

Currentlystd::move is unconditionally used instd::uninitialized_move andstd::uninitialized_move_n, which may involve unnecessary move construction if dereferencing the input iterator yields a prvalue.

The status quo was mentioned inpaper issue #975, but no further process is done since then.

[2023-06-01; Reflector poll]

Set priority to 3 after reflector poll. Send to LEWG.

"P2283 wants to remove guaranteed elision here.""Poorly motivated, not clear anybody is using these algos with proxy iterators.""Consider usingiter_move in the move algos."

Previous resolution [SUPERSEDED]:

This wording is relative toN4944.

  1. Modify 26.11.1[specialized.algorithms.general] as indicated:

    -3- Some algorithms specified in 26.11[specialized.algorithms] make use of thefollowing exposition-only functionsvoidify:

    template<class T>  constexpr void*voidify(T& obj) noexcept {    return addressof(obj);  }template<class I>  decltype(auto)deref-move(const I& it) {    if constexpr (is_lvalue_reference_v<decltype(*it)>)      return std::move(*it);    else      return *it;  }
  2. Modify 26.11.6[uninitialized.move] as indicated:

    template<class InputIterator, class NoThrowForwardIterator>  NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last,                                            NoThrowForwardIterator result);

    -1-Preconditions:result + [0, (last - first)) does not overlap with[first, last).

    -2-Effects: Equivalent to:

    for (; first != last; (void)++result, ++first)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return result;
    […]
    template<class InputIterator, class Size, class NoThrowForwardIterator>  pair<InputIterator, NoThrowForwardIterator>    uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);

    -6-Preconditions:result + [0, n) does not overlap withfirst + [0, n).

    -7-Effects: Equivalent to:

    for (; n > 0; ++result,(void) ++first, --n)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return {first, result};

[2024-03-22; Tokyo: Jonathan updates wording after LEWG review]

LEWG agrees it would be good to do this.Usingiter_move was discussed, but it was noted that the versions of thesealgos in theranges namespace already use it and introducingranges::iter_move into the non-ranges versions wasn't desirable.It was observed that the proposedderef-move has aconst I& parameter which would be ill-formed for any iteratorwith a non-constoperator* member. Suggested removing the const andrecommended LWG to accept the proposed resolution.

Previous resolution [SUPERSEDED]:

This wording is relative toN4971.

  1. Modify 26.11.1[specialized.algorithms.general] as indicated:

    -3- Some algorithms specified in 26.11[specialized.algorithms] make use of thefollowing exposition-only functionsvoidify:

    template<class T>  constexpr void*voidify(T& obj) noexcept {    return addressof(obj);  }template<class I>  decltype(auto)deref-move(I& it) {    if constexpr (is_lvalue_reference_v<decltype(*it)>)      return std::move(*it);    else      return *it;  }
  2. Modify 26.11.6[uninitialized.move] as indicated:

    template<class InputIterator, class NoThrowForwardIterator>  NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last,                                            NoThrowForwardIterator result);

    -1-Preconditions:result + [0, (last - first)) does not overlap with[first, last).

    -2-Effects: Equivalent to:

    for (; first != last; (void)++result, ++first)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return result;
    […]
    template<class InputIterator, class Size, class NoThrowForwardIterator>  pair<InputIterator, NoThrowForwardIterator>    uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);

    -6-Preconditions:result + [0, n) does not overlap withfirst + [0, n).

    -7-Effects: Equivalent to:

    for (; n > 0; ++result,(void) ++first, --n)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return {first, result};

[St. Louis 2024-06-24; revert P/R and move to Ready]

Tim observed that the iterator requirements require all iterators to beconst-dereferenceable, so there was no reason to remove the const.Restore the original resolution and move to Ready.

[Wrocław 2024-11-23; Status changed: Voting → WP.]

Proposed resolution:

This wording is relative toN4971.

  1. Modify 26.11.1[specialized.algorithms.general] as indicated:

    -3- Some algorithms specified in 26.11[specialized.algorithms] make use of thefollowing exposition-only functionsvoidify:

    template<class T>  constexpr void*voidify(T& obj) noexcept {    return addressof(obj);  }template<class I>  decltype(auto)deref-move(I& it) {    if constexpr (is_lvalue_reference_v<decltype(*it)>)      return std::move(*it);    else      return *it;  }
  2. Modify 26.11.6[uninitialized.move] as indicated:

    template<class InputIterator, class NoThrowForwardIterator>  NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last,                                            NoThrowForwardIterator result);

    -1-Preconditions:result + [0, (last - first)) does not overlap with[first, last).

    -2-Effects: Equivalent to:

    for (; first != last; (void)++result, ++first)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return result;
    […]
    template<class InputIterator, class Size, class NoThrowForwardIterator>  pair<InputIterator, NoThrowForwardIterator>    uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);

    -6-Preconditions:result + [0, n) does not overlap withfirst + [0, n).

    -7-Effects: Equivalent to:

    for (; n > 0; ++result,(void) ++first, --n)  ::new (voidify(*result))    typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*deref-move(first));return {first, result};

[8]ページ先頭

©2009-2026 Movatter.jp