blob: ca45fd81829c87a28787cd1c9052342b4d39dbfb [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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, c++20
// constexpr auto begin() requires(!simple-view<V>)
// constexpr auto begin() const requires range<const V>
// Note: Checks here are augmented by checks in
// iterator/ctor.copy.pass.cpp.
#include <cassert>
#include <concepts>
#include <ranges>
#include "types.h"
template <class T>
concept HasConstBegin = requires(const T& ct) { ct.begin(); };
template <class T>
concept HasBegin = requires(T& t) { t.begin(); };
template <class T>
concept HasConstAndNonConstBegin = requires(T& t, const T& ct) {
// The return types for begin are different when this is const or not:
// the iterator's _Const non-type-template parameter is true in the former
// and false in the latter.
requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>;
};
template <class T>
// There is a begin but it's not const qualified => Only non-const qualified begin.
concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;
template <class T>
// There is a const-qualified begin and there are not both const- and non-const qualified begin => Only const-qualified begin.
concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;
static_assert(HasOnlyNonConstBegin<std::ranges::stride_view<UnSimpleNoConstCommonView>>);
static_assert(HasOnlyConstBegin<std::ranges::stride_view<SimpleCommonConstView>>);
static_assert(HasConstAndNonConstBegin<std::ranges::stride_view<UnSimpleConstView>>);
constexpr bool test() {
{
// Return type check for non-simple const view.
const auto v = UnSimpleConstView();
const auto sv = std::ranges::stride_view(v, 1);
static_assert(std::same_as<decltype(*sv.begin()), double&>);
}
{
// Return type check for simple const view.
auto v = SimpleCommonConstView();
auto sv = std::ranges::stride_view(v, 1);
static_assert(std::same_as<decltype(*sv.begin()), int&>);
}
{
// Verify begin() produces the first element with stride 1.
int data[] = {10, 20, 30, 40, 50};
auto v = BasicTestView<int*, int*>{data, data + 5};
auto sv = std::ranges::stride_view(v, 1);
assert(*sv.begin() == 10);
}
{
// Verify begin() produces the first element with stride 3.
int data[] = {10, 20, 30, 40, 50};
auto v = BasicTestView<int*, int*>{data, data + 5};
auto sv = std::ranges::stride_view(v, 3);
assert(*sv.begin() == 10);
}
{
// Verify iterating from begin with stride 2 produces correct elements.
int data[] = {1, 2, 3, 4, 5};
auto v = BasicTestView<int*, int*>{data, data + 5};
auto sv = std::ranges::stride_view(v, 2);
auto it = sv.begin();
assert(*it == 1);
++it;
assert(*it == 3);
++it;
assert(*it == 5);
++it;
assert(it == sv.end());
}
{
// Verify begin on forward range.
int data[] = {100, 200, 300};
using FwdView = BasicTestView<forward_iterator<int*>, forward_iterator<int*>>;
auto v = FwdView{forward_iterator(data), forward_iterator(data + 3)};
auto sv = std::ranges::stride_view(v, 2);
assert(*sv.begin() == 100);
auto it = sv.begin();
++it;
assert(*it == 300);
}
{
// Empty range: begin() == end().
int data[] = {1};
auto v = BasicTestView<int*, int*>{data, data};
auto sv = std::ranges::stride_view(v, 3);
assert(sv.begin() == sv.end());
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}