mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-02 18:58:15 +00:00
[libc++] Fix bugs in common_iterator; add test coverage.
Differential Revision: https://reviews.llvm.org/D117400
This commit is contained in:
parent
0a3d946e7b
commit
eadf7268d5
@ -126,7 +126,7 @@
|
||||
`3571 <https://wg21.link/LWG3571>`__,"``flush_emit`` should set ``badbit`` if the ``emit`` call fails","October 2021","",""
|
||||
`3572 <https://wg21.link/LWG3572>`__,"``copyable-box`` should be fully ``constexpr``","October 2021","","","|ranges|"
|
||||
`3573 <https://wg21.link/LWG3573>`__,"Missing Throws element for ``basic_string_view(It begin, End end)``","October 2021","|Complete|","14.0"
|
||||
`3574 <https://wg21.link/LWG3574>`__,"``common_iterator`` should be completely ``constexpr``-able","October 2021","","","|ranges|"
|
||||
`3574 <https://wg21.link/LWG3574>`__,"``common_iterator`` should be completely ``constexpr``-able","October 2021","|Complete|","14.0","|ranges|"
|
||||
`3580 <https://wg21.link/LWG3580>`__,"``iota_view``'s ``iterator``'s binary ``operator+`` should be improved","October 2021","","","|ranges|"
|
||||
`3581 <https://wg21.link/LWG3581>`__,"The range constructor makes ``basic_string_view`` not trivially move constructible","October 2021","","","|ranges|"
|
||||
`3585 <https://wg21.link/LWG3585>`__,"``variant`` converting assignment with immovable alternative","October 2021","",""
|
||||
@ -135,7 +135,7 @@
|
||||
`3591 <https://wg21.link/LWG3591>`__,"``lazy_split_view<input_view>::inner-iterator::base() &&`` invalidates outer iterators","October 2021","","","|ranges|"
|
||||
`3592 <https://wg21.link/LWG3592>`__,"``lazy_split_view`` needs to check the simpleness of Pattern","October 2021","","","|ranges|"
|
||||
`3593 <https://wg21.link/LWG3593>`__,"Several iterators' ``base() const &`` and ``lazy_split_view::outer-iterator::value_type::end()`` missing ``noexcept``","October 2021","","","|ranges|"
|
||||
`3595 <https://wg21.link/LWG3595>`__,"Exposition-only classes proxy and postfix-proxy for ``common_iterator`` should be fully ``constexpr``","October 2021","","","|ranges|"
|
||||
`3595 <https://wg21.link/LWG3595>`__,"Exposition-only classes proxy and postfix-proxy for ``common_iterator`` should be fully ``constexpr``","October 2021","|Complete|","14.0","|ranges|"
|
||||
"","","","",""
|
||||
`3645 <https://wg21.link/LWG3645>`__,"``resize_and_overwrite`` is overspecified to call its callback with lvalues", "Not voted in","|Complete|","14.0",""
|
||||
"","","","",""
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -41,7 +41,7 @@ class common_iterator {
|
||||
: __value(_VSTD::move(__x)) {}
|
||||
|
||||
public:
|
||||
const iter_value_t<_Iter>* operator->() const {
|
||||
constexpr const iter_value_t<_Iter>* operator->() const noexcept {
|
||||
return _VSTD::addressof(__value);
|
||||
}
|
||||
};
|
||||
@ -58,7 +58,7 @@ class common_iterator {
|
||||
constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>> &&
|
||||
move_constructible<iter_value_t<_Iter>>;
|
||||
|
||||
const iter_value_t<_Iter>& operator*() const {
|
||||
constexpr const iter_value_t<_Iter>& operator*() const noexcept {
|
||||
return __value;
|
||||
}
|
||||
};
|
||||
@ -75,7 +75,7 @@ public:
|
||||
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.");
|
||||
_LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to construct from a valueless common_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_)};
|
||||
@ -85,7 +85,7 @@ public:
|
||||
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.");
|
||||
_LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator");
|
||||
|
||||
auto __idx = __hold_.index();
|
||||
auto __other_idx = __other.__hold_.index();
|
||||
@ -105,18 +105,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
decltype(auto) operator*()
|
||||
constexpr decltype(auto) operator*()
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot dereference sentinel. Common iterator not holding an iterator.");
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator");
|
||||
return *_VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
}
|
||||
|
||||
decltype(auto) operator*() const
|
||||
constexpr decltype(auto) operator*() const
|
||||
requires __dereferenceable<const _Iter>
|
||||
{
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot dereference sentinel. Common iterator not holding an iterator.");
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator");
|
||||
return *_VSTD::__unchecked_get<_Iter>(__hold_);
|
||||
}
|
||||
|
||||
@ -127,9 +125,7 @@ public:
|
||||
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.");
|
||||
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_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>>) {
|
||||
@ -141,15 +137,12 @@ public:
|
||||
}
|
||||
|
||||
common_iterator& operator++() {
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_),
|
||||
"Cannot increment sentinel. Common iterator not holding an iterator.");
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_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.");
|
||||
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator");
|
||||
if constexpr (forward_iterator<_Iter>) {
|
||||
auto __tmp = *this;
|
||||
++*this;
|
||||
@ -166,10 +159,9 @@ public:
|
||||
|
||||
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.)");
|
||||
friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
|
||||
_LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
@ -185,10 +177,9 @@ public:
|
||||
|
||||
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.)");
|
||||
friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
|
||||
_LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
@ -207,10 +198,9 @@ public:
|
||||
|
||||
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.)");
|
||||
friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) {
|
||||
_LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to subtract from a valueless common_iterator");
|
||||
_LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to subtract a valueless common_iterator");
|
||||
|
||||
auto __x_index = __x.__hold_.index();
|
||||
auto __y_index = __y.__hold_.index();
|
||||
@ -227,24 +217,21 @@ public:
|
||||
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)
|
||||
friend constexpr 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.");
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_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)
|
||||
friend constexpr 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_));
|
||||
_LIBCPP_ASSERT(holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator");
|
||||
_LIBCPP_ASSERT(holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator");
|
||||
return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_));
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,7 +258,7 @@ struct __arrow_type_or_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->());
|
||||
using type = decltype(declval<const common_iterator<_Iter, _Sent>&>().operator->());
|
||||
};
|
||||
|
||||
template<class _Iter, class _Sent>
|
||||
|
@ -0,0 +1,28 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// template<input_or_output_iterator I, sentinel_for<I> S>
|
||||
// requires (!same_as<I, S> && copyable<I>)
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template<class I, class S>
|
||||
concept ValidCommonIterator = requires {
|
||||
typename std::common_iterator<I, S>;
|
||||
};
|
||||
|
||||
static_assert( ValidCommonIterator<int*, const int*>);
|
||||
static_assert(!ValidCommonIterator<int, int>); // !input_or_output_iterator<I>
|
||||
static_assert(!ValidCommonIterator<int*, float*>); // !sentinel_for<S, I>
|
||||
static_assert(!ValidCommonIterator<int*, int*>); // !same_as<I, S>
|
||||
static_assert(!ValidCommonIterator<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>); // !copyable<I>
|
@ -0,0 +1,48 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
|
||||
constexpr bool test()
|
||||
{
|
||||
struct Base {};
|
||||
struct Derived : Base {};
|
||||
|
||||
using BaseIt = std::common_iterator<Base*, const Base*>;
|
||||
using DerivedIt = std::common_iterator<Derived*, const Derived*>;
|
||||
static_assert(std::is_convertible_v<DerivedIt, BaseIt>); // Derived* to Base*
|
||||
static_assert(!std::is_constructible_v<DerivedIt, BaseIt>); // Base* to Derived*
|
||||
|
||||
Derived a[10] = {};
|
||||
DerivedIt it = DerivedIt(a); // the iterator type
|
||||
BaseIt jt = BaseIt(it);
|
||||
assert(jt == BaseIt(a));
|
||||
|
||||
it = DerivedIt((const Derived*)a); // the sentinel type
|
||||
jt = BaseIt(it);
|
||||
assert(jt == BaseIt(a));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// constexpr common_iterator() requires default_initializable<I> = default;
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
constexpr bool test()
|
||||
{
|
||||
{
|
||||
using It = cpp17_input_iterator<int*>;
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
static_assert(!std::is_default_constructible_v<It>); // premise
|
||||
static_assert(!std::is_default_constructible_v<CommonIt>); // conclusion
|
||||
}
|
||||
{
|
||||
// The base iterator is value-initialized.
|
||||
std::common_iterator<int*, sentinel_wrapper<int*>> c;
|
||||
assert(c == nullptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(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
|
||||
|
||||
// constexpr common_iterator(I i);
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template<class It>
|
||||
constexpr bool test() {
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
int a[] = {1,2,3};
|
||||
It it = It(a);
|
||||
CommonIt lv = CommonIt(it);
|
||||
assert(&*lv == a);
|
||||
CommonIt rv = CommonIt(std::move(it));
|
||||
assert(&*rv == a);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<cpp17_input_iterator<int*>>();
|
||||
test<forward_iterator<int*>>();
|
||||
test<bidirectional_iterator<int*>>();
|
||||
test<random_access_iterator<int*>>();
|
||||
test<contiguous_iterator<int*>>();
|
||||
test<int*>();
|
||||
test<const int*>();
|
||||
|
||||
static_assert(test<cpp17_input_iterator<int*>>());
|
||||
static_assert(test<forward_iterator<int*>>());
|
||||
static_assert(test<bidirectional_iterator<int*>>());
|
||||
static_assert(test<random_access_iterator<int*>>());
|
||||
static_assert(test<contiguous_iterator<int*>>());
|
||||
static_assert(test<int*>());
|
||||
static_assert(test<const int*>());
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// 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,63 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// constexpr common_iterator(S s);
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template<class It>
|
||||
constexpr bool test() {
|
||||
using Sent = sentinel_wrapper<It>;
|
||||
using CommonIt = std::common_iterator<It, Sent>;
|
||||
int a[] = {1,2,3};
|
||||
It it = It(a);
|
||||
Sent sent = Sent(It(a+1));
|
||||
|
||||
CommonIt lv = CommonIt(sent);
|
||||
assert(lv == CommonIt(sent));
|
||||
assert(lv != CommonIt(it));
|
||||
if (!std::is_constant_evaluated()) {
|
||||
assert(lv == std::next(CommonIt(it)));
|
||||
}
|
||||
|
||||
CommonIt rv = CommonIt(std::move(sent));
|
||||
assert(rv == CommonIt(sent));
|
||||
assert(rv != CommonIt(it));
|
||||
if (!std::is_constant_evaluated()) {
|
||||
assert(rv == std::next(CommonIt(it)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<cpp17_input_iterator<int*>>();
|
||||
test<forward_iterator<int*>>();
|
||||
test<bidirectional_iterator<int*>>();
|
||||
test<random_access_iterator<int*>>();
|
||||
test<contiguous_iterator<int*>>();
|
||||
test<int*>();
|
||||
test<const int*>();
|
||||
|
||||
static_assert(test<cpp17_input_iterator<int*>>());
|
||||
static_assert(test<forward_iterator<int*>>());
|
||||
static_assert(test<bidirectional_iterator<int*>>());
|
||||
static_assert(test<random_access_iterator<int*>>());
|
||||
static_assert(test<contiguous_iterator<int*>>());
|
||||
static_assert(test<int*>());
|
||||
static_assert(test<const int*>());
|
||||
|
||||
return 0;
|
||||
}
|
@ -15,35 +15,79 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
struct IterMovingIt {
|
||||
using value_type = int;
|
||||
using difference_type = int;
|
||||
explicit IterMovingIt() = default;
|
||||
IterMovingIt(const IterMovingIt&); // copyable, but this test shouldn't make copies
|
||||
IterMovingIt(IterMovingIt&&) = default;
|
||||
IterMovingIt& operator=(const IterMovingIt&);
|
||||
int& operator*() const;
|
||||
constexpr IterMovingIt& operator++() { return *this; }
|
||||
IterMovingIt operator++(int);
|
||||
friend constexpr int iter_move(const IterMovingIt&) {
|
||||
return 42;
|
||||
}
|
||||
bool operator==(std::default_sentinel_t) const;
|
||||
};
|
||||
static_assert(std::input_iterator<IterMovingIt>);
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
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&&);
|
||||
using It = int*;
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
int a[] = {1, 2, 3};
|
||||
CommonIt it = CommonIt(It(a));
|
||||
ASSERT_NOEXCEPT(iter_move(it));
|
||||
ASSERT_NOEXCEPT(std::ranges::iter_move(it));
|
||||
ASSERT_SAME_TYPE(decltype(iter_move(it)), int&&);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(it)), int&&);
|
||||
assert(iter_move(it) == 1);
|
||||
if (!std::is_constant_evaluated()) {
|
||||
++it;
|
||||
assert(iter_move(it) == 2);
|
||||
}
|
||||
}
|
||||
{
|
||||
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&&);
|
||||
using It = const int*;
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
int a[] = {1, 2, 3};
|
||||
CommonIt it = CommonIt(It(a));
|
||||
ASSERT_NOEXCEPT(iter_move(it));
|
||||
ASSERT_NOEXCEPT(std::ranges::iter_move(it));
|
||||
ASSERT_SAME_TYPE(decltype(iter_move(it)), const int&&);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(it)), const int&&);
|
||||
assert(iter_move(it) == 1);
|
||||
if (!std::is_constant_evaluated()) {
|
||||
++it;
|
||||
assert(iter_move(it) == 2);
|
||||
}
|
||||
}
|
||||
{
|
||||
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&&);
|
||||
using It = IterMovingIt;
|
||||
using CommonIt = std::common_iterator<It, std::default_sentinel_t>;
|
||||
CommonIt it = CommonIt(It());
|
||||
ASSERT_NOT_NOEXCEPT(iter_move(it));
|
||||
ASSERT_NOT_NOEXCEPT(std::ranges::iter_move(it));
|
||||
ASSERT_SAME_TYPE(decltype(iter_move(it)), int);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(it)), int);
|
||||
assert(iter_move(it) == 42);
|
||||
if (!std::is_constant_evaluated()) {
|
||||
++it;
|
||||
assert(iter_move(it) == 42);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -10,55 +10,114 @@
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
|
||||
// template<indirectly_swappable<I> I2, class S2>
|
||||
// friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
|
||||
// friend constexpr 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 <type_traits>
|
||||
|
||||
#include "test_iterators.h"
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
void test() {
|
||||
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
template<int K>
|
||||
struct IterSwappingIt {
|
||||
using value_type = int;
|
||||
using difference_type = int;
|
||||
constexpr explicit IterSwappingIt(int *swaps) : swaps_(swaps) {}
|
||||
IterSwappingIt(const IterSwappingIt&); // copyable, but this test shouldn't make copies
|
||||
IterSwappingIt(IterSwappingIt&&) = default;
|
||||
IterSwappingIt& operator=(const IterSwappingIt&);
|
||||
int& operator*() const;
|
||||
constexpr IterSwappingIt& operator++() { return *this; }
|
||||
IterSwappingIt operator++(int);
|
||||
|
||||
template<int L>
|
||||
friend constexpr int iter_swap(const IterSwappingIt<K>& lhs, const IterSwappingIt<L>& rhs) {
|
||||
*lhs.swaps_ += 10;
|
||||
*rhs.swaps_ += 1;
|
||||
return 42; // should be accepted but ignored
|
||||
}
|
||||
|
||||
bool operator==(std::default_sentinel_t) const;
|
||||
|
||||
int *swaps_ = nullptr;
|
||||
};
|
||||
static_assert(std::input_iterator<IterSwappingIt<0>>);
|
||||
static_assert(std::indirectly_swappable<IterSwappingIt<0>, IterSwappingIt<0>>);
|
||||
static_assert(std::indirectly_swappable<IterSwappingIt<0>, IterSwappingIt<1>>);
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
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);
|
||||
using It = int*;
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
static_assert(std::indirectly_swappable<CommonIt, CommonIt>);
|
||||
|
||||
int a[] = {1, 2, 3};
|
||||
CommonIt it = CommonIt(It(a));
|
||||
CommonIt jt = CommonIt(It(a+1));
|
||||
ASSERT_NOEXCEPT(iter_swap(it, jt));
|
||||
ASSERT_SAME_TYPE(decltype(iter_swap(it, jt)), void);
|
||||
iter_swap(it, jt);
|
||||
assert(a[0] == 2);
|
||||
assert(a[1] == 1);
|
||||
}
|
||||
{
|
||||
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);
|
||||
using It = const int*;
|
||||
using CommonIt = std::common_iterator<It, sentinel_wrapper<It>>;
|
||||
static_assert(!std::indirectly_swappable<CommonIt, CommonIt>);
|
||||
}
|
||||
{
|
||||
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);
|
||||
using It = IterSwappingIt<0>;
|
||||
using CommonIt = std::common_iterator<It, std::default_sentinel_t>;
|
||||
static_assert(std::indirectly_swappable<CommonIt, CommonIt>);
|
||||
|
||||
int iswaps = 100;
|
||||
int jswaps = 100;
|
||||
CommonIt it = CommonIt(It(&iswaps));
|
||||
CommonIt jt = CommonIt(It(&jswaps));
|
||||
ASSERT_NOT_NOEXCEPT(iter_swap(it, jt));
|
||||
ASSERT_SAME_TYPE(decltype(iter_swap(it, jt)), void);
|
||||
iter_swap(it, jt); // lvalue iterators
|
||||
assert(iswaps == 110);
|
||||
assert(jswaps == 101);
|
||||
iter_swap(CommonIt(It(&iswaps)), CommonIt(It(&jswaps))); // rvalue iterators
|
||||
assert(iswaps == 120);
|
||||
assert(jswaps == 102);
|
||||
std::ranges::iter_swap(it, jt);
|
||||
assert(iswaps == 130);
|
||||
assert(jswaps == 103);
|
||||
}
|
||||
{
|
||||
using It = IterSwappingIt<0>;
|
||||
using Jt = IterSwappingIt<1>;
|
||||
static_assert(std::indirectly_swappable<It, Jt>);
|
||||
using CommonIt = std::common_iterator<It, std::default_sentinel_t>;
|
||||
using CommonJt = std::common_iterator<Jt, std::default_sentinel_t>;
|
||||
static_assert(std::indirectly_swappable<CommonIt, CommonJt>);
|
||||
|
||||
int iswaps = 100;
|
||||
int jswaps = 100;
|
||||
CommonIt it = CommonIt(It(&iswaps));
|
||||
CommonJt jt = CommonJt(Jt(&jswaps));
|
||||
ASSERT_NOT_NOEXCEPT(iter_swap(it, jt));
|
||||
ASSERT_SAME_TYPE(decltype(iter_swap(it, jt)), void);
|
||||
iter_swap(it, jt); // lvalue iterators
|
||||
assert(iswaps == 110);
|
||||
assert(jswaps == 101);
|
||||
iter_swap(CommonIt(It(&iswaps)), CommonJt(Jt(&jswaps))); // rvalue iterators
|
||||
assert(iswaps == 120);
|
||||
assert(jswaps == 102);
|
||||
std::ranges::iter_swap(it, jt);
|
||||
assert(iswaps == 130);
|
||||
assert(jswaps == 103);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -157,32 +157,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -117,38 +117,6 @@ public:
|
||||
void operator,(T const &) = delete;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
non_default_constructible_iterator() = delete;
|
||||
|
||||
TEST_CONSTEXPR explicit non_default_constructible_iterator(It it) : it_(it) {}
|
||||
template <class U>
|
||||
TEST_CONSTEXPR non_default_constructible_iterator(const non_default_constructible_iterator<U>& u) : it_(u.it_) {}
|
||||
|
||||
TEST_CONSTEXPR reference operator*() const {return *it_;}
|
||||
TEST_CONSTEXPR 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) {return non_default_constructible_iterator(it_++);}
|
||||
|
||||
friend TEST_CONSTEXPR bool operator==(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) {return x.it_ == y.it_;}
|
||||
friend TEST_CONSTEXPR bool operator!=(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) {return x.it_ != y.it_;}
|
||||
|
||||
template <class T>
|
||||
void operator,(T const &) = delete;
|
||||
};
|
||||
|
||||
template <class It>
|
||||
class bidirectional_iterator
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user