Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -1140,16 +1140,21 @@ namespace ranges {
// clang-format on

_NODISCARD friend constexpr _Ioterator operator+(_Ioterator _It, const difference_type _Off) noexcept(
noexcept(static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current + _Off)};
is_nothrow_move_constructible_v<_Ioterator>&& noexcept(
_It += _Off)) /* strengthened */ requires _Advanceable<_Wi> {
_It += _Off;
return _It;
}
_NODISCARD friend constexpr _Ioterator operator+(const difference_type _Off, _Ioterator _It) noexcept(
noexcept(static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> {
is_nothrow_move_constructible_v<_Wi>&& noexcept(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casey Carter (@CaseyCarter) I observe that this one says is_nothrow_move_constructible_v<_Wi> but the other two said is_nothrow_move_constructible_v<_Ioterator>. You mentioned that they're equivalent, and there seems to be a rationale (as this one constructs an _Ioterator prvalue), but I wanted to point this out in case it was unintentional and should be cleaned up later. No change requested here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other two functions return an lvalue denoting a variable with automatic storage duration, so they are implicitly moved, and that variable is a function argument, so they cannot benefit from NRVO or RVO. Consequently they move construct an _Ioterator.

This function returns a prvalue, so no _Ioterators are moved or copied - C++17 delayed temporary materialization kicks in. It does need to account for potential throws from the _Ioterator constructor from _Wi, however. That constructor is annotated with noexcept(is_nothrow_move_constructible_v<_Wi>. I'm not sure why I decided to "inline" that noexcept-specifier instead of using the more direct is_nothrow_constructible_v<_Ioterator, _Wi>. I really need to work at making my conditional noexcept style more consistent.

static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current + _Off)};
}
_NODISCARD friend constexpr _Ioterator operator-(_Ioterator _It, const difference_type _Off) noexcept(
noexcept(static_cast<_Wi>(_It._Current - _Off))) /* strengthened */ requires _Advanceable<_Wi> {
return _Ioterator{static_cast<_Wi>(_It._Current - _Off)};
is_nothrow_move_constructible_v<_Ioterator>&& noexcept(
_It -= _Off)) /* strengthened */ requires _Advanceable<_Wi> {
_It -= _Off;
return _It;
}
_NODISCARD friend constexpr difference_type
operator-(const _Ioterator& _Left, const _Ioterator& _Right) noexcept(
Expand Down