forked from OSchip/llvm-project
[libcxx][ranges] Add `ranges::join_view`.
Differential Revision: https://reviews.llvm.org/D107671
This commit is contained in:
parent
7b20e05c71
commit
df324bba5c
|
@ -140,7 +140,7 @@ Section,Description,Dependencies,Assignee,Complete
|
|||
`[range.transform] <http://wg21.link/range.transform>`_,`transform_view <https://llvm.org/D103056>`_,[range.all],Zoe Carver,✅
|
||||
`[range.iota] <http://wg21.link/range.iota>`_,iota_view,[range.all],Zoe Carver,✅
|
||||
`[range.take] <http://wg21.link/range.take>`_,take_view,[range.all],Zoe Carver,✅
|
||||
`[range.join] <http://wg21.link/range.join>`_,join_view,[range.all],Zoe Carver,In Progress
|
||||
`[range.join] <http://wg21.link/range.join>`_,join_view,[range.all],Zoe Carver,✅
|
||||
`[range.empty] <http://wg21.link/range.empty>`_,`empty_view <https://llvm.org/D103208>`_,[view.interface],Zoe Carver,✅
|
||||
`[range.single] <http://wg21.link/range.single>`_,single_view,[view.interface],Zoe Carver,✅
|
||||
`[range.split] <http://wg21.link/range.split>`_,split_view,[range.all],Zoe Carver,In Progress
|
||||
|
|
|
|
@ -224,6 +224,7 @@ set(files
|
|||
__ranges/enable_borrowed_range.h
|
||||
__ranges/enable_view.h
|
||||
__ranges/iota_view.h
|
||||
__ranges/join_view.h
|
||||
__ranges/non_propagating_cache.h
|
||||
__ranges/ref_view.h
|
||||
__ranges/reverse_view.h
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
// -*- 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___RANGES_JOIN_VIEW_H
|
||||
#define _LIBCPP___RANGES_JOIN_VIEW_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__ranges/access.h>
|
||||
#include <__ranges/all.h>
|
||||
#include <__ranges/concepts.h>
|
||||
#include <__ranges/non_propagating_cache.h>
|
||||
#include <__ranges/ref_view.h>
|
||||
#include <__ranges/subrange.h>
|
||||
#include <__ranges/view_interface.h>
|
||||
#include <__utility/declval.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
namespace ranges {
|
||||
template<class>
|
||||
struct __join_view_iterator_category {};
|
||||
|
||||
template<class _View>
|
||||
requires is_reference_v<range_reference_t<_View>> &&
|
||||
forward_range<_View> &&
|
||||
forward_range<range_reference_t<_View>>
|
||||
struct __join_view_iterator_category<_View> {
|
||||
using _OuterC = typename iterator_traits<iterator_t<_View>>::iterator_category;
|
||||
using _InnerC = typename iterator_traits<iterator_t<range_reference_t<_View>>>::iterator_category;
|
||||
|
||||
using iterator_category = _If<
|
||||
derived_from<_OuterC, bidirectional_iterator_tag> && derived_from<_InnerC, bidirectional_iterator_tag>,
|
||||
bidirectional_iterator_tag,
|
||||
_If<
|
||||
derived_from<_OuterC, forward_iterator_tag> && derived_from<_InnerC, forward_iterator_tag>,
|
||||
forward_iterator_tag,
|
||||
input_iterator_tag
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
template<input_range _View>
|
||||
requires view<_View> && input_range<range_reference_t<_View>>
|
||||
class join_view
|
||||
: public view_interface<join_view<_View>> {
|
||||
private:
|
||||
using _InnerRange = range_reference_t<_View>;
|
||||
|
||||
template<bool> struct __iterator;
|
||||
template<bool> struct __sentinel;
|
||||
|
||||
static constexpr bool _UseCache = !is_reference_v<_InnerRange>;
|
||||
using _Cache = _If<_UseCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>;
|
||||
[[no_unique_address]] _Cache __cache_;
|
||||
_View __base_ = _View(); // TODO: [[no_unique_address]] makes clang crash! File a bug :)
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
join_view() requires default_initializable<_View> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr explicit join_view(_View __base)
|
||||
: __base_(_VSTD::move(__base)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr _View base() && { return _VSTD::move(__base_); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr auto begin() {
|
||||
constexpr bool __use_const = __simple_view<_View> &&
|
||||
is_reference_v<range_reference_t<_View>>;
|
||||
return __iterator<__use_const>{*this, ranges::begin(__base_)};
|
||||
}
|
||||
|
||||
template<class _V2 = _View>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr auto begin() const
|
||||
requires input_range<const _V2> &&
|
||||
is_reference_v<range_reference_t<const _V2>>
|
||||
{
|
||||
return __iterator<true>{*this, ranges::begin(__base_)};
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr auto end() {
|
||||
if constexpr (forward_range<_View> &&
|
||||
is_reference_v<_InnerRange> &&
|
||||
forward_range<_InnerRange> &&
|
||||
common_range<_View> &&
|
||||
common_range<_InnerRange>)
|
||||
return __iterator<__simple_view<_View>>{*this, ranges::end(__base_)};
|
||||
else
|
||||
return __sentinel<__simple_view<_View>>{*this};
|
||||
}
|
||||
|
||||
template<class _V2 = _View>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr auto end() const
|
||||
requires input_range<const _V2> &&
|
||||
is_reference_v<range_reference_t<const _V2>>
|
||||
{
|
||||
using _ConstInnerRange = range_reference_t<const _View>;
|
||||
if constexpr (forward_range<const _View> &&
|
||||
is_reference_v<_ConstInnerRange> &&
|
||||
forward_range<_ConstInnerRange> &&
|
||||
common_range<const _View> &&
|
||||
common_range<_ConstInnerRange>) {
|
||||
return __iterator<true>{*this, ranges::end(__base_)};
|
||||
} else {
|
||||
return __sentinel<true>{*this};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<input_range _View>
|
||||
requires view<_View> && input_range<range_reference_t<_View>>
|
||||
template<bool _Const> struct join_view<_View>::__sentinel {
|
||||
template<bool> friend struct __sentinel;
|
||||
|
||||
private:
|
||||
using _Parent = __maybe_const<_Const, join_view>;
|
||||
using _Base = __maybe_const<_Const, _View>;
|
||||
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
__sentinel() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr explicit __sentinel(_Parent& __parent)
|
||||
: __end_(ranges::end(__parent.__base_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __sentinel(__sentinel<!_Const> __s)
|
||||
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
|
||||
: __end_(_VSTD::move(__s.__end_)) {}
|
||||
|
||||
template<bool _OtherConst>
|
||||
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
|
||||
return __x.__outer_ == __y.__end_;
|
||||
}
|
||||
};
|
||||
|
||||
template<input_range _View>
|
||||
requires view<_View> && input_range<range_reference_t<_View>>
|
||||
template<bool _Const> struct join_view<_View>::__iterator
|
||||
: public __join_view_iterator_category<__maybe_const<_Const, _View>> {
|
||||
|
||||
template<bool> friend struct __iterator;
|
||||
|
||||
private:
|
||||
using _Parent = __maybe_const<_Const, join_view>;
|
||||
using _Base = __maybe_const<_Const, _View>;
|
||||
using _Outer = iterator_t<_Base>;
|
||||
using _Inner = iterator_t<range_reference_t<_Base>>;
|
||||
|
||||
static constexpr bool __ref_is_glvalue = is_reference_v<range_reference_t<_Base>>;
|
||||
|
||||
public:
|
||||
_Outer __outer_ = _Outer();
|
||||
|
||||
private:
|
||||
optional<_Inner> __inner_;
|
||||
_Parent *__parent_ = nullptr;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr void __satisfy() {
|
||||
for (; __outer_ != ranges::end(__parent_->__base_); ++__outer_) {
|
||||
auto&& __inner = [&]() -> auto&& {
|
||||
if constexpr (__ref_is_glvalue)
|
||||
return *__outer_;
|
||||
else
|
||||
return __parent_->__cache_.__emplace_deref(__outer_);
|
||||
}();
|
||||
__inner_ = ranges::begin(__inner);
|
||||
if (*__inner_ != ranges::end(__inner))
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (__ref_is_glvalue)
|
||||
__inner_.reset();
|
||||
}
|
||||
|
||||
public:
|
||||
using iterator_concept = _If<
|
||||
__ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>>,
|
||||
bidirectional_iterator_tag,
|
||||
_If<
|
||||
__ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>>,
|
||||
forward_iterator_tag,
|
||||
input_iterator_tag
|
||||
>
|
||||
>;
|
||||
|
||||
using value_type = range_value_t<range_reference_t<_Base>>;
|
||||
|
||||
using difference_type = common_type_t<
|
||||
range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
__iterator() requires default_initializable<_Outer> = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator(_Parent& __parent, _Outer __outer)
|
||||
: __outer_(_VSTD::move(__outer))
|
||||
, __parent_(_VSTD::addressof(__parent)) {
|
||||
__satisfy();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator(__iterator<!_Const> __i)
|
||||
requires _Const &&
|
||||
convertible_to<iterator_t<_View>, _Outer> &&
|
||||
convertible_to<iterator_t<_InnerRange>, _Inner>
|
||||
: __outer_(_VSTD::move(__i.__outer_))
|
||||
, __inner_(_VSTD::move(__i.__inner_))
|
||||
, __parent_(__i.__parent_) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr decltype(auto) operator*() const {
|
||||
return **__inner_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr _Inner operator->() const
|
||||
requires __has_arrow<_Inner> && copyable<_Inner>
|
||||
{
|
||||
return *__inner_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator& operator++() {
|
||||
auto&& __inner = [&]() -> auto&& {
|
||||
if constexpr (__ref_is_glvalue)
|
||||
return *__outer_;
|
||||
else
|
||||
return *__parent_->__cache_;
|
||||
}();
|
||||
if (++*__inner_ == ranges::end(__inner)) {
|
||||
++__outer_;
|
||||
__satisfy();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr void operator++(int) {
|
||||
++*this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator operator++(int)
|
||||
requires __ref_is_glvalue &&
|
||||
forward_range<_Base> &&
|
||||
forward_range<range_reference_t<_Base>>
|
||||
{
|
||||
auto __tmp = *this;
|
||||
++*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator& operator--()
|
||||
requires __ref_is_glvalue &&
|
||||
bidirectional_range<_Base> &&
|
||||
bidirectional_range<range_reference_t<_Base>> &&
|
||||
common_range<range_reference_t<_Base>>
|
||||
{
|
||||
if (__outer_ == ranges::end(__parent_->__base_))
|
||||
__inner_ = ranges::end(*--__outer_);
|
||||
|
||||
// Skip empty inner ranges when going backwards.
|
||||
while (*__inner_ == ranges::begin(*__outer_)) {
|
||||
__inner_ = ranges::end(*--__outer_);
|
||||
}
|
||||
|
||||
--*__inner_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr __iterator operator--(int)
|
||||
requires __ref_is_glvalue &&
|
||||
bidirectional_range<_Base> &&
|
||||
bidirectional_range<range_reference_t<_Base>> &&
|
||||
common_range<range_reference_t<_Base>>
|
||||
{
|
||||
auto __tmp = *this;
|
||||
--*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
|
||||
requires __ref_is_glvalue &&
|
||||
equality_comparable<iterator_t<_Base>> &&
|
||||
equality_comparable<iterator_t<range_reference_t<_Base>>>
|
||||
{
|
||||
return __x.__outer_ == __y.__outer_ && __x.__inner_ == __y.__inner_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
friend constexpr decltype(auto) iter_move(const __iterator& __i)
|
||||
noexcept(noexcept(ranges::iter_move(*__i.__inner_)))
|
||||
{
|
||||
return ranges::iter_move(*__i.__inner_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y)
|
||||
noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_)))
|
||||
requires indirectly_swappable<_Inner>
|
||||
{
|
||||
return ranges::iter_swap(*__x.__inner_, *__y.__inner_);
|
||||
}
|
||||
};
|
||||
|
||||
template<class _Range>
|
||||
explicit join_view(_Range&&) -> join_view<views::all_t<_Range>>;
|
||||
|
||||
} // namespace ranges
|
||||
|
||||
#undef _CONSTEXPR_TERNARY
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___RANGES_JOIN_VIEW_H
|
|
@ -85,6 +85,14 @@ namespace ranges {
|
|||
constexpr void __set(_Tp const& __value) { __value_.emplace(__value); }
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr void __set(_Tp&& __value) { __value_.emplace(_VSTD::move(__value)); }
|
||||
|
||||
template<class _Other>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr _Tp& __emplace_deref(const _Other& __value) {
|
||||
__value_.reset();
|
||||
__value_.emplace(*__value);
|
||||
return *__value_;
|
||||
}
|
||||
};
|
||||
|
||||
struct __empty_cache { };
|
||||
|
|
|
@ -659,6 +659,7 @@ module std [system] {
|
|||
module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" }
|
||||
module enable_view { private header "__ranges/enable_view.h" }
|
||||
module iota_view { private header "__ranges/iota_view.h" }
|
||||
module join_view { private header "__ranges/join_view.h" }
|
||||
module non_propagating_cache { private header "__ranges/non_propagating_cache.h" }
|
||||
module ref_view { private header "__ranges/ref_view.h" }
|
||||
module reverse_view { private header "__ranges/reverse_view.h" }
|
||||
|
|
|
@ -184,6 +184,11 @@ namespace std::ranges {
|
|||
|
||||
template<class W, class Bound>
|
||||
inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
|
||||
|
||||
// [range.join], join view
|
||||
template<input_range V>
|
||||
requires view<V> && input_range<range_reference_t<V>>
|
||||
class join_view;
|
||||
}
|
||||
|
||||
*/
|
||||
|
@ -207,6 +212,7 @@ namespace std::ranges {
|
|||
#include <__ranges/enable_borrowed_range.h>
|
||||
#include <__ranges/enable_view.h>
|
||||
#include <__ranges/iota_view.h>
|
||||
#include <__ranges/join_view.h>
|
||||
#include <__ranges/ref_view.h>
|
||||
#include <__ranges/reverse_view.h>
|
||||
#include <__ranges/take_view.h>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__ranges/join_view.h'}}
|
||||
#include <__ranges/join_view.h>
|
|
@ -0,0 +1,62 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr V base() const& requires copy_constructible<V>;
|
||||
// constexpr V base() &&;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
constexpr bool hasLValueQualifiedBase(auto&& view) {
|
||||
return requires { view.base(); };
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(std::move(jv).base().ptr_ == children);
|
||||
|
||||
static_assert(!hasLValueQualifiedBase(jv));
|
||||
ASSERT_SAME_TYPE(decltype(std::move(jv).base()), ParentView<ChildView>);
|
||||
}
|
||||
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(jv.base().base() == buffer + 0);
|
||||
|
||||
static_assert(hasLValueQualifiedBase(jv));
|
||||
ASSERT_SAME_TYPE(decltype(jv.base()), std::ranges::ref_view<int [4][4]>);
|
||||
}
|
||||
|
||||
{
|
||||
const std::ranges::join_view jv(buffer);
|
||||
assert(jv.base().base() == buffer + 0);
|
||||
|
||||
static_assert(hasLValueQualifiedBase(jv));
|
||||
ASSERT_SAME_TYPE(decltype(jv.base()), std::ranges::ref_view<int [4][4]>);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr auto begin();
|
||||
// constexpr auto begin() const;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
// Parent is empty.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
std::ranges::join_view jv(ParentView(children, 0));
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// Parent size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0])};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
// Parent and child size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
// Parent size is one child is empty
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// Has all empty children.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// First child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
// Last child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
|
||||
{
|
||||
const std::ranges::join_view jv(buffer);
|
||||
assert(*jv.begin() == 1111);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// template<class R>
|
||||
// explicit join_view(R&&) -> join_view<views::all_t<R>>;
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template<class T>
|
||||
struct View : std::ranges::view_base {
|
||||
// All friends here are defined to prevent GCC warnings.
|
||||
friend T* begin(View&) { return nullptr; }
|
||||
friend T* begin(View const&) { return nullptr; }
|
||||
friend sentinel_wrapper<T*> end(View&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
friend sentinel_wrapper<T*> end(View const&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct Range {
|
||||
friend T* begin(Range&) { return nullptr; }
|
||||
friend T* begin(Range const&) { return nullptr; }
|
||||
friend sentinel_wrapper<T*> end(Range&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
friend sentinel_wrapper<T*> end(Range const&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct BorrowedRange {
|
||||
friend T* begin(BorrowedRange&) { return nullptr; }
|
||||
friend T* begin(BorrowedRange const&) { return nullptr; }
|
||||
friend sentinel_wrapper<T*> end(BorrowedRange&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
friend sentinel_wrapper<T*> end(BorrowedRange const&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
};
|
||||
|
||||
template<>
|
||||
inline constexpr bool std::ranges::enable_borrowed_range<BorrowedRange<BorrowedRange<int>>> = true;
|
||||
|
||||
void testCTAD() {
|
||||
View<View<int>> v;
|
||||
Range<Range<int>> r;
|
||||
BorrowedRange<BorrowedRange<int>> br;
|
||||
|
||||
static_assert(std::same_as<
|
||||
decltype(std::ranges::join_view(v)),
|
||||
std::ranges::join_view<View<View<int>>>
|
||||
>);
|
||||
static_assert(std::same_as<
|
||||
decltype(std::ranges::join_view(r)),
|
||||
std::ranges::join_view<std::ranges::ref_view<Range<Range<int>>>>
|
||||
>);
|
||||
// std::ranges::join_view(std::move(r)) invalid. RValue range must be borrowed.
|
||||
static_assert(std::same_as<
|
||||
decltype(std::ranges::join_view(br)),
|
||||
std::ranges::join_view<std::ranges::ref_view<BorrowedRange<BorrowedRange<int>>>>
|
||||
>);
|
||||
static_assert(std::same_as<
|
||||
decltype(std::ranges::join_view(std::move(br))),
|
||||
std::ranges::join_view<std::ranges::subrange<BorrowedRange<int> *,
|
||||
sentinel_wrapper<BorrowedRange<int> *>,
|
||||
std::ranges::subrange_kind::unsized>>
|
||||
>);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// template<class R>
|
||||
// explicit join_view(R&&) -> join_view<views::all_t<R>>;
|
||||
|
||||
// Tests that the deduction guide is explicit.
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
template<class T>
|
||||
struct Range {
|
||||
friend T* begin(Range&) { return nullptr; }
|
||||
friend T* begin(Range const&) { return nullptr; }
|
||||
friend sentinel_wrapper<T*> end(Range&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
friend sentinel_wrapper<T*> end(Range const&) { return sentinel_wrapper<T*>(nullptr); }
|
||||
};
|
||||
|
||||
void testExplicitCTAD() {
|
||||
Range<Range<int>> r;
|
||||
std::ranges::join_view v = r; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'join_view'}}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr explicit join_view(V base);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView{children});
|
||||
assert(std::move(jv).base().ptr_ == children);
|
||||
}
|
||||
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(jv.base().base() == buffer + 0);
|
||||
}
|
||||
|
||||
{
|
||||
// Test explicitness.
|
||||
static_assert( std::is_constructible_v<std::ranges::join_view<ParentView<ChildView>>, ParentView<ChildView>>);
|
||||
static_assert(!std::is_convertible_v<std::ranges::join_view<ParentView<ChildView>>, ParentView<ChildView>>);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// join_view() requires default_initializable<V> = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
constexpr bool test() {
|
||||
std::ranges::join_view<ParentView<ChildView>> jv;
|
||||
assert(std::move(jv).base().ptr_ == globalChildren);
|
||||
|
||||
static_assert( std::default_initializable<std::ranges::join_view<ParentView<ChildView>>>);
|
||||
static_assert(!std::default_initializable<std::ranges::join_view<CopyableParent>>);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr auto end();
|
||||
// constexpr auto end() const;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
// Non const common, forward range.
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
static_assert(std::same_as<decltype(jv.end()), decltype(jv.begin())>);
|
||||
}
|
||||
|
||||
// Non const not common, input range.
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
static_assert(!std::same_as<decltype(jv.end()), decltype(jv.begin())>);
|
||||
}
|
||||
|
||||
// Const common, forward range.
|
||||
{
|
||||
const std::ranges::join_view jv(buffer);
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
static_assert(std::same_as<decltype(jv.end()), decltype(jv.begin())>);
|
||||
}
|
||||
|
||||
// Const not common, input range.
|
||||
{
|
||||
static_assert(std::is_reference_v<std::ranges::range_reference_t<const CopyableParent>>);
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
const auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
static_assert(!std::same_as<decltype(jv.end()), decltype(jv.begin())>);
|
||||
}
|
||||
|
||||
// Has some empty children.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 5));
|
||||
}
|
||||
// Parent is empty.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
std::ranges::join_view jv(ParentView(children, 0));
|
||||
assert(jv.end() == jv.begin());
|
||||
}
|
||||
// Parent size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0])};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 4));
|
||||
}
|
||||
// Parent and child size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0], 1)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(jv.end() == std::ranges::next(jv.begin()));
|
||||
}
|
||||
// Parent size is one child is empty
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer[0], 0)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(jv.end() == jv.begin());
|
||||
}
|
||||
// Has all empty children.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == jv.begin());
|
||||
}
|
||||
// First child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 4));
|
||||
}
|
||||
// Last child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4), CopyableChild(buffer[3], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 12));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// General tests for join_view. This file does not test anything specifically.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
template<class R, class I>
|
||||
bool isEqual(R &r, I i) {
|
||||
for (auto e : r)
|
||||
if (e != *i++)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
{
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
int *flattened = reinterpret_cast<int*>(buffer);
|
||||
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(isEqual(jv, flattened));
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<std::string> vec = {"Hello", ",", " ", "World", "!"};
|
||||
std::string check = "Hello, World!";
|
||||
std::ranges::join_view jv(vec);
|
||||
assert(isEqual(jv, check.begin()));
|
||||
}
|
||||
|
||||
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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr InnerIter operator->() const
|
||||
// requires has-arrow<InnerIter> && copyable<InnerIter>;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
Box buffer[4][4] = {{{1111}, {2222}, {3333}, {4444}}, {{555}, {666}, {777}, {888}}, {{99}, {1010}, {1111}, {1212}}, {{13}, {14}, {15}, {16}}};
|
||||
|
||||
{
|
||||
// Copyable input iterator with arrow.
|
||||
ValueView<Box> children[4] = {ValueView(buffer[0]), ValueView(buffer[1]), ValueView(buffer[2]), ValueView(buffer[3])};
|
||||
std::ranges::join_view jv(ValueView<ValueView<Box>>{children});
|
||||
assert(jv.begin()->x == 1111);
|
||||
}
|
||||
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(jv.begin()->x == 1111);
|
||||
}
|
||||
|
||||
{
|
||||
const std::ranges::join_view jv(buffer);
|
||||
assert(jv.begin()->x == 1111);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// iterator() requires default_initializable<OuterIter> = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
template<class T>
|
||||
struct DefaultCtorParent : std::ranges::view_base {
|
||||
T *ptr_;
|
||||
constexpr DefaultCtorParent(T *ptr) : ptr_(ptr) {}
|
||||
|
||||
constexpr cpp17_input_iterator<T *> begin() { return cpp17_input_iterator<T *>(ptr_); }
|
||||
constexpr cpp17_input_iterator<const T *> begin() const { return cpp17_input_iterator<const T *>(ptr_); }
|
||||
constexpr T *end() { return ptr_ + 4; }
|
||||
constexpr const T *end() const { return ptr_ + 4; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr bool operator==(const cpp17_input_iterator<T*> &lhs, const T *rhs) { return lhs.base() == rhs; }
|
||||
template<class T>
|
||||
constexpr bool operator==(const T *lhs, const cpp17_input_iterator<T*> &rhs) { return rhs.base() == lhs; }
|
||||
|
||||
constexpr bool test() {
|
||||
using Base = DefaultCtorParent<ChildView>;
|
||||
// Note, only the outer iterator is default_initializable:
|
||||
static_assert( std::default_initializable<std::ranges::iterator_t<Base>>);
|
||||
static_assert(!std::default_initializable<std::ranges::iterator_t<std::ranges::range_reference_t<Base>>>);
|
||||
|
||||
std::ranges::iterator_t<std::ranges::join_view<Base>> iter1;
|
||||
(void) iter1;
|
||||
|
||||
static_assert(!std::default_initializable<std::ranges::iterator_t<std::ranges::join_view<ParentView<ChildView>>>>);
|
||||
|
||||
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
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr iterator(iterator<!Const> i);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
std::ranges::join_view jv(CopyableParent{children});
|
||||
auto iter1 = jv.begin();
|
||||
std::ranges::iterator_t<const decltype(jv)> iter2 = iter1;
|
||||
assert(iter1 == iter2);
|
||||
|
||||
// We cannot create a non-const iterator from a const iterator.
|
||||
static_assert(!std::constructible_from<decltype(iter1), decltype(iter2)>);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr iterator(Parent& parent, OuterIter outer);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
CopyableParent parent{children};
|
||||
std::ranges::join_view jv(parent);
|
||||
std::ranges::iterator_t<decltype(jv)> iter(jv, std::ranges::begin(parent));
|
||||
assert(*iter == 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr iterator& operator--();
|
||||
// constexpr iterator operator--(int);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
// outer == ranges::end
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = std::next(jv.begin(), 16);
|
||||
for (int i = 16; i != 0; --i) {
|
||||
assert(*--iter == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
// outer == ranges::end
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = std::next(jv.begin(), 13);
|
||||
for (int i = 13; i != 0; --i) {
|
||||
assert(*--iter == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
// outer != ranges::end
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = std::next(jv.begin(), 12);
|
||||
for (int i = 12; i != 0; --i) {
|
||||
assert(*--iter == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
// outer != ranges::end
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = std::next(jv.begin());
|
||||
for (int i = 1; i != 0; --i) {
|
||||
assert(*--iter == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
int small[2][1] = {{1}, {2}};
|
||||
std::ranges::join_view jv(small);
|
||||
auto iter = std::next(jv.begin(), 2);
|
||||
for (int i = 2; i != 0; --i) {
|
||||
assert(*--iter == i);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// friend constexpr bool operator==(const iterator& x, const iterator& y);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter1 = jv.begin();
|
||||
auto iter2 = jv.begin();
|
||||
assert(iter1 == iter2);
|
||||
iter1++;
|
||||
assert(iter1 != iter2);
|
||||
iter2++;
|
||||
assert(iter1 == iter2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr iterator& operator++();
|
||||
// constexpr void operator++(int);
|
||||
// constexpr iterator operator++(int);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
// This way if we read past end we'll catch the error.
|
||||
int buffer1[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
|
||||
int dummy = 42;
|
||||
(void) dummy;
|
||||
int buffer2[2][4] = {{9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
// operator++(int);
|
||||
{
|
||||
std::ranges::join_view jv(buffer1);
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 9; ++i) {
|
||||
assert(*iter++ == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
|
||||
std::ranges::join_view jv(ValueView<ValueView<int>>{children});
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 17; ++i) {
|
||||
assert(*iter == i);
|
||||
iter++;
|
||||
}
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(iter++), void);
|
||||
}
|
||||
{
|
||||
std::ranges::join_view jv(buffer1);
|
||||
auto iter = std::next(jv.begin(), 7);
|
||||
assert(*iter++ == 8);
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
{
|
||||
int small[2][1] = {{1}, {2}};
|
||||
std::ranges::join_view jv(small);
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 3; ++i) {
|
||||
assert(*iter++ == i);
|
||||
}
|
||||
}
|
||||
// Has some empty children.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 1), CopyableChild(buffer2[1], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
auto iter = jv.begin();
|
||||
assert(*iter == 1); iter++;
|
||||
assert(*iter == 2); iter++;
|
||||
assert(*iter == 3); iter++;
|
||||
assert(*iter == 4); iter++;
|
||||
assert(*iter == 9); iter++;
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
// Parent is empty.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer1[0]), CopyableChild(buffer1[1]), CopyableChild(buffer2[0]), CopyableChild(buffer2[1])};
|
||||
std::ranges::join_view jv(ParentView(children, 0));
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// Parent size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer1[0])};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
auto iter = jv.begin();
|
||||
assert(*iter == 1); iter++;
|
||||
assert(*iter == 2); iter++;
|
||||
assert(*iter == 3); iter++;
|
||||
assert(*iter == 4); iter++;
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
// Parent and child size is one.
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer1[0], 1)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
auto iter = jv.begin();
|
||||
assert(*iter == 1); iter++;
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
// Parent size is one child is empty
|
||||
{
|
||||
CopyableChild children[1] = {CopyableChild(buffer1[0], 0)};
|
||||
std::ranges::join_view jv(ParentView(children, 1));
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// Has all empty children.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer1[0], 0), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 0), CopyableChild(buffer2[1], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.begin() == jv.end());
|
||||
}
|
||||
// First child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 0), CopyableChild(buffer2[0], 0), CopyableChild(buffer2[1], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
auto iter = jv.begin();
|
||||
assert(*iter == 1); iter++;
|
||||
assert(*iter == 2); iter++;
|
||||
assert(*iter == 3); iter++;
|
||||
assert(*iter == 4); iter++;
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
// Last child is empty, others are not.
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer1[0], 4), CopyableChild(buffer1[1], 4), CopyableChild(buffer2[0], 4), CopyableChild(buffer2[1], 0)};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 13; ++i) {
|
||||
assert(*iter == i);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
// operator++();
|
||||
{
|
||||
std::ranges::join_view jv(buffer1);
|
||||
auto iter = jv.begin();
|
||||
for (int i = 2; i < 9; ++i) {
|
||||
assert(*++iter == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
|
||||
std::ranges::join_view jv(ValueView<ValueView<int>>{children});
|
||||
auto iter = jv.begin();
|
||||
for (int i = 2; i < 17; ++i) {
|
||||
assert(*++iter == i);
|
||||
}
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(++iter), decltype(iter)&);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// friend constexpr decltype(auto) iter_move(const iterator& i);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
std::ranges::join_view jv(buffer);
|
||||
assert(std::ranges::iter_move(jv.begin()) == 1);
|
||||
ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(jv.begin())), int&&);
|
||||
|
||||
static_assert(noexcept(std::ranges::iter_move(std::declval<decltype(jv.begin())>())));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// friend constexpr void iter_swap(const iterator& x, const iterator& y);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter1 = jv.begin();
|
||||
auto iter2 = std::next(jv.begin());
|
||||
assert(*iter1 == 1);
|
||||
assert(*iter2 == 2);
|
||||
std::ranges::swap(iter1, iter2);
|
||||
assert(*iter1 == 2);
|
||||
assert(*iter2 == 1);
|
||||
|
||||
static_assert(noexcept(std::ranges::iter_swap(iter1, iter2)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// 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 {
|
||||
friend forward_iterator<T*> begin(ForwardView&) { return forward_iterator<T*>(nullptr); }
|
||||
friend forward_iterator<T*> begin(ForwardView const&) { return forward_iterator<T*>(nullptr); }
|
||||
friend forward_iterator<T*> end(ForwardView&) { return forward_iterator<T*>(nullptr); }
|
||||
friend forward_iterator<T*> end(ForwardView const&) { return forward_iterator<T*>(nullptr); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct InputView : std::ranges::view_base {
|
||||
friend cpp17_input_iterator<T*> begin(InputView&) { return cpp17_input_iterator<T*>(nullptr); }
|
||||
friend cpp17_input_iterator<T*> begin(InputView const&) { return cpp17_input_iterator<T*>(nullptr); }
|
||||
friend cpp17_input_iterator<T*> end(InputView&) { return cpp17_input_iterator<T*>(nullptr); }
|
||||
friend cpp17_input_iterator<T*> end(InputView const&) { return cpp17_input_iterator<T*>(nullptr); }
|
||||
};
|
||||
|
||||
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)>;
|
||||
|
||||
ASSERT_SAME_TYPE(Iter::iterator_concept, std::bidirectional_iterator_tag);
|
||||
ASSERT_SAME_TYPE(Iter::iterator_category, std::bidirectional_iterator_tag);
|
||||
ASSERT_SAME_TYPE(Iter::difference_type, std::ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(Iter::value_type, int);
|
||||
}
|
||||
{
|
||||
using Iter = std::ranges::iterator_t<std::ranges::join_view<ForwardView<ForwardView<int>>>>;
|
||||
|
||||
ASSERT_SAME_TYPE(Iter::iterator_concept, std::forward_iterator_tag);
|
||||
ASSERT_SAME_TYPE(Iter::iterator_category, std::forward_iterator_tag);
|
||||
ASSERT_SAME_TYPE(Iter::difference_type, std::ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(Iter::value_type, int);
|
||||
}
|
||||
{
|
||||
using Iter = std::ranges::iterator_t<std::ranges::join_view<InputView<InputView<int>>>>;
|
||||
|
||||
ASSERT_SAME_TYPE(Iter::iterator_concept, std::input_iterator_tag);
|
||||
static_assert(!HasIterCategory<Iter>);
|
||||
ASSERT_SAME_TYPE(Iter::difference_type, std::ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(Iter::value_type, int);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr decltype(auto) operator*() const;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 17; ++i) {
|
||||
assert(*iter++ == i);
|
||||
}
|
||||
}
|
||||
{
|
||||
std::ranges::join_view jv(buffer);
|
||||
auto iter = std::next(jv.begin(), 15);
|
||||
assert(*iter++ == 16);
|
||||
assert(iter == jv.end());
|
||||
}
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
auto iter = jv.begin();
|
||||
for (int i = 1; i < 17; ++i) {
|
||||
assert(*iter == i);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// sentinel() = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
std::ranges::sentinel_t<std::ranges::join_view<CopyableParent>> sent;
|
||||
(void) sent;
|
||||
|
||||
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
|
||||
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr sentinel(sentinel<!Const> s);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
std::ranges::join_view jv(CopyableParent{children});
|
||||
auto sent1 = jv.end();
|
||||
std::ranges::sentinel_t<const decltype(jv)> sent2 = sent1;
|
||||
(void) sent2; // We can't really do anything with these sentinels now :/
|
||||
|
||||
// We cannot create a non-const iterator from a const iterator.
|
||||
static_assert(!std::constructible_from<decltype(sent1), decltype(sent2)>);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// constexpr explicit sentinel(Parent& parent);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
|
||||
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
CopyableParent parent{children};
|
||||
std::ranges::join_view jv(parent);
|
||||
std::ranges::sentinel_t<decltype(jv)> sent(jv);
|
||||
assert(sent == std::ranges::next(jv.begin(), 16));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
{
|
||||
// Test explicitness.
|
||||
using Parent = std::ranges::join_view<ParentView<ChildView>>;
|
||||
static_assert( std::is_constructible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
static_assert(!std::is_convertible_v<std::ranges::sentinel_t<Parent>, Parent&>);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: libcpp-has-no-incomplete-ranges
|
||||
|
||||
// template<bool OtherConst>
|
||||
// requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
|
||||
// friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "../types.h"
|
||||
|
||||
constexpr bool test() {
|
||||
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
{
|
||||
ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
|
||||
auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
}
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
const auto jv = std::ranges::join_view(ParentView(children));
|
||||
assert(jv.end() == std::ranges::next(jv.begin(), 16));
|
||||
}
|
||||
{
|
||||
CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])};
|
||||
const std::ranges::join_view jvc(CopyableParent{children});
|
||||
std::ranges::join_view jv(CopyableParent{children});
|
||||
assert(jvc.end() == std::ranges::next(jv.begin(), 16));
|
||||
assert( jv.end() == std::ranges::next(jvc.begin(), 16));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
|
||||
#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
|
||||
|
||||
#include <concepts>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
int globalBuffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
|
||||
|
||||
struct ChildView : std::ranges::view_base {
|
||||
int *ptr_;
|
||||
|
||||
constexpr ChildView(int *ptr = globalBuffer[0]) : ptr_(ptr) {}
|
||||
ChildView(const ChildView&) = delete;
|
||||
ChildView(ChildView&&) = default;
|
||||
ChildView& operator=(const ChildView&) = delete;
|
||||
ChildView& operator=(ChildView&&) = default;
|
||||
|
||||
constexpr cpp20_input_iterator<int *> begin() { return cpp20_input_iterator<int *>(ptr_); }
|
||||
constexpr cpp20_input_iterator<const int *> begin() const { return cpp20_input_iterator<const int *>(ptr_); }
|
||||
constexpr int *end() { return ptr_ + 4; }
|
||||
constexpr const int *end() const { return ptr_ + 4; }
|
||||
};
|
||||
|
||||
constexpr bool operator==(const cpp20_input_iterator<int*> &lhs, int* rhs) { return lhs.base() == rhs; }
|
||||
constexpr bool operator==(int* lhs, const cpp20_input_iterator<int*> &rhs) { return rhs.base() == lhs; }
|
||||
|
||||
ChildView globalChildren[4] = {ChildView(globalBuffer[0]), ChildView(globalBuffer[1]), ChildView(globalBuffer[2]), ChildView(globalBuffer[3])};
|
||||
|
||||
template<class T>
|
||||
struct ParentView : std::ranges::view_base {
|
||||
T *ptr_;
|
||||
unsigned size_;
|
||||
|
||||
constexpr ParentView(T *ptr, unsigned size = 4)
|
||||
: ptr_(ptr), size_(size) {}
|
||||
constexpr ParentView(ChildView *ptr = globalChildren, unsigned size = 4)
|
||||
requires std::same_as<ChildView, T>
|
||||
: ptr_(ptr), size_(size) {}
|
||||
ParentView(const ParentView&) = delete;
|
||||
ParentView(ParentView&&) = default;
|
||||
ParentView& operator=(const ParentView&) = delete;
|
||||
ParentView& operator=(ParentView&&) = default;
|
||||
|
||||
constexpr cpp20_input_iterator<T *> begin() { return cpp20_input_iterator<T *>(ptr_); }
|
||||
constexpr cpp20_input_iterator<const T *> begin() const { return cpp20_input_iterator<const T *>(ptr_); }
|
||||
constexpr T *end() { return ptr_ + size_; }
|
||||
constexpr const T *end() const { return ptr_ + size_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr bool operator==(const cpp20_input_iterator<T*> &lhs, T *rhs) { return lhs.base() == rhs; }
|
||||
template<class T>
|
||||
constexpr bool operator==(T *lhs, const cpp20_input_iterator<T*> &rhs) { return rhs.base() == lhs; }
|
||||
|
||||
struct CopyableChild : std::ranges::view_base {
|
||||
int *ptr_;
|
||||
unsigned size_;
|
||||
constexpr CopyableChild(int *ptr = globalBuffer[0], unsigned size = 4)
|
||||
: ptr_(ptr), size_(size) {}
|
||||
|
||||
constexpr cpp17_input_iterator<int *> begin() { return cpp17_input_iterator<int *>(ptr_); }
|
||||
constexpr cpp17_input_iterator<const int *> begin() const { return cpp17_input_iterator<const int *>(ptr_); }
|
||||
constexpr int *end() { return ptr_ + size_; }
|
||||
constexpr const int *end() const { return ptr_ + size_; }
|
||||
};
|
||||
|
||||
constexpr bool operator==(const cpp17_input_iterator<const int*> &lhs, const int* rhs) { return lhs.base() == rhs; }
|
||||
constexpr bool operator==(const int* lhs, const cpp17_input_iterator<const int*> &rhs) { return rhs.base() == lhs; }
|
||||
|
||||
struct CopyableParent : std::ranges::view_base {
|
||||
CopyableChild *ptr_;
|
||||
constexpr CopyableParent(CopyableChild *ptr) : ptr_(ptr) {}
|
||||
|
||||
constexpr cpp17_input_iterator<CopyableChild *> begin() { return cpp17_input_iterator<CopyableChild *>(ptr_); }
|
||||
constexpr cpp17_input_iterator<const CopyableChild *> begin() const { return cpp17_input_iterator<const CopyableChild *>(ptr_); }
|
||||
constexpr CopyableChild *end() { return ptr_ + 4; }
|
||||
constexpr const CopyableChild *end() const { return ptr_ + 4; }
|
||||
};
|
||||
|
||||
constexpr bool operator==(const cpp17_input_iterator<const CopyableChild*> &lhs, const CopyableChild *rhs) { return lhs.base() == rhs; }
|
||||
constexpr bool operator==(const CopyableChild *lhs, const cpp17_input_iterator<const CopyableChild*> &rhs) { return rhs.base() == lhs; }
|
||||
|
||||
struct Box { int x; };
|
||||
|
||||
template<class T>
|
||||
struct InputValueIter {
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef int difference_type;
|
||||
typedef T reference;
|
||||
|
||||
T *ptr_;
|
||||
constexpr InputValueIter(T *ptr) : ptr_(ptr) {}
|
||||
|
||||
constexpr T operator*() const { return std::move(*ptr_); }
|
||||
constexpr void operator++(int) { ++ptr_; }
|
||||
constexpr InputValueIter& operator++() { ++ptr_; return *this; }
|
||||
|
||||
constexpr T *operator->() { return ptr_; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
constexpr bool operator==(const InputValueIter<T> &lhs, const T* rhs) { return lhs.ptr_ == rhs; }
|
||||
template<class T>
|
||||
constexpr bool operator==(const T* lhs, const InputValueIter<T> &rhs) { return rhs.ptr_ == lhs; }
|
||||
|
||||
template<class T>
|
||||
struct ValueView : std::ranges::view_base {
|
||||
InputValueIter<T> ptr_;
|
||||
|
||||
constexpr ValueView(T *ptr) : ptr_(ptr) {}
|
||||
|
||||
constexpr ValueView(ValueView &&other)
|
||||
: ptr_(other.ptr_) { other.ptr_.ptr_ = nullptr; }
|
||||
|
||||
constexpr ValueView& operator=(ValueView &&other) {
|
||||
ptr_ = other.ptr_;
|
||||
other.ptr_ = InputValueIter<T>(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ValueView(const ValueView&) = delete;
|
||||
ValueView& operator=(const ValueView&) = delete;
|
||||
|
||||
constexpr InputValueIter<T> begin() { return ptr_; }
|
||||
constexpr const InputValueIter<T> begin() const { return ptr_; }
|
||||
constexpr T *end() { return ptr_.ptr_ + 4; }
|
||||
constexpr const T *end() const { return ptr_.ptr_ + 4; }
|
||||
};
|
||||
|
||||
#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
|
|
@ -914,6 +914,13 @@ private:
|
|||
difference_type stride_displacement_ = 0;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
concept sentinel_for_base = requires(U const& u) {
|
||||
u.base();
|
||||
requires std::input_or_output_iterator<std::remove_cvref_t<decltype(u.base())>>;
|
||||
requires std::equality_comparable_with<T, decltype(u.base())>;
|
||||
};
|
||||
|
||||
template <std::input_or_output_iterator I>
|
||||
class sentinel_wrapper {
|
||||
public:
|
||||
|
@ -927,6 +934,12 @@ public:
|
|||
constexpr const I& base() const& { return base_; }
|
||||
constexpr I base() && { return std::move(base_); }
|
||||
|
||||
template<std::input_or_output_iterator I2>
|
||||
requires sentinel_for_base<I, I2>
|
||||
constexpr bool operator==(I2 const& other) const {
|
||||
return base_ == other.base();
|
||||
}
|
||||
|
||||
private:
|
||||
I base_ = I();
|
||||
};
|
||||
|
|
|
@ -62,4 +62,10 @@ struct test_view : std::ranges::view_base {
|
|||
sentinel end() const;
|
||||
};
|
||||
|
||||
template<template<class...> class I, class R>
|
||||
constexpr auto make_archetype_range(R&& r) {
|
||||
return std::ranges::subrange(I(std::ranges::begin(r)), sentinel_wrapper(std::ranges::end(r)));
|
||||
}
|
||||
|
||||
|
||||
#endif // LIBCXX_TEST_SUPPORT_TEST_RANGE_H
|
||||
|
|
Loading…
Reference in New Issue