forked from OSchip/llvm-project
[libcxx][ranges] Add common_iterator.
Differential Revision: https://reviews.llvm.org/D103335
This commit is contained in:
parent
4a30a5c8d9
commit
1a29403d2f
|
@ -77,7 +77,7 @@ Section,Description,Dependencies,Assignee,Complete
|
|||
[move.sentinel],,[predef.iterators],Unassigned,Not started
|
||||
[common.iterator],,"| [iterator.concepts]
|
||||
| [iterator.cust.swap]
|
||||
| [iterator.cust.move]",Zoe Carver,In Progress
|
||||
| [iterator.cust.move]",Zoe Carver,✅
|
||||
[default.sentinels],std::default_sentinel_t.,No dependencies,Zoe Carver,✅
|
||||
[counted.iterator],,"| [iterator.concepts]
|
||||
| [iterator.cust.swap]
|
||||
|
|
|
|
@ -133,6 +133,7 @@ set(files
|
|||
__iterator/access.h
|
||||
__iterator/advance.h
|
||||
__iterator/back_insert_iterator.h
|
||||
__iterator/common_iterator.h
|
||||
__iterator/concepts.h
|
||||
__iterator/data.h
|
||||
__iterator/default_sentinel.h
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
// -*- 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 <__debug>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <__iterator/iter_move.h>
|
||||
#include <__iterator/iter_swap.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/readable_traits.h>
|
||||
#include <concepts>
|
||||
#include <variant>
|
||||
|
||||
#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<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
|
||||
requires (!same_as<_Iter, _Sent> && copyable<_Iter>)
|
||||
class common_iterator {
|
||||
class __proxy {
|
||||
friend common_iterator;
|
||||
|
||||
iter_value_t<_Iter> __value;
|
||||
// We can move __x because the only caller verifies that __x is not a reference.
|
||||
constexpr __proxy(iter_reference_t<_Iter>&& __x)
|
||||
: __value(_VSTD::move(__x)) {}
|
||||
|
||||
public:
|
||||
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(_VSTD::forward<iter_reference_t<_Iter>>(__x)) {}
|
||||
|
||||
public:
|
||||
constexpr static bool __valid_for_iter =
|
||||
constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>> &&
|
||||
move_constructible<iter_value_t<_Iter>>;
|
||||
|
||||
const iter_value_t<_Iter>& operator*() const {
|
||||
return __value;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
variant<_Iter, _Sent> __hold_;
|
||||
|
||||
common_iterator() requires default_initializable<_Iter> = default;
|
||||
|
||||
constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {}
|
||||
constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {}
|
||||
|
||||
template<class _I2, class _S2>
|
||||
requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent>
|
||||
constexpr common_iterator(const common_iterator<_I2, _S2>& __other)
|
||||
: __hold_([&]() -> variant<_Iter, _Sent> {
|
||||
_LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Constructed from valueless iterator.");
|
||||
if (__other.__hold_.index() == 0)
|
||||
return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)};
|
||||
return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)};
|
||||
}()) {}
|
||||
|
||||
template<class _I2, class _S2>
|
||||
requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> &&
|
||||
assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&>
|
||||
common_iterator& operator=(const common_iterator<_I2, _S2>& __other) {
|
||||
_LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Assigned from valueless iterator.");
|
||||
|
||||
auto __idx = __hold_.index();
|
||||
auto __other_idx = __other.__hold_.index();
|
||||
|
||||
// If they're the same index, just assign.
|
||||
if (__idx == 0 && __other_idx == 0)
|
||||
_VSTD::__unchecked_get<0>(__hold_) = _VSTD::__unchecked_get<0>(__other.__hold_);
|
||||
else if (__idx == 1 && __other_idx == 1)
|
||||
_VSTD::__unchecked_get<1>(__hold_) = _VSTD::__unchecked_get<1>(__other.__hold_);
|
||||
|
||||
// Otherwise replace with the oposite element.
|
||||
else if (__other_idx == 1)
|
||||
__hold_.template emplace<1>(_VSTD::__unchecked_get<1>(__other.__hold_));
|
||||
else if (__other_idx == 0)
|
||||
__hold_.template emplace<0>(_VSTD::__unchecked_get<0>(__other.__hold_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
decltype(auto) operator*()
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot dereference sentinel. Common iterator not holding an iterator.");
|
||||
return *_VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
}
|
||||
|
||||
decltype(auto) operator*() const
|
||||
requires __dereferenceable<const _Iter>
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot dereference sentinel. Common iterator not holding an iterator.");
|
||||
return *_VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
}
|
||||
|
||||
template<class _I2 = _Iter>
|
||||
decltype(auto) operator->() const
|
||||
requires indirectly_readable<const _I2> &&
|
||||
(requires(const _I2& __i) { __i.operator->(); } ||
|
||||
is_reference_v<iter_reference_t<_I2>> ||
|
||||
constructible_from<iter_value_t<_I2>, iter_reference_t<_I2>>)
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot dereference sentinel. Common iterator not holding an iterator.");
|
||||
|
||||
if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) {
|
||||
return _VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
} else if constexpr (is_reference_v<iter_reference_t<_Iter>>) {
|
||||
auto&& __tmp = *_VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
return _VSTD::addressof(__tmp);
|
||||
} else {
|
||||
return __proxy(*_VSTD::__unchecked_get<_Iter>(__hold_));
|
||||
}
|
||||
}
|
||||
|
||||
common_iterator& operator++() {
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot increment sentinel. Common iterator not holding an iterator.");
|
||||
++_VSTD::__unchecked_get<_Iter>(__hold_); return *this;
|
||||
}
|
||||
|
||||
decltype(auto) operator++(int) {
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot increment sentinel. Common iterator not holding an iterator.");
|
||||
|
||||
if constexpr (forward_iterator<_Iter>) {
|
||||
auto __tmp = *this;
|
||||
++*this;
|
||||
return __tmp;
|
||||
} else if constexpr (requires (_Iter& __i) { { *__i++ } -> __referenceable; } ||
|
||||
!__postfix_proxy::__valid_for_iter) {
|
||||
return _VSTD::__unchecked_get<_Iter>(__hold_)++;
|
||||
} else {
|
||||
__postfix_proxy __p(**this);
|
||||
++*this;
|
||||
return __p;
|
||||
}
|
||||
}
|
||||
|
||||
template<class _I2, sentinel_for<_Iter> _S2>
|
||||
requires sentinel_for<_Sent, _I2>
|
||||
friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
|
||||
!__y.__hold_.valueless_by_exception(),
|
||||
"One or both common_iterators are valueless. (Cannot compare valueless iterators.)");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
|
||||
if (__x_index == __y_index)
|
||||
return true;
|
||||
|
||||
if (__x_index == 0)
|
||||
return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_);
|
||||
|
||||
return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_);
|
||||
}
|
||||
|
||||
template<class _I2, sentinel_for<_Iter> _S2>
|
||||
requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2>
|
||||
friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
|
||||
!__y.__hold_.valueless_by_exception(),
|
||||
"One or both common_iterators are valueless. (Cannot compare valueless iterators.)");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
|
||||
if (__x_index == 1 && __y_index == 1)
|
||||
return true;
|
||||
|
||||
if (__x_index == 0 && __y_index == 0)
|
||||
return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_);
|
||||
|
||||
if (__x_index == 0)
|
||||
return _VSTD::__unchecked_get<_Iter>(__x.__hold_) == _VSTD::__unchecked_get<_S2>(__y.__hold_);
|
||||
|
||||
return _VSTD::__unchecked_get<_Sent>(__x.__hold_) == _VSTD::__unchecked_get<_I2>(__y.__hold_);
|
||||
}
|
||||
|
||||
template<sized_sentinel_for<_Iter> _I2, sized_sentinel_for<_Iter> _S2>
|
||||
requires sized_sentinel_for<_Sent, _I2>
|
||||
friend iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception() &&
|
||||
!__y.__hold_.valueless_by_exception(),
|
||||
"One or both common_iterators are valueless. (Cannot subtract valueless iterators.)");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
|
||||
if (__x_index == 1 && __y_index == 1)
|
||||
return 0;
|
||||
|
||||
if (__x_index == 0 && __y_index == 0)
|
||||
return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_);
|
||||
|
||||
if (__x_index == 0)
|
||||
return _VSTD::__unchecked_get<_Iter>(__x.__hold_) - _VSTD::__unchecked_get<_S2>(__y.__hold_);
|
||||
|
||||
return _VSTD::__unchecked_get<_Sent>(__x.__hold_) - _VSTD::__unchecked_get<_I2>(__y.__hold_);
|
||||
}
|
||||
|
||||
friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i)
|
||||
noexcept(noexcept(ranges::iter_move(declval<const _Iter&>())))
|
||||
requires input_iterator<_Iter>
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_),
|
||||
"Cannot iter_move a sentinel. Common iterator not holding an iterator.");
|
||||
return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_));
|
||||
}
|
||||
|
||||
template<indirectly_swappable<_Iter> _I2, class _S2>
|
||||
friend void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y)
|
||||
noexcept(noexcept(ranges::iter_swap(declval<const _Iter&>(), declval<const _I2&>())))
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_),
|
||||
"Cannot swap __y with a sentinel. Common iterator (__x) not holding an iterator.");
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__y.__hold_),
|
||||
"Cannot swap __x with a sentinel. Common iterator (__y) not holding an iterator.");
|
||||
return ranges::iter_swap( _VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_Iter>(__y.__hold_));
|
||||
}
|
||||
};
|
||||
|
||||
template<class _Iter, class _Sent>
|
||||
struct incrementable_traits<common_iterator<_Iter, _Sent>> {
|
||||
using difference_type = iter_difference_t<_Iter>;
|
||||
};
|
||||
|
||||
template<class _Iter>
|
||||
concept __denotes_forward_iter =
|
||||
requires { typename iterator_traits<_Iter>::iterator_category; } &&
|
||||
derived_from<typename iterator_traits<_Iter>::iterator_category, forward_iterator_tag>;
|
||||
|
||||
template<class _Iter, class _Sent>
|
||||
concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent>& __a) {
|
||||
__a.operator->();
|
||||
};
|
||||
|
||||
template<class, class>
|
||||
struct __arrow_type_or_void {
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template<class _Iter, class _Sent>
|
||||
requires __common_iter_has_ptr_op<_Iter, _Sent>
|
||||
struct __arrow_type_or_void<_Iter, _Sent> {
|
||||
using type = decltype(declval<const common_iterator<_Iter, _Sent>>().operator->());
|
||||
};
|
||||
|
||||
template<class _Iter, class _Sent>
|
||||
struct iterator_traits<common_iterator<_Iter, _Sent>> {
|
||||
using iterator_concept = _If<forward_iterator<_Iter>,
|
||||
forward_iterator_tag,
|
||||
input_iterator_tag>;
|
||||
using iterator_category = _If<__denotes_forward_iter<_Iter>,
|
||||
forward_iterator_tag,
|
||||
input_iterator_tag>;
|
||||
using pointer = typename __arrow_type_or_void<_Iter, _Sent>::type;
|
||||
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
|
|
@ -136,6 +136,10 @@ template<class In, class Out>
|
|||
template<class I1, class I2 = I1>
|
||||
concept indirectly_swappable = see below; // since C++20
|
||||
|
||||
template<input_or_output_iterator I, sentinel_for<I> S>
|
||||
requires (!same_as<I, S> && copyable<I>)
|
||||
class common_iterator; // since C++20
|
||||
|
||||
template<class Category, class T, class Distance = ptrdiff_t,
|
||||
class Pointer = T*, class Reference = T&>
|
||||
struct iterator // deprecated in C++17
|
||||
|
@ -564,6 +568,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
|
|||
#include <__iterator/access.h>
|
||||
#include <__iterator/advance.h>
|
||||
#include <__iterator/back_insert_iterator.h>
|
||||
#include <__iterator/common_iterator.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/data.h>
|
||||
#include <__iterator/default_sentinel.h>
|
||||
|
|
|
@ -480,6 +480,7 @@ module std [system] {
|
|||
module access { private header "__iterator/access.h" }
|
||||
module advance { private header "__iterator/advance.h" }
|
||||
module back_insert_iterator { private header "__iterator/back_insert_iterator.h" }
|
||||
module common_iterator { private header "__iterator/common_iterator.h" }
|
||||
module concepts { private header "__iterator/concepts.h" }
|
||||
module data { private header "__iterator/data.h" }
|
||||
module default_sentinel { private header "__iterator/default_sentinel.h" }
|
||||
|
|
|
@ -201,12 +201,12 @@ namespace std {
|
|||
|
||||
#include <__availability>
|
||||
#include <__config>
|
||||
#include <__functional/hash.h>
|
||||
#include <__tuple>
|
||||
#include <__utility/forward.h>
|
||||
#include <__variant/monostate.h>
|
||||
#include <__tuple>
|
||||
#include <compare>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
|
@ -1748,6 +1748,28 @@ struct _LIBCPP_TEMPLATE_VIS hash<
|
|||
}
|
||||
};
|
||||
|
||||
// __unchecked_get is the same as std::get, except, it is UB to use it with the wrong
|
||||
// type whereas std::get will throw or returning nullptr. This makes it faster than
|
||||
// std::get.
|
||||
template <size_t _Ip, class _Vp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr auto&& __unchecked_get(_Vp&& __v) noexcept {
|
||||
using __variant_detail::__access::__variant;
|
||||
return __variant::__get_alt<_Ip>(_VSTD::forward<_Vp>(__v)).__value;
|
||||
}
|
||||
|
||||
template <class _Tp, class... _Types>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr auto&& __unchecked_get(const variant<_Types...>& __v) noexcept {
|
||||
return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
|
||||
}
|
||||
|
||||
template <class _Tp, class... _Types>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr auto&& __unchecked_get(variant<_Types...>& __v) noexcept {
|
||||
return __unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
// Case 2: http://eel.is/c++draft/iterators.common#common.iter.access-5.2
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(commonIter1.operator->() == buffer);
|
||||
assert(commonIter2.operator->() == buffer);
|
||||
}
|
||||
|
||||
// Case 3: http://eel.is/c++draft/iterators.common#common.iter.access-5.3
|
||||
{
|
||||
auto iter1 = value_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(*commonIter1.operator->().operator->() == 1);
|
||||
assert(*commonIter2.operator->().operator->() == 1);
|
||||
}
|
||||
|
||||
// Case 3: http://eel.is/c++draft/iterators.common#common.iter.access-5.3
|
||||
{
|
||||
auto iter1 = void_plus_plus_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(*commonIter1.operator->().operator->() == 1);
|
||||
assert(*commonIter2.operator->().operator->() == 1);
|
||||
}
|
||||
|
||||
// Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(commonIter1.operator->().base() == buffer);
|
||||
assert(commonIter2.operator->().base() == buffer);
|
||||
}
|
||||
|
||||
// Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1
|
||||
{
|
||||
auto iter1 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(commonIter1.operator->().base() == buffer);
|
||||
assert(commonIter2.operator->().base() == buffer);
|
||||
}
|
||||
|
||||
// Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
|
||||
assert(commonIter1.operator->().base() == buffer);
|
||||
assert(commonIter2.operator->().base() == buffer);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<class I2, class S2>
|
||||
// requires convertible_to<const I2&, I> && convertible_to<const S2&, S> &&
|
||||
// assignable_from<I&, const I2&> && assignable_from<S&, const S2&>
|
||||
// common_iterator& operator=(const common_iterator<I2, S2>& x);
|
||||
|
||||
#include <iterator>
|
||||
#include <ranges>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(cpp17_input_iterator<int*>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(forward_iterator<int*>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1 + 1);
|
||||
auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
{
|
||||
auto iter1 = assignable_iterator<int*>(buffer);
|
||||
auto iter2 = forward_iterator<int*>(buffer + 1);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
auto commonIter2 = std::common_iterator<decltype(iter2), sentinel_type<int*>>(iter2);
|
||||
auto commonSent2 = std::common_iterator<decltype(iter2), sentinel_type<int*>>(sentinel_type<int*>{buffer + 7});
|
||||
|
||||
assert(*commonIter1 == 1);
|
||||
assert(*commonIter2 == 2);
|
||||
|
||||
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);
|
||||
|
||||
commonIter1 = commonSent1;
|
||||
|
||||
assert(commonIter1 == commonSent2);
|
||||
|
||||
commonIter1 = commonSent2;
|
||||
|
||||
assert(commonIter1 == commonSent2);
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
auto iter1 = maybe_valueless_iterator<int*>(buffer);
|
||||
auto iter2 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent2 = std::common_iterator<decltype(iter1),
|
||||
sentinel_throws_on_convert<int*>>(sentinel_throws_on_convert<int*>{buffer + 8});
|
||||
auto commonIter2 = std::common_iterator<decltype(iter2), sentinel_type<int*>>(iter2);
|
||||
|
||||
try {
|
||||
commonIter1 = commonSent2;
|
||||
assert(false);
|
||||
} catch (int x) {
|
||||
assert(x == 42);
|
||||
commonIter1 = commonIter2;
|
||||
}
|
||||
|
||||
assert(*commonIter1 == 1);
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<I> = default;
|
||||
// constexpr common_iterator(I i);
|
||||
// constexpr common_iterator(S s);
|
||||
// template<class I2, class S2>
|
||||
// requires convertible_to<const I2&, I> && convertible_to<const S2&, S>
|
||||
// constexpr common_iterator(const common_iterator<I2, S2>& x);
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
template<class I, class S>
|
||||
concept ValidCommonIterator = requires {
|
||||
typename std::common_iterator<I, S>;
|
||||
};
|
||||
|
||||
template<class I, class I2>
|
||||
concept ConvCtorEnabled = requires(std::common_iterator<I2, sentinel_type<int*>> ci) {
|
||||
std::common_iterator<I, sentinel_type<int*>>(ci);
|
||||
};
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
static_assert( std::is_default_constructible_v<std::common_iterator<int*, sentinel_type<int*>>>);
|
||||
static_assert(!std::is_default_constructible_v<std::common_iterator<non_default_constructible_iterator<int*>, sentinel_type<int*>>>);
|
||||
|
||||
// Not copyable:
|
||||
static_assert(!ValidCommonIterator<cpp20_input_iterator<int*>, sentinel_type<int*>>);
|
||||
// Same iter and sent:
|
||||
static_assert(!ValidCommonIterator<cpp17_input_iterator<int*>, cpp17_input_iterator<int*>>);
|
||||
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(*iter1 == 1);
|
||||
assert(*commonIter1 == 1);
|
||||
assert(commonIter1 != commonSent1);
|
||||
}
|
||||
{
|
||||
auto iter1 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(*iter1 == 1);
|
||||
assert(*commonIter1 == 1);
|
||||
assert(commonIter1 != commonSent1);
|
||||
}
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(*iter1 == 1);
|
||||
assert(*commonIter1 == 1);
|
||||
assert(commonIter1 != commonSent1);
|
||||
}
|
||||
|
||||
// Conversion constructor:
|
||||
{
|
||||
convertible_iterator<int*> conv{buffer};
|
||||
auto commonIter1 = std::common_iterator<convertible_iterator<int*>, sentinel_type<int*>>(conv);
|
||||
auto commonIter2 = std::common_iterator<forward_iterator<int*>, sentinel_type<int*>>(commonIter1);
|
||||
assert(*commonIter2 == 1);
|
||||
|
||||
static_assert( ConvCtorEnabled<forward_iterator<int*>, convertible_iterator<int*>>);
|
||||
static_assert(!ConvCtorEnabled<forward_iterator<int*>, random_access_iterator<int*>>);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<const I>;
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto iter2 = simple_iterator<int*>(buffer);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto iter2 = value_iterator<int*>(buffer);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto iter2 = cpp17_input_iterator<int*>(buffer);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto iter2 = forward_iterator<int*>(buffer);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto iter2 = random_access_iterator<int*>(buffer);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<class I2, sentinel_for<I> S2>
|
||||
// requires sentinel_for<S, I2>
|
||||
// friend bool operator==(
|
||||
// const common_iterator& x, const common_iterator<I2, S2>& y);
|
||||
// template<class I2, sentinel_for<I> S2>
|
||||
// requires sentinel_for<S, I2> && equality_comparable_with<I, I2>
|
||||
// friend bool operator==(
|
||||
// const common_iterator& x, const common_iterator<I2, S2>& y);
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
}
|
||||
{
|
||||
auto iter1 = value_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
}
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto iter2 = comparable_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter2), sentinel_type<int*>>(iter2);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter2), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 == commonIter2);
|
||||
assert(commonSent1 != commonIter2);
|
||||
assert(commonSent1 == commonSent2);
|
||||
assert(commonSent2 == commonSent1);
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
assert(commonIter1 == commonIter2);
|
||||
assert(commonIter2 == commonIter1);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
|
||||
// This check may *seem* incorrect (our iterators point to two completely different
|
||||
// elements of buffer). However, this is actually what the Standard wants.
|
||||
// See https://eel.is/c++draft/iterators.common#common.iter.cmp-2.
|
||||
assert(commonIter1 == commonIter2);
|
||||
}
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
}
|
||||
{
|
||||
auto iter1 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
}
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
const auto commonSent2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
assert(commonIter1 != commonSent1);
|
||||
assert(commonIter2 != commonSent2);
|
||||
assert(commonSent1 != commonIter1);
|
||||
assert(commonSent2 != commonIter2);
|
||||
|
||||
assert(commonSent1 == commonSent2);
|
||||
assert(commonSent2 == commonSent1);
|
||||
|
||||
for (auto i = 1; commonIter1 != commonSent1; ++i) {
|
||||
assert(*(commonIter1++) == i);
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
assert(commonSent1 == commonIter1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<I> iter_move(const common_iterator& i)
|
||||
// noexcept(noexcept(ranges::iter_move(declval<const I&>())))
|
||||
// requires input_iterator<I>;
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
assert(std::ranges::iter_move(commonIter1) == 1);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&);
|
||||
}
|
||||
{
|
||||
auto iter1 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
assert(std::ranges::iter_move(commonIter1) == 1);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&);
|
||||
}
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
assert(std::ranges::iter_move(commonIter1) == 1);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<indirectly_swappable<I> I2, class S2>
|
||||
// friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
|
||||
// noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(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);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<input_iterator I, class S>
|
||||
// struct iterator_traits<common_iterator<I, S>>;
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
{
|
||||
using Iter = simple_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
static_assert(std::same_as<IterTraits::pointer, int*>);
|
||||
static_assert(std::same_as<IterTraits::reference, int&>);
|
||||
}
|
||||
{
|
||||
using Iter = value_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
// Note: IterTraits::pointer == __proxy.
|
||||
static_assert(!std::same_as<IterTraits::pointer, int*>);
|
||||
static_assert(std::same_as<IterTraits::reference, int>);
|
||||
}
|
||||
{
|
||||
using Iter = non_const_deref_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
static_assert(std::same_as<IterTraits::pointer, void>);
|
||||
static_assert(std::same_as<IterTraits::reference, int&>);
|
||||
}
|
||||
{
|
||||
using Iter = cpp17_input_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::input_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
static_assert(std::same_as<IterTraits::pointer, const Iter&>);
|
||||
static_assert(std::same_as<IterTraits::reference, int&>);
|
||||
}
|
||||
{
|
||||
using Iter = forward_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::forward_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::forward_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
static_assert(std::same_as<IterTraits::pointer, const Iter&>);
|
||||
static_assert(std::same_as<IterTraits::reference, int&>);
|
||||
}
|
||||
{
|
||||
using Iter = random_access_iterator<int*>;
|
||||
using CommonIter = std::common_iterator<Iter, sentinel_type<int*>>;
|
||||
using IterTraits = std::iterator_traits<CommonIter>;
|
||||
|
||||
static_assert(std::same_as<IterTraits::iterator_concept, std::forward_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::iterator_category, std::forward_iterator_tag>);
|
||||
static_assert(std::same_as<IterTraits::value_type, int>);
|
||||
static_assert(std::same_as<IterTraits::difference_type, std::ptrdiff_t>);
|
||||
static_assert(std::same_as<IterTraits::pointer, const Iter&>);
|
||||
static_assert(std::same_as<IterTraits::reference, int&>);
|
||||
}
|
||||
|
||||
// Testing iterator conformance.
|
||||
{
|
||||
static_assert(std::input_iterator<std::common_iterator<cpp17_input_iterator<int*>, sentinel_type<int*>>>);
|
||||
static_assert(std::forward_iterator<std::common_iterator<forward_iterator<int*>, sentinel_type<int*>>>);
|
||||
static_assert(std::forward_iterator<std::common_iterator<random_access_iterator<int*>, sentinel_type<int*>>>);
|
||||
static_assert(std::forward_iterator<std::common_iterator<contiguous_iterator<int*>, sentinel_type<int*>>>);
|
||||
// Even these are only forward.
|
||||
static_assert(!std::bidirectional_iterator<std::common_iterator<random_access_iterator<int*>, sentinel_type<int*>>>);
|
||||
static_assert(!std::bidirectional_iterator<std::common_iterator<contiguous_iterator<int*>, sentinel_type<int*>>>);
|
||||
|
||||
using Iter = std::common_iterator<forward_iterator<int*>, sentinel_type<int*>>;
|
||||
static_assert(std::indirectly_writable<Iter, int>);
|
||||
static_assert(std::indirectly_swappable<Iter, Iter>);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2>
|
||||
// requires sized_sentinel_for<S, I2>
|
||||
// friend iter_difference_t<I2> operator-(
|
||||
// const common_iterator& x, const common_iterator<I2, S2>& y);
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(sized_sentinel_type<int*>{buffer + 8});
|
||||
assert(commonIter1 - commonSent1 == -8);
|
||||
assert(commonSent1 - commonIter1 == 8);
|
||||
assert(commonIter1 - commonIter1 == 0);
|
||||
assert(commonSent1 - commonSent1 == 0);
|
||||
}
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto iter2 = comparable_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(iter1);
|
||||
auto commonIter2 = std::common_iterator<decltype(iter2), sized_sentinel_type<int*>>(iter2);
|
||||
|
||||
assert(commonIter1 - commonIter2 == 0);
|
||||
}
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
const auto commonIter1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(iter1);
|
||||
const auto commonSent1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(sized_sentinel_type<int*>{buffer + 8});
|
||||
assert(commonIter1 - commonSent1 == -8);
|
||||
assert(commonSent1 - commonIter1 == 8);
|
||||
assert(commonIter1 - commonIter1 == 0);
|
||||
assert(commonSent1 - commonSent1 == 0);
|
||||
}
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto iter2 = comparable_iterator<int*>(buffer);
|
||||
const auto commonIter1 = std::common_iterator<decltype(iter1), sized_sentinel_type<int*>>(iter1);
|
||||
const auto commonIter2 = std::common_iterator<decltype(iter2), sized_sentinel_type<int*>>(iter2);
|
||||
|
||||
assert(commonIter1 - commonIter2 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
struct Incomplete;
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
// Reference: http://eel.is/c++draft/iterators.common#common.iter.nav-5
|
||||
// Case 2: can-reference
|
||||
{
|
||||
auto iter1 = simple_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
|
||||
// Case 2: can-reference
|
||||
{
|
||||
auto iter1 = value_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
|
||||
// Case 3: postfix-proxy
|
||||
{
|
||||
auto iter1 = void_plus_plus_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
|
||||
// Case 2: where this is not referencable or move constructible
|
||||
{
|
||||
auto iter1 = value_type_not_move_constructible_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{buffer + 8});
|
||||
|
||||
commonIter1++;
|
||||
// Note: postfix operator++ returns void.
|
||||
// assert(*(commonIter1++) == 1);
|
||||
assert(*commonIter1 == 2);
|
||||
assert(*(++commonIter1) == 3);
|
||||
assert(*commonIter1 == 3);
|
||||
|
||||
for (auto i = 3; commonIter1 != commonSent1; ++i) {
|
||||
assert(*commonIter1 == i);
|
||||
commonIter1++;
|
||||
}
|
||||
assert(commonIter1 == commonSent1);
|
||||
}
|
||||
|
||||
// Case 2: can-reference
|
||||
{
|
||||
auto iter1 = cpp17_input_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
|
||||
// Case 1: forward_iterator
|
||||
{
|
||||
auto iter1 = forward_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
|
||||
// Case 1: forward_iterator
|
||||
{
|
||||
auto iter1 = random_access_iterator<int*>(buffer);
|
||||
auto commonIter1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(iter1);
|
||||
auto commonSent1 = std::common_iterator<decltype(iter1), sentinel_type<int*>>(sentinel_type<int*>{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);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
class assignable_iterator;
|
||||
|
||||
template <class It>
|
||||
class simple_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::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 It>
|
||||
class value_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::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 std::move(*it_);}
|
||||
|
||||
constexpr value_iterator& operator++() {++it_; return *this;}
|
||||
constexpr value_iterator operator++(int)
|
||||
{value_iterator tmp(*this); ++(*this); return tmp;}
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class void_plus_plus_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
void_plus_plus_iterator() = default;
|
||||
explicit constexpr void_plus_plus_iterator(It it) : it_(it) {}
|
||||
|
||||
constexpr value_type operator*() const {return std::move(*it_);}
|
||||
|
||||
constexpr void_plus_plus_iterator& operator++() {++it_; return *this;}
|
||||
constexpr void operator++(int) {++(*this);}
|
||||
};
|
||||
|
||||
// Not referenceable, constructible, and not move constructible.
|
||||
template <class It>
|
||||
class value_type_not_move_constructible_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
template<class T>
|
||||
struct hold {
|
||||
T value_;
|
||||
hold(T v) : value_(v) {}
|
||||
hold(const hold&) = delete;
|
||||
hold(hold&&) = delete;
|
||||
};
|
||||
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type underlying_value_type;
|
||||
typedef hold<underlying_value_type> value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
value_type_not_move_constructible_iterator() = default;
|
||||
explicit constexpr value_type_not_move_constructible_iterator(It it) : it_(it) {}
|
||||
|
||||
constexpr underlying_value_type operator*() const {return std::move(*it_);}
|
||||
|
||||
constexpr value_type_not_move_constructible_iterator& operator++() {++it_; return *this;}
|
||||
constexpr void operator++(int) {++(*this);}
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class comparable_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
comparable_iterator() = default;
|
||||
explicit constexpr comparable_iterator(It it) : it_(it) {}
|
||||
|
||||
constexpr reference operator*() const {return *it_;}
|
||||
|
||||
constexpr comparable_iterator& operator++() {++it_; return *this;}
|
||||
constexpr comparable_iterator operator++(int)
|
||||
{comparable_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
friend constexpr bool operator==(const comparable_iterator& lhs, const simple_iterator<It>& rhs) {
|
||||
return lhs.base() == rhs.base();
|
||||
}
|
||||
friend constexpr bool operator==(const simple_iterator<It>& lhs, const comparable_iterator& rhs) {
|
||||
return lhs.base() == rhs.base();
|
||||
}
|
||||
|
||||
friend constexpr auto operator-(const comparable_iterator& lhs, const simple_iterator<It>& rhs) {
|
||||
return lhs.base() - rhs.base();
|
||||
}
|
||||
friend constexpr auto operator-(const simple_iterator<It>& lhs, const comparable_iterator& rhs) {
|
||||
return lhs.base() - rhs.base();
|
||||
}
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class convertible_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
convertible_iterator() = default;
|
||||
explicit constexpr convertible_iterator(It it) : it_(it) {}
|
||||
|
||||
constexpr reference operator*() const {return *it_;}
|
||||
|
||||
constexpr convertible_iterator& operator++() {++it_; return *this;}
|
||||
constexpr convertible_iterator operator++(int)
|
||||
{convertible_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
operator forward_iterator<It>() const { return forward_iterator<It>(it_); }
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class non_const_deref_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
non_const_deref_iterator() = default;
|
||||
explicit constexpr non_const_deref_iterator(It it) : it_(it) {}
|
||||
|
||||
constexpr reference operator*() {return *it_;} // Note: non-const.
|
||||
|
||||
constexpr non_const_deref_iterator& operator++() {++it_; return *this;}
|
||||
constexpr non_const_deref_iterator operator++(int)
|
||||
{non_const_deref_iterator tmp(*this); ++(*this); return tmp;}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sentinel_type {
|
||||
T base;
|
||||
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const sentinel_type& lhs, const U& rhs) { return lhs.base == rhs.base(); }
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const U& lhs, const sentinel_type& rhs) { return lhs.base() == rhs.base; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sized_sentinel_type {
|
||||
T base;
|
||||
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); }
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; }
|
||||
template<class U>
|
||||
friend constexpr auto operator- (const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); }
|
||||
template<class U>
|
||||
friend constexpr auto operator- (const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; }
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class assignable_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
assignable_iterator() = default;
|
||||
explicit constexpr assignable_iterator(It it) : it_(it) {}
|
||||
|
||||
assignable_iterator(const forward_iterator<It>& it) : it_(it.base()) {}
|
||||
assignable_iterator(const sentinel_type<It>& it) : it_(it.base) {}
|
||||
|
||||
constexpr reference operator*() const {return *it_;}
|
||||
|
||||
constexpr assignable_iterator& operator++() {++it_; return *this;}
|
||||
constexpr assignable_iterator operator++(int)
|
||||
{assignable_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
assignable_iterator& operator=(const forward_iterator<It> &other) {
|
||||
it_ = other.base();
|
||||
return *this;
|
||||
}
|
||||
|
||||
assignable_iterator& operator=(const sentinel_type<It> &other) {
|
||||
it_ = other.base;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
template<class T>
|
||||
struct sentinel_throws_on_convert {
|
||||
T base;
|
||||
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const sentinel_throws_on_convert& lhs, const U& rhs) { return lhs.base == rhs.base(); }
|
||||
template<class U>
|
||||
friend constexpr bool operator==(const U& lhs, const sentinel_throws_on_convert& rhs) { return lhs.base() == rhs.base; }
|
||||
|
||||
operator sentinel_type<int*>() const { throw 42; }
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class maybe_valueless_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
constexpr It base() const {return it_;}
|
||||
|
||||
maybe_valueless_iterator() = default;
|
||||
explicit constexpr maybe_valueless_iterator(It it) : it_(it) {}
|
||||
|
||||
maybe_valueless_iterator(const forward_iterator<It>& it) : it_(it.base()) {}
|
||||
|
||||
constexpr reference operator*() const {return *it_;}
|
||||
|
||||
constexpr maybe_valueless_iterator& operator++() {++it_; return *this;}
|
||||
constexpr maybe_valueless_iterator operator++(int)
|
||||
{maybe_valueless_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
maybe_valueless_iterator& operator=(const forward_iterator<It> &other) {
|
||||
it_ = other.base();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
|
||||
#endif // TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H
|
|
@ -161,6 +161,59 @@ operator!=(const forward_iterator<T>& x, const forward_iterator<U>& y)
|
|||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
class non_default_constructible_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
template <class U> friend class non_default_constructible_iterator;
|
||||
public:
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef typename std::iterator_traits<It>::value_type value_type;
|
||||
typedef typename std::iterator_traits<It>::difference_type difference_type;
|
||||
typedef It pointer;
|
||||
typedef typename std::iterator_traits<It>::reference reference;
|
||||
|
||||
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
|
||||
|
||||
non_default_constructible_iterator() = delete;
|
||||
|
||||
explicit TEST_CONSTEXPR_CXX14 non_default_constructible_iterator(It it) : it_(it) {}
|
||||
template <class U>
|
||||
TEST_CONSTEXPR_CXX14 non_default_constructible_iterator(const non_default_constructible_iterator<U>& u) :it_(u.it_) {}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
|
||||
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
|
||||
|
||||
TEST_CONSTEXPR_CXX14 non_default_constructible_iterator& operator++() {++it_; return *this;}
|
||||
TEST_CONSTEXPR_CXX14 non_default_constructible_iterator operator++(int)
|
||||
{non_default_constructible_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
friend TEST_CONSTEXPR_CXX14 bool operator==(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y)
|
||||
{return x.it_ == y.it_;}
|
||||
friend TEST_CONSTEXPR_CXX14 bool operator!=(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y)
|
||||
{return !(x == y);}
|
||||
|
||||
template <class T>
|
||||
void operator,(T const &) DELETE_FUNCTION;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
bool TEST_CONSTEXPR_CXX14
|
||||
operator==(const non_default_constructible_iterator<T>& x, const non_default_constructible_iterator<U>& y)
|
||||
{
|
||||
return x.base() == y.base();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
bool TEST_CONSTEXPR_CXX14
|
||||
operator!=(const non_default_constructible_iterator<T>& x, const non_default_constructible_iterator<U>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
class bidirectional_iterator
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue