diff --git a/libcxx/docs/OneRangesProposalStatus.csv b/libcxx/docs/OneRangesProposalStatus.csv --- a/libcxx/docs/OneRangesProposalStatus.csv +++ b/libcxx/docs/OneRangesProposalStatus.csv @@ -77,7 +77,7 @@ [move.sentinel],,[predef.iterators],Unassigned,Not started [common.iterator],,"| [iterator.concepts] | [iterator.cust.swap] -| [iterator.cust.move]",Zoe Carver,Not started +| [iterator.cust.move]",Zoe Carver,`D103335 `_,✅ [default.sentinels],std::default_sentinel_t.,No dependencies,Unassigned,Not started [counted.iterator],,"| [iterator.concepts] | [iterator.cust.swap] diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -132,6 +132,7 @@ __hash_table __iterator/advance.h __iterator/back_insert_iterator.h + __iterator/common_iterator.h __iterator/concepts.h __iterator/default_sentinel.h __iterator/front_insert_iterator.h diff --git a/libcxx/include/__iterator/common_iterator.h b/libcxx/include/__iterator/common_iterator.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/common_iterator.h @@ -0,0 +1,217 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_COMMON_ITERATOR_H +#define _LIBCPP___ITERATOR_COMMON_ITERATOR_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +template _Sent> + requires (!same_as<_Iter, _Sent> && copyable<_Iter>) +class common_iterator { + union _Hold { + _Iter __iter; // __index == 0; + _Sent __sent; // __index == 1; + + _Hold() = default; + constexpr _Hold(_Iter __iter) : __iter(_VSTD::move(__iter)) {} + constexpr _Hold(_Sent __sent) : __sent(_VSTD::move(__sent)) {} + } __u; + bool __index; + + class __proxy { + friend common_iterator; + + iter_value_t<_Iter> __value; + constexpr __proxy(iter_reference_t<_Iter>&& __x) + : __value(__x) {} + + public: + constexpr const iter_value_t<_Iter>* operator->() const { + return _VSTD::addressof(__value); + } + }; + + class __postfix_proxy { + friend common_iterator; + + iter_value_t<_Iter> __value; + constexpr __postfix_proxy(iter_reference_t<_Iter>&& __x) + : __value(__x) {} + + public: + constexpr const iter_value_t<_Iter>& operator*() const { + return __value; + } + }; + +public: + common_iterator() requires default_initializable<_Iter> = default; + + constexpr common_iterator(_Iter __i) : __u(_VSTD::move(__i)), __index(false) {} + constexpr common_iterator(_Sent __s) : __u(_VSTD::move(__s)), __index(true ) {} + + template + requires convertible_to && convertible_to + constexpr common_iterator(const common_iterator<_I2, _S2>& __other) + : __u(__other.__u), __index(__other.__index) {} + + template + requires convertible_to && convertible_to && + assignable_from && assignable_from + constexpr common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { + __u = __other.__u; + __index = __other.__index; + } + + constexpr decltype(auto) operator*() { return *__u.__iter; } + constexpr decltype(auto) operator*() const + requires __dereferenceable + { return *__u.__iter; } + + constexpr decltype(auto) operator->() const + requires indirectly_readable && + (requires(const _Iter& __i) { __i.operator->(); } || + is_reference_v> || + constructible_from, iter_reference_t<_Iter>>) { + if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { + return __u.__iter; + } else if constexpr (is_reference_v>) { + auto&& __tmp = *__u.__iter; + return _VSTD::addressof(__tmp); + } else { + return __proxy(*__u.__iter); + } + } + + constexpr common_iterator& operator++() { ++__u.__iter; return *this; } + constexpr decltype(auto) operator++(int) { + if constexpr (forward_iterator<_Iter>) { + auto __tmp = *this; + ++*this; + return __tmp; + } else if constexpr (requires (_Iter& __i) { { *__i++ } -> __referenceable; } || + !constructible_from, iter_reference_t<_Iter>>) { + return __u.__iter++; + } else { + __postfix_proxy __p(*this); + ++*this; + return __p; + } + } + + template _S2> + requires sentinel_for<_Sent, _I2> + friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__index == __y.__index) + return true; + + if (__x.__index == 0) + return __x.__u.__iter == __y.__u.__sent; + + return __x.__u.__sent == __y.__u.__iter; + } + + template _S2> + requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> + friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__index && __y.__index) + return true; + + if (__x.__index == 0 && __y.__index == 0) + return __x.__u.__iter == __y.__u.__iter; + + if (__x.__index == 0) + return __x.__u.__iter == __y.__u.__sent; + + return __x.__u.__sent == __y.__u.__iter; + } + + template _I2, sized_sentinel_for<_Iter> _S2> + requires sized_sentinel_for<_Sent, _I2> + friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__index && __y.__index) + return 0; + + if (__x.__index == 0 && __y.__index == 0) + return __x.__u.__iter - __y.__u.__iter; + + if (__x.__index == 0) + return __x.__u.__iter - __y.__u.__sent; + + return __x.__u.__sent - __y.__u.__iter; + } + + friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(declval()))) + requires input_iterator<_Iter> + { return ranges::iter_move(__i.__u.__iter); } + + template _I2, class _S2> + friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) + noexcept(noexcept(ranges::iter_swap(declval(), declval()))) + { return ranges::iter_swap(__x.__u.__iter, __y.__u.__iter); } +}; + +template +struct incrementable_traits> { + using difference_type = iter_difference_t<_Iter>; +}; + +template +concept __denotes_forward_iter = + requires { + typename iterator_traits<_Iter>::iterator_category; + } && + derived_from::iterator_category, forward_iterator_tag>; + +template +concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent> __a) { + __a.operator->(); +}; + +template +struct iterator_traits> { + using iterator_concept = conditional_t, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = conditional_t<__denotes_forward_iter<_Iter>, + forward_iterator_tag, + input_iterator_tag>; + using pointer = conditional_t<__common_iter_has_ptr_op<_Iter, _Sent>, + decltype(declval>().operator->()), + void>; + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using reference = iter_reference_t<_Iter>; +}; + + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -136,6 +136,10 @@ template concept indirectly_swappable = see below; // since C++20 +template S> + requires (!same_as && copyable) +class common_iterator; // since C++20 + template struct iterator // deprecated in C++17 @@ -563,6 +567,7 @@ #include <__functional_base> #include <__iterator/advance.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/common_iterator.h> #include <__iterator/concepts.h> #include <__iterator/default_sentinel.h> #include <__iterator/front_insert_iterator.h> diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// decltype(auto) operator->() const +// requires see below; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->() == buffer); + assert(commonIter2.operator->() == buffer); + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*commonIter1.operator->().operator->() == 1); + assert(*commonIter2.operator->().operator->() == 1); + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// requires convertible_to && convertible_to && +// assignable_from && assignable_from +// common_iterator& operator=(const common_iterator& x); + +#include +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(cpp17_input_iterator(buffer + 1)); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(forward_iterator(buffer + 1)); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + auto commonIter2 = std::common_iterator>(iter1 + 1); + auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 7}); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + + assert(std::ranges::next(commonIter1, 6) != commonSent1); + assert(std::ranges::next(commonIter1, 6) == commonSent2); + + commonSent1 = commonSent2; + + assert(std::ranges::next(commonIter1, 6) == commonSent1); + assert(std::ranges::next(commonIter1, 6) == commonSent2); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// constexpr common_iterator() requires default_initializable = default; +// constexpr common_iterator(I i); +// constexpr common_iterator(S s); +// template +// requires convertible_to && convertible_to +// constexpr common_iterator(const common_iterator& x); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +struct ConvertibleToForwardIter { + int *ptr; + + constexpr operator forward_iterator() { return forward_iterator(ptr); } +}; + +template +concept ValidCommonIterator = requires { + typename std::common_iterator; +}; + +template +concept ConvCtorEnabled = requires(I2 ci) { + std::common_iterator(ci); +}; + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + static_assert( std::is_default_constructible_v>>); + static_assert(!std::is_default_constructible_v, sentienl_type>>); + + // Not copyable: + static_assert(!ValidCommonIterator, sentienl_type>); + // Same iter and sent: + static_assert(!ValidCommonIterator, cpp17_input_iterator>); + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + + // Conversion constructor: + { + ConvertibleToForwardIter conv{buffer}; + auto commonIter = std::common_iterator, sentienl_type>(conv); + assert(*commonIter == 1); + + static_assert(ConvCtorEnabled, sentienl_type, ConvertibleToForwardIter>); + static_assert(!ConvCtorEnabled, sentienl_type, random_access_iterator>); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// decltype(auto) operator*(); +// decltype(auto) operator*() const +// requires dereferenceable; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = simple_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = value_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = cpp17_input_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = forward_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = random_access_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template S2> +// requires sentinel_for +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); +// template S2> +// requires sentinel_for && equality_comparable_with +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// friend iter_rvalue_reference_t iter_move(const common_iterator& i) +// noexcept(noexcept(ranges::iter_move(declval()))) +// requires input_iterator; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template I2, class S2> +// friend void iter_swap(const common_iterator& x, const common_iterator& y) +// noexcept(noexcept(ranges::iter_swap(declval(), declval()))); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// struct iterator_traits>; + +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + { + using Iter = simple_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } + { + using Iter = value_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + // Note: IterTraits::pointer == __proxy. + static_assert(!std::same_as); + static_assert(std::same_as); + } + { + using Iter = cpp17_input_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); // TODO: is this right? + static_assert(std::same_as); + } + { + using Iter = forward_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } + { + using Iter = random_access_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/members.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/members.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/members.pass.cpp @@ -0,0 +1,208 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// decltype(auto) operator*(); +// decltype(auto) operator*() const +// requires dereferenceable; +// decltype(auto) operator->() const +// requires see below; + +// common_iterator& operator++(); +// decltype(auto) operator++(int); + +// template S2> +// requires sentinel_for +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); +// template S2> +// requires sentinel_for && equality_comparable_with +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); + +// template I2, sized_sentinel_for S2> +// requires sized_sentinel_for +// friend iter_difference_t operator-( +// const common_iterator& x, const common_iterator& y); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = simple_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + assert(commonIter1.operator->() == buffer); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + assert(commonIter2 != commonSent2); + assert(commonIter2.operator->() == buffer); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = value_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + assert(*commonIter1.operator->().operator->() == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + assert(commonIter2 != commonSent2); + assert(*commonIter2.operator->().operator->() == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = cpp17_input_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + assert(commonIter1.operator->().base() == buffer); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + assert(commonIter2 != commonSent2); + assert(commonIter2.operator->().base() == buffer); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = forward_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + assert(commonIter1.operator->().base() == buffer); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + assert(commonIter2 != commonSent2); + assert(commonIter2.operator->().base() == buffer); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + const auto iter2 = random_access_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + assert(commonIter1.operator->().base() == buffer); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + assert(commonIter2 != commonSent2); + assert(commonIter2.operator->().base() == buffer); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sized_sentienl_type{buffer + 8}); + assert(commonIter1 - commonSent1 == -8); + assert(commonSent1 - commonIter1 == 8); + assert(commonIter1 - commonIter1 == 0); + assert(commonSent1 - commonSent1 == 0); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template I2, sized_sentinel_for S2> +// requires sized_sentinel_for +// friend iter_difference_t operator-( +// const common_iterator& x, const common_iterator& y); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sized_sentienl_type{buffer + 8}); + assert(commonIter1 - commonSent1 == -8); + assert(commonSent1 - commonIter1 == 8); + assert(commonIter1 - commonIter1 == 0); + assert(commonSent1 - commonSent1 == 0); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// common_iterator& operator++(); +// decltype(auto) operator++(int); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentienl_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h b/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H +#define TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H + +#include "test_macros.h" +#include "test_iterators.h" + +template +class simple_iterator +{ + It it_; + +public: + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + simple_iterator() = default; + explicit constexpr simple_iterator(It it) : it_(it) {} + + constexpr reference operator*() const {return *it_;} + + constexpr simple_iterator& operator++() {++it_; return *this;} + constexpr simple_iterator operator++(int) + {simple_iterator tmp(*this); ++(*this); return tmp;} +}; + +template +class value_iterator +{ + It it_; + +public: + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + value_iterator() = default; + explicit constexpr value_iterator(It it) : it_(it) {} + + constexpr value_type operator*() const {return *it_;} + + constexpr value_iterator& operator++() {++it_; return *this;} + constexpr value_iterator operator++(int) + {value_iterator tmp(*this); ++(*this); return tmp;} +}; + + +template +struct sentienl_type { + T base; + + template + friend constexpr bool operator==(const sentienl_type& lhs, const U& rhs) { return lhs.base == rhs.base(); } + template + friend constexpr bool operator==(const U& lhs, const sentienl_type& rhs) { return lhs.base() == rhs.base; } +}; + +template +struct sized_sentienl_type { + T base; + + template + friend constexpr bool operator==(const sized_sentienl_type& lhs, const U& rhs) { return lhs.base - rhs.base(); } + template + friend constexpr bool operator==(const U& lhs, const sized_sentienl_type& rhs) { return lhs.base() - rhs.base; } + template + friend constexpr auto operator- (const sized_sentienl_type& lhs, const U& rhs) { return lhs.base - rhs.base(); } + template + friend constexpr auto operator- (const U& lhs, const sized_sentienl_type& rhs) { return lhs.base() - rhs.base; } +}; + +#endif // TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -160,6 +160,59 @@ return !(x == y); } +template +class no_default_constructor +{ + It it_; + + template friend class no_default_constructor; +public: + typedef std::forward_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR_CXX14 It base() const {return it_;} + + no_default_constructor() = delete; + + explicit TEST_CONSTEXPR_CXX14 no_default_constructor(It it) : it_(it) {} + template + TEST_CONSTEXPR_CXX14 no_default_constructor(const no_default_constructor& u) :it_(u.it_) {} + + TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;} + TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;} + + TEST_CONSTEXPR_CXX14 no_default_constructor& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 no_default_constructor operator++(int) + {no_default_constructor tmp(*this); ++(*this); return tmp;} + + friend TEST_CONSTEXPR_CXX14 bool operator==(const no_default_constructor& x, const no_default_constructor& y) + {return x.it_ == y.it_;} + friend TEST_CONSTEXPR_CXX14 bool operator!=(const no_default_constructor& x, const no_default_constructor& y) + {return !(x == y);} + + template + void operator,(T const &) DELETE_FUNCTION; +}; + +template +inline +bool TEST_CONSTEXPR_CXX14 +operator==(const no_default_constructor& x, const no_default_constructor& y) +{ + return x.base() == y.base(); +} + +template +inline +bool TEST_CONSTEXPR_CXX14 +operator!=(const no_default_constructor& x, const no_default_constructor& y) +{ + return !(x == y); +} + template class bidirectional_iterator {