| //===----------------------------------------------------------------------===// |
| // |
| // 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: !c++experimental |
| |
| // Iterator traits and member typedefs in join_view::<iterator>. |
| |
| #include <ranges> |
| |
| #include "test_iterators.h" |
| #include "test_macros.h" |
| #include "../types.h" |
| |
| template<class T> |
| struct ForwardView : std::ranges::view_base { |
| forward_iterator<T*> begin() const; |
| sentinel_wrapper<forward_iterator<T*>> end() const; |
| }; |
| |
| template<class T> |
| struct InputView : std::ranges::view_base { |
| cpp17_input_iterator<T*> begin() const; |
| sentinel_wrapper<cpp17_input_iterator<T*>> end() const; |
| }; |
| |
| template <class T, class V> |
| struct diff_type_iter { |
| using iterator_category = std::input_iterator_tag; |
| using value_type = V; |
| using difference_type = T; |
| |
| V& operator*() const; |
| diff_type_iter& operator++(); |
| void operator++(int); |
| friend constexpr bool operator==(diff_type_iter, diff_type_iter) = default; |
| }; |
| |
| template <class T, class V = int> |
| struct DiffTypeRange : std::ranges::view_base { |
| diff_type_iter<T, V> begin() const; |
| diff_type_iter<T, V> end() const; |
| }; |
| |
| template<class T> |
| concept HasIterCategory = requires { typename T::iterator_category; }; |
| |
| void test() { |
| { |
| int buffer[4][4]; |
| std::ranges::join_view jv(buffer); |
| using Iter = std::ranges::iterator_t<decltype(jv)>; |
| |
| static_assert(std::is_same_v<Iter::iterator_concept, std::bidirectional_iterator_tag>); |
| static_assert(std::is_same_v<Iter::iterator_category, std::bidirectional_iterator_tag>); |
| static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); |
| static_assert(std::is_same_v<Iter::value_type, int>); |
| static_assert(HasIterCategory<Iter>); |
| } |
| |
| { |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<ForwardView<ForwardView<int>>>>; |
| |
| static_assert(std::is_same_v<Iter::iterator_concept, std::forward_iterator_tag>); |
| static_assert(std::is_same_v<Iter::iterator_category, std::forward_iterator_tag>); |
| static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); |
| static_assert(std::is_same_v<Iter::value_type, int>); |
| static_assert(HasIterCategory<Iter>); |
| } |
| |
| { |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<InputView<InputView<int>>>>; |
| |
| static_assert(std::is_same_v<Iter::iterator_concept, std::input_iterator_tag>); |
| static_assert(!HasIterCategory<Iter>); |
| static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); |
| static_assert(std::is_same_v<Iter::value_type, int>); |
| } |
| |
| { |
| // LWG3535 `join_view::iterator::iterator_category` and `::iterator_concept` lie |
| // Bidi non common inner range should not have bidirectional_iterator_tag |
| using Base = BidiCommonOuter<BidiNonCommonInner>; |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<Base>>; |
| static_assert(std::is_same_v<Iter::iterator_concept, std::forward_iterator_tag>); |
| static_assert(std::is_same_v<Iter::iterator_category, std::forward_iterator_tag>); |
| static_assert(HasIterCategory<Iter>); |
| static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>); |
| static_assert(std::is_same_v<Iter::value_type, int>); |
| } |
| |
| { |
| // !ref-is-glvalue |
| using Outer = InnerRValue<BidiCommonOuter<BidiCommonInner>>; |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<Outer>>; |
| static_assert(!HasIterCategory<Iter>); |
| static_assert(std::is_same_v<Iter::iterator_concept, std::input_iterator_tag>); |
| } |
| |
| { |
| // value_type == inner's value_type |
| using Inner = IterMoveSwapAwareView; |
| using InnerValue = std::ranges::range_value_t<Inner>; |
| using InnerReference = std::ranges::range_reference_t<Inner>; |
| static_assert(!std::is_same_v<InnerValue, std::remove_cvref<InnerReference>>); |
| |
| using Outer = BidiCommonOuter<Inner>; |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<Outer>>; |
| static_assert(std::is_same_v<InnerValue, std::pair<int, int>>); |
| static_assert(std::is_same_v<Iter::value_type, std::pair<int, int>>); |
| } |
| |
| { |
| // difference_type |
| using Inner = DiffTypeRange<std::intptr_t>; |
| using Outer = DiffTypeRange<std::ptrdiff_t, Inner>; |
| using Iter = std::ranges::iterator_t<std::ranges::join_view<Outer>>; |
| static_assert(std::is_same_v<Iter::difference_type, std::common_type_t<std::intptr_t, std::ptrdiff_t>>); |
| } |
| } |