Skip to content
Merged
Show file tree
Hide file tree
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
59 changes: 30 additions & 29 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ public:
// clang-format off
template <class _OIter, class _OSe>
requires _Not_same_as<_Variantish<_OIter, _OSe>, _Variantish>
_Variantish(const _Variantish<_OIter, _OSe>& _That) noexcept(
constexpr _Variantish(const _Variantish<_OIter, _OSe>& _That) noexcept(
is_nothrow_constructible_v<_It, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>)
: _Contains{_That._Contains} {
// clang-format on
Expand All @@ -574,11 +574,11 @@ public:
}

// clang-format off
_Variantish(const _Variantish&) requires is_trivially_copy_constructible_v<_It>
constexpr _Variantish(const _Variantish&) requires is_trivially_copy_constructible_v<_It>
&& is_trivially_copy_constructible_v<_Se> = default;
// clang-format on

_Variantish(const _Variantish& _That) noexcept(
constexpr _Variantish(const _Variantish& _That) noexcept(
is_nothrow_copy_constructible_v<_It>&& is_nothrow_copy_constructible_v<_Se>)
: _Contains{_That._Contains} {
switch (_Contains) {
Expand All @@ -594,11 +594,11 @@ public:
}
Comment thread
StephanTLavavej marked this conversation as resolved.

Comment thread
StephanTLavavej marked this conversation as resolved.
// clang-format off
_Variantish(_Variantish&&) requires is_trivially_move_constructible_v<_It>
constexpr _Variantish(_Variantish&&) requires is_trivially_move_constructible_v<_It>
&& is_trivially_move_constructible_v<_Se> = default;
// clang-format on

_Variantish(_Variantish&& _That) noexcept(
constexpr _Variantish(_Variantish&& _That) noexcept(
is_nothrow_move_constructible_v<_It>&& is_nothrow_move_constructible_v<_Se>)
: _Contains{_That._Contains} {
switch (_Contains) {
Expand All @@ -614,23 +614,23 @@ public:
}

// clang-format off
~_Variantish() requires is_trivially_destructible_v<_It> && is_trivially_destructible_v<_Se> = default;
constexpr ~_Variantish() requires is_trivially_destructible_v<_It> && is_trivially_destructible_v<_Se> = default;
// clang-format on

~_Variantish() {
constexpr ~_Variantish() {
_Raw_clear();
}

// clang-format off
_Variantish& operator=(const _Variantish&) requires is_trivially_destructible_v<_It>
constexpr _Variantish& operator=(const _Variantish&) requires is_trivially_destructible_v<_It>
&& is_trivially_destructible_v<_Se>
&& is_trivially_copy_constructible_v<_It>
&& is_trivially_copy_constructible_v<_Se>
&& is_trivially_copy_assignable_v<_It>
&& is_trivially_copy_assignable_v<_Se> = default;
// clang-format on

_Variantish& operator=(const _Variantish& _That) noexcept(
constexpr _Variantish& operator=(const _Variantish& _That) noexcept(
is_nothrow_copy_constructible_v<_It>&& is_nothrow_copy_constructible_v<_Se>&&
is_nothrow_copy_assignable_v<_It>&& is_nothrow_copy_assignable_v<_Se>) {
if (_Contains == _That._Contains) {
Expand Down Expand Up @@ -667,15 +667,15 @@ public:
}

// clang-format off
_Variantish& operator=(_Variantish&&) requires is_trivially_destructible_v<_It>
constexpr _Variantish& operator=(_Variantish&&) requires is_trivially_destructible_v<_It>
&& is_trivially_destructible_v<_Se>
&& is_trivially_move_constructible_v<_It>
&& is_trivially_move_constructible_v<_Se>
&& is_trivially_move_assignable_v<_It>
&& is_trivially_move_assignable_v<_Se> = default;
// clang-format on

_Variantish& operator=(_Variantish&& _That) noexcept(
constexpr _Variantish& operator=(_Variantish&& _That) noexcept(
is_nothrow_move_constructible_v<_It>&& is_nothrow_move_constructible_v<_Se>&&
is_nothrow_move_assignable_v<_It>&& is_nothrow_move_assignable_v<_Se>) {
if (_Contains == _That._Contains) {
Expand Down Expand Up @@ -714,7 +714,7 @@ public:
// clang-format off
template <class _OIter, class _OSe>
requires _Not_same_as<_Variantish<_OIter, _OSe>, _Variantish>
_Variantish& operator=(const _Variantish<_OIter, _OSe>& _That) noexcept(
constexpr _Variantish& operator=(const _Variantish<_OIter, _OSe>& _That) noexcept(
is_nothrow_constructible_v<_It, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>
&& is_nothrow_assignable_v<_It&, const _OIter&> && is_nothrow_assignable_v<_Se&, const _OSe&>) {
// clang-format on
Expand Down Expand Up @@ -777,7 +777,7 @@ public:
_Right = _STD move(_Tmp);
}

void _Raw_clear() noexcept {
constexpr void _Raw_clear() noexcept {
switch (_Contains) {
case _Variantish_state::_Holds_iter:
_Iterator.~_It();
Expand All @@ -790,7 +790,7 @@ public:
}
}

void _Clear() noexcept {
constexpr void _Clear() noexcept {
_Raw_clear();
_Contains = _Variantish_state::_Nothing;
}
Expand Down Expand Up @@ -818,7 +818,7 @@ private:
struct _Proxy_base {
iter_value_t<_Iter> _Keep;

explicit _Proxy_base(iter_reference_t<_Iter>&& _Right) noexcept(
constexpr explicit _Proxy_base(iter_reference_t<_Iter>&& _Right) noexcept(
is_nothrow_constructible_v<iter_value_t<_Iter>, iter_reference_t<_Iter>>) // strengthened
: _Keep(_STD forward<iter_reference_t<_Iter>>(_Right)) {}
};
Expand Down Expand Up @@ -846,7 +846,7 @@ public:
template <class _OIter, class _OSe>
requires convertible_to<const _OIter&, _Iter> && convertible_to<const _OSe&, _Se>
&& assignable_from<_Iter&, const _OIter&> && assignable_from<_Se&, const _OSe&>
common_iterator& operator=(const common_iterator<_OIter, _OSe>& _Right) noexcept(
constexpr common_iterator& operator=(const common_iterator<_OIter, _OSe>& _Right) noexcept(
is_nothrow_constructible_v<_Iter, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>
&& is_nothrow_assignable_v<_Iter&, const _OIter&>
&& is_nothrow_assignable_v<_Se&, const _OSe&>) /* strengthened */ {
Expand All @@ -855,15 +855,15 @@ public:
return *this;
}

_NODISCARD decltype(auto) operator*() {
_NODISCARD constexpr decltype(auto) operator*() {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_iter,
"common_iterator can only be dereferenced if it holds an iterator");
#endif // _ITERATOR_DEBUG_LEVEL != 0
return *_Val._Iterator;
}

_NODISCARD decltype(auto) operator*() const requires _Dereferenceable<const _Iter> {
_NODISCARD constexpr decltype(auto) operator*() const requires _Dereferenceable<const _Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_iter,
"common_iterator can only be dereferenced if it holds an iterator");
Expand All @@ -872,7 +872,7 @@ public:
}

// clang-format off
_NODISCARD decltype(auto) operator->() const
_NODISCARD constexpr decltype(auto) operator->() const
requires indirectly_readable<const _Iter>
&& (_Has_member_arrow<const _Iter&> || is_reference_v<iter_reference_t<_Iter>>
|| constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>>) {
Expand All @@ -893,7 +893,7 @@ public:

using _Proxy_base::_Proxy_base;

_NODISCARD const iter_value_t<_Iter>* operator->() const noexcept /* strengthened */ {
_NODISCARD constexpr const iter_value_t<_Iter>* operator->() const noexcept {
return _STD addressof(this->_Keep);
}
};
Expand All @@ -902,7 +902,7 @@ public:
}
}

common_iterator& operator++() {
constexpr common_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_iter,
"common_iterator can only be incremented if it holds an iterator");
Expand All @@ -911,7 +911,7 @@ public:
return *this;
}

decltype(auto) operator++(int) {
constexpr decltype(auto) operator++(int) {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_iter,
"common_iterator can only be incremented if it holds an iterator");
Expand All @@ -927,7 +927,7 @@ public:

using _Proxy_base::_Proxy_base;

_NODISCARD const iter_value_t<_Iter>& operator*() const noexcept /* strengthened */ {
_NODISCARD constexpr const iter_value_t<_Iter>& operator*() const noexcept {
return this->_Keep;
}
};
Expand All @@ -943,7 +943,8 @@ public:
// clang-format off
template <class _OIter, sentinel_for<_Iter> _OSe>
requires sentinel_for<_Se, _OIter>
_NODISCARD friend bool operator==(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
_NODISCARD friend constexpr
bool operator==(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
// clang-format on
auto& _Right_val = _Right._Get_val();
#if _ITERATOR_DEBUG_LEVEL != 0
Expand Down Expand Up @@ -974,7 +975,7 @@ public:
// clang-format off
template <sized_sentinel_for<_Iter> _OIter, sized_sentinel_for<_Iter> _OSe>
requires sized_sentinel_for<_Se, _OIter>
_NODISCARD friend iter_difference_t<_OIter> operator-(
_NODISCARD friend constexpr iter_difference_t<_OIter> operator-(
const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
// clang-format on
auto& _Right_val = _Right._Get_val();
Expand All @@ -999,7 +1000,7 @@ public:
}
}

_NODISCARD friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& _Right) noexcept(
_NODISCARD friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& _Right) noexcept(
noexcept(_RANGES iter_move(_Right._Val._Iterator))) requires input_iterator<_Iter> {
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Right._Val._Contains == _Variantish_state::_Holds_iter,
Expand All @@ -1009,7 +1010,7 @@ public:
}

template <indirectly_swappable<_Iter> _OIter, class _OSe>
friend void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) noexcept(
friend constexpr void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) noexcept(
noexcept(_RANGES iter_swap(_Left._Val._Iterator, _Right._Get_val()._Iterator))) {
auto& _Right_val = _Right._Get_val();
#if _ITERATOR_DEBUG_LEVEL != 0
Expand All @@ -1020,10 +1021,10 @@ public:
return _RANGES iter_swap(_Left._Val._Iterator, _Right_val._Iterator);
}

_NODISCARD _Variantish<_Iter, _Se>& _Get_val() noexcept {
_NODISCARD constexpr _Variantish<_Iter, _Se>& _Get_val() noexcept {
return _Val;
}
_NODISCARD const _Variantish<_Iter, _Se>& _Get_val() const noexcept {
_NODISCARD constexpr const _Variantish<_Iter, _Se>& _Get_val() const noexcept {
return _Val;
}

Expand Down
4 changes: 3 additions & 1 deletion tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ struct with_output_iterators {
template <class Continuation, class Element>
struct with_writable_iterators {
template <class... Args>
static constexpr void call() {
static constexpr bool call() {
using namespace test;
using test::iterator;

Expand All @@ -902,6 +902,8 @@ struct with_writable_iterators {
iterator<input, Element, CanDifference::no, CanCompare::no, ProxyRef::yes>>();

with_output_iterators<Continuation, Element>::template call<Args...>();

return true;
}
};

Expand Down
60 changes: 58 additions & 2 deletions tests/std/tests/P0896R4_common_iterator/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ struct instantiator {
}
};

bool test_operator_arrow() {
constexpr bool test_operator_arrow() {
P input[3] = {{0, 1}, {0, 2}, {0, 3}};

using pointerTest = common_iterator<P*, void*>;
Expand Down Expand Up @@ -226,6 +226,10 @@ using ICID = iterator_traits<common_iterator<input_copy_but_no_eq, default_senti
STATIC_ASSERT(same_as<typename ICID::iterator_category, input_iterator_tag>);

struct poor_sentinel {
poor_sentinel() = default;
constexpr poor_sentinel(const poor_sentinel&) {} // non-trivial copy constructor, to test _Variantish behavior
poor_sentinel& operator=(const poor_sentinel&) = default;

template <weakly_incrementable Winc>
[[nodiscard]] constexpr bool operator==(const Winc&) const noexcept {
return true;
Expand All @@ -242,7 +246,7 @@ struct poor_sentinel {
}
};

void test_gh_2065() { // Guard against regression of GH-2065, for which we previously stumbled over CWG-1699.
constexpr bool test_gh_2065() { // Guard against regression of GH-2065, for which we previously stumbled over CWG-1699.
{
int x = 42;
common_iterator<int*, unreachable_sentinel_t> it1{&x};
Expand All @@ -256,12 +260,64 @@ void test_gh_2065() { // Guard against regression of GH-2065, for which we previ
common_iterator<const int*, poor_sentinel> it2{&i};
assert(it1 - it2 == 0);
}

return true;
}

constexpr bool test_lwg_3574() {
int arr[]{11, 22, 33};

{
common_iterator<int*, const int*> x{arr};
common_iterator<int*, const int*> y{arr + 2};
assert(y - x == 2);
}

{ // test that copy construction is constexpr, even when the sentinel isn't trivially copy constructible
common_iterator<int*, poor_sentinel> a{arr};
common_iterator<int*, poor_sentinel> b{a}; // copy-construct with a stored iterator
common_iterator<int*, poor_sentinel> x{poor_sentinel{}};
common_iterator<int*, poor_sentinel> y{x}; // copy-construct with a stored sentinel
assert(b - a == 0);
}

common_iterator<int*, unreachable_sentinel_t> i{arr};
common_iterator<const int*, unreachable_sentinel_t> ci{arr + 1};

assert(*ci == 22);
assert(*as_const(ci) == 22);
assert(ci.operator->() == arr + 1);

ci = i;
assert(*ci == 11);
assert(ci == i);

assert(*++ci == 22);
assert(ci != i);

assert(*ci++ == 22);
assert(*ci == 33);

assert(iter_move(i) == 11);

common_iterator<int*, unreachable_sentinel_t> k{arr + 2};
iter_swap(i, k);
assert(arr[0] == 33);
assert(arr[2] == 11);

return true;
}

int main() {
with_writable_iterators<instantiator, P>::call();
static_assert(with_writable_iterators<instantiator, P>::call());

test_operator_arrow();
static_assert(test_operator_arrow());

test_gh_2065();
static_assert(test_gh_2065());

test_lwg_3574();
static_assert(test_lwg_3574());
}
2 changes: 1 addition & 1 deletion tests/std/tests/P0896R4_counted_iterator/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ void test_P2259() {
}

int main() {
STATIC_ASSERT((with_writable_iterators<instantiator, int>::call(), true));
STATIC_ASSERT(with_writable_iterators<instantiator, int>::call());
with_writable_iterators<instantiator, int>::call();

{ // Validate unwrapping
Expand Down
2 changes: 1 addition & 1 deletion tests/std/tests/P0896R4_views_counted/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ struct instantiator {
};

int main() {
STATIC_ASSERT((with_writable_iterators<instantiator, int>::call(), true));
STATIC_ASSERT(with_writable_iterators<instantiator, int>::call());
with_writable_iterators<instantiator, int>::call();
}