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
505 changes: 505 additions & 0 deletions stl/inc/iterator

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,6 @@ void _Deallocate(void* _Ptr, size_t _Bytes) noexcept {

#undef _HAS_ALIGNED_NEW

// FUNCTION TEMPLATE _Construct_in_place
template <class _Ty, class... _Types>
void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) {
::new (const_cast<void*>(static_cast<const volatile void*>(_STD addressof(_Obj))))
_Ty(_STD forward<_Types>(_Args)...);
}

// FUNCTION TEMPLATE _Global_new
template <class _Ty, class... _Types>
_Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection
Expand Down
15 changes: 11 additions & 4 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ struct _Get_rebind_alias<_Ty, _Other, void_t<typename _Ty::template rebind<_Othe
using type = typename _Ty::template rebind<_Other>;
};

// FUNCTION TEMPLATE _Construct_in_place
template <class _Ty, class... _Types>
void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) {
::new (const_cast<void*>(static_cast<const volatile void*>(_STD addressof(_Obj))))
_Ty(_STD forward<_Types>(_Args)...);
}

// STRUCT TEMPLATE pointer_traits
template <class _Ty>
struct pointer_traits {
Expand Down Expand Up @@ -2329,6 +2336,10 @@ _NODISCARD _Ty _Fake_decay_copy(_Ty) noexcept;
// (2) is well-formed if and only if E is implicitly convertible to T and T is destructible, and
// (3) is non-throwing if and only if both conversion from decltype((E)) to T and destruction of T are non-throwing.

// CONCEPT _Not_same_as
template <class _Ty1, class _Ty2>
concept _Not_same_as = !same_as<remove_cvref_t<_Ty1>, remove_cvref_t<_Ty2>>;

namespace ranges {
// VARIABLE TEMPLATE _Has_complete_elements
template <class>
Expand Down Expand Up @@ -3426,10 +3437,6 @@ namespace ranges {
using is_transparent = int;
};

// CONCEPT _Not_same_as
template <class _Ty1, class _Ty2>
concept _Not_same_as = !same_as<remove_cvref_t<_Ty1>, remove_cvref_t<_Ty2>>;

// CONCEPT ranges::common_range
// clang-format off
template <class _Rng>
Expand Down
11 changes: 10 additions & 1 deletion tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,16 @@ namespace test {

using _Prevent_inheriting_unwrap = sentinel;

using unwrap = sentinel<Element, IsWrapped::no>;
using unwrap = sentinel<Element, IsWrapped::no>;
using Constinel = sentinel<const Element, Wrapped>;

constexpr operator Constinel() && noexcept {
return Constinel{exchange(ptr_, nullptr)};
}

constexpr operator Constinel() const& noexcept {
return Constinel{ptr_};
}

// clang-format off
[[nodiscard]] constexpr auto _Unwrapped() const noexcept requires (to_bool(Wrapped)) {
Expand Down
2 changes: 2 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ tests\P0768R1_spaceship_operator
tests\P0769R2_shift_left_shift_right
tests\P0784R7_library_support_for_more_constexpr_containers
tests\P0811R3_midpoint_lerp
tests\P0896R4_common_iterator
tests\P0896R4_common_iterator_death
tests\P0896R4_counted_iterator
tests\P0896R4_counted_iterator_death
tests\P0896R4_P1614R2_comparisons
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_common_iterator/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_concepts_matrix.lst
201 changes: 201 additions & 0 deletions tests/std/tests/P0896R4_common_iterator/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cassert>
#include <concepts>
#include <iterator>
#include <type_traits>
#include <utility>

#include <range_algorithm_support.hpp>
using namespace std;
using P = pair<int, int>;

// clang-format off
template <class Iter>
concept CanDifference = requires(Iter it) {
{ it - it };
};

template <class Iter>
concept HasProxy = !is_reference_v<iter_reference_t<Iter>>;
// clang-format on

struct instantiator {
template <input_or_output_iterator Iter>
static constexpr void call() {
if constexpr (copyable<Iter>) {
using ConstIter = typename Iter::Consterator;
using Sen = test::sentinel<iter_value_t<Iter>>;
using OSen = test::sentinel<const iter_value_t<Iter>>;
using Cit = common_iterator<Iter, Sen>;
using OCit = common_iterator<ConstIter, OSen>;
P input[3] = {{0, 1}, {0, 2}, {0, 3}};

// [common.iter.types]
{
using iconcept = typename iterator_traits<Cit>::iterator_concept;
if constexpr (forward_iterator<Iter>) {
STATIC_ASSERT(same_as<iconcept, forward_iterator_tag>);
} else {
STATIC_ASSERT(same_as<typename iterator_traits<Cit>::iterator_concept, input_iterator_tag>);
}

using icat = typename iterator_traits<Cit>::iterator_category;
if constexpr (derived_from<icat, forward_iterator_tag>) {
STATIC_ASSERT(same_as<icat, forward_iterator_tag>);
} else {
STATIC_ASSERT(same_as<icat, input_iterator_tag>);
}

using ipointer = typename iterator_traits<Cit>::pointer;
if constexpr (_Has_member_arrow<Iter>) {
STATIC_ASSERT(same_as<ipointer, decltype(declval<const Iter&>().operator->())>);
} else {
STATIC_ASSERT(same_as<ipointer, void>);
}
}

{ // [common.iter.const]
Cit defaultConstructed{};
Cit iterConstructed{Iter{input}};
Cit sentinelConstructed(Sen{});
Cit copyConstructed{defaultConstructed};
copyConstructed = iterConstructed;

OCit conversionConstructed{defaultConstructed};
conversionConstructed = iterConstructed;

OCit conversionConstructedSentinel{sentinelConstructed};
conversionConstructed = iterConstructed;
}

{ // [common.iter.access]
Cit iter{Iter{input}};
assert(*iter == P(0, 1));
assert(iter->first == 0);
assert(iter->second == 1);
if constexpr (HasProxy<Iter>) {
// We return a proxy class here
static_assert(is_class_v<decltype(iter.operator->())>);
} else {
// Either a pointer or the wrapped iterator
static_assert(!is_class_v<decltype(iter.operator->())>);
}

const Cit constIter{Iter{input}};
assert(*constIter == P(0, 1));
assert(constIter->first == 0);
assert(constIter->second == 1);
if constexpr (HasProxy<Iter>) {
// We return a proxy class here
static_assert(is_class_v<decltype(constIter.operator->())>);
} else {
// Either a pointer or the wrapped iterator
static_assert(!is_class_v<decltype(constIter.operator->())>);
}
}

{ // [common.iter.nav]
Cit iter{Iter{input}};
++iter;
assert(*iter == P(0, 2));

assert(*iter++ == P(0, 2));
assert(*iter == P(0, 3));
}

{ // [common.iter.cmp]
// Compare iterator / iterator
assert(Cit{Iter{input}} == Cit{Iter{input}});
assert(Cit{Iter{input}} != Cit{Iter{input + 1}});

// Compare iterator / sentinel
assert(Cit{Iter{input}} == Cit{Sen{input}});
assert(Cit{Sen{input}} != Cit{Iter{input + 1}});

// Compare sentinel / sentinel
assert(Cit{Sen{input}} == Cit{Sen{input}});
assert(Cit{Sen{input}} == Cit{Sen{input + 1}});

if constexpr (CanDifference<Iter>) {
// Difference iterator / iterator
const same_as<iter_difference_t<Iter>> auto diff_it_it = Cit{Iter{input}} - Cit{Iter{input + 1}};
assert(diff_it_it == -1);

// Difference iterator / sentinel
const same_as<iter_difference_t<Iter>> auto diff_it_sen = Cit{Iter{input}} - Cit{Sen{input + 1}};
const same_as<iter_difference_t<Iter>> auto diff_sen_it = Cit{Sen{input + 1}} - Cit{Iter{input}};
assert(diff_it_sen == -1);
assert(diff_sen_it == 1);

// Difference sentinel / sentinel
const same_as<iter_difference_t<Iter>> auto diff_sen_sen = Cit{Sen{input}} - Cit{Sen{input + 1}};
assert(diff_sen_sen == 0);

// Difference iterator / other iterator
const same_as<iter_difference_t<Iter>> auto diff_it_oit = Cit{Iter{input}} - OCit{Iter{input + 1}};
assert(diff_it_oit == -1);

// Difference iterator / other sentinel
const same_as<iter_difference_t<Iter>> auto diff_it_osen = Cit{Iter{input}} - OCit{OSen{input + 1}};
assert(diff_it_osen == -1);

// Difference other iterator / sentinel
const same_as<iter_difference_t<Iter>> auto diff_sen_oit = Cit{Sen{input + 1}} - OCit{Iter{input}};
assert(diff_sen_oit == 1);

// Difference sentinel / other sentinel
const same_as<iter_difference_t<Iter>> auto diff_sen_osen = Cit{Sen{input}} - OCit{OSen{input + 1}};
assert(diff_sen_osen == 0);
}
}

{ // [common.iter.cust]
if constexpr (input_iterator<Iter>) { // iter_move
Cit iter1{Iter{input}};

const same_as<iter_value_t<Iter>> auto element1 = ranges::iter_move(iter1);
assert(element1 == P(0, 1));
}

if constexpr (indirectly_swappable<Iter>) { // iter_swap
Cit iter1{Iter{input}};
Cit iter2{Iter{input + 1}};

ranges::iter_swap(iter1, iter2);
assert(*iter1 == P(0, 2));
assert(*iter2 == P(0, 1));
}
}
}
}
};

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

using pointerTest = common_iterator<P*, void*>;
pointerTest pointerIter{input};

assert(*pointerIter == P(0, 1));
assert(pointerIter->first == 0);
assert(pointerIter->second == 1);
static_assert(is_same_v<decltype(pointerIter.operator->()), P* const&>);

using countedTest = common_iterator<counted_iterator<P*>, default_sentinel_t>;
countedTest countedIter{counted_iterator{input, 3}};

assert(*countedIter == P(0, 1));
assert(countedIter->first == 0);
assert(countedIter->second == 1);
static_assert(is_same_v<decltype(countedIter.operator->()), P*>);

return true;
}

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

test_operator_arrow();
}
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_common_iterator_death/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_winsdk_concepts_matrix.lst
Loading