//===----------------------------------------------------------------------===//
//
// 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
// template<class T>
// concept contiguous_iterator;
#include <iterator>
#include <compare>
#include <memory>
#include "test_iterators.h"
static_assert(!std::contiguous_iterator<cpp17_input_iterator<int*>>);
static_assert(!std::contiguous_iterator<cpp20_input_iterator<int*>>);
static_assert(!std::contiguous_iterator<forward_iterator<int*>>);
static_assert(!std::contiguous_iterator<bidirectional_iterator<int*>>);
static_assert(!std::contiguous_iterator<random_access_iterator<int*>>);
static_assert(std::contiguous_iterator<contiguous_iterator<int*>>);
static_assert(std::contiguous_iterator<int*>);
static_assert(std::contiguous_iterator<int const*>);
static_assert(std::contiguous_iterator<int volatile*>);
static_assert(std::contiguous_iterator<int const volatile*>);
struct simple_contiguous_iterator {
typedef std::contiguous_iterator_tag iterator_category;
typedef int value_type;
typedef int element_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef simple_contiguous_iterator self;
simple_contiguous_iterator();
reference operator*() const;
pointer operator->() const;
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
friend self operator+(difference_type n, self x);
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
static_assert(std::random_access_iterator<simple_contiguous_iterator>);
static_assert(std::contiguous_iterator<simple_contiguous_iterator>);
struct mismatch_value_iter_ref_t {
typedef std::contiguous_iterator_tag iterator_category;
typedef short value_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef mismatch_value_iter_ref_t self;
mismatch_value_iter_ref_t();
reference operator*() const;
pointer operator->() const;
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
friend self operator+(difference_type n, self x);
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
static_assert(std::random_access_iterator<mismatch_value_iter_ref_t>);
static_assert(!std::contiguous_iterator<mismatch_value_iter_ref_t>);
struct wrong_iter_reference_t {
typedef std::contiguous_iterator_tag iterator_category;
typedef short value_type;
typedef short element_type;
typedef std::ptrdiff_t difference_type;
typedef short* pointer;
typedef int& reference;
typedef wrong_iter_reference_t self;
wrong_iter_reference_t();
reference operator*() const;
pointer operator->() const;
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
friend self operator+(difference_type n, self x);
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
static_assert(std::random_access_iterator<wrong_iter_reference_t>);
static_assert(!std::contiguous_iterator<wrong_iter_reference_t>);
struct to_address_wrong_return_type {
typedef std::contiguous_iterator_tag iterator_category;
typedef int value_type;
typedef int element_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef to_address_wrong_return_type self;
to_address_wrong_return_type();
reference operator*() const;
pointer operator->() const;
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
friend self operator+(difference_type n, self x);
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
template<>
struct std::pointer_traits<to_address_wrong_return_type> {
typedef void element_type;
static void *to_address(to_address_wrong_return_type const&);
};
static_assert(std::random_access_iterator<to_address_wrong_return_type>);
static_assert(!std::contiguous_iterator<to_address_wrong_return_type>);
template<class>
struct template_and_no_element_type {
typedef std::contiguous_iterator_tag iterator_category;
typedef int value_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef template_and_no_element_type self;
template_and_no_element_type();
reference operator*() const;
pointer operator->() const;
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
friend self operator+(difference_type, self) { return self{}; }
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
// Template param is used instead of element_type.
static_assert(std::random_access_iterator<template_and_no_element_type<int>>);
static_assert(std::contiguous_iterator<template_and_no_element_type<int>>);
template <bool DisableArrow, bool DisableToAddress>
struct no_operator_arrow {
typedef std::contiguous_iterator_tag iterator_category;
typedef int value_type;
typedef int element_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef no_operator_arrow self;
no_operator_arrow();
reference operator*() const;
pointer operator->() const requires (!DisableArrow);
auto operator<=>(const self&) const = default;
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
self& operator+=(difference_type n);
self operator+(difference_type n) const;
// Note: it's a template function to prevent a GCC warning ("friend declaration declares a non-template function").
template <bool B1, bool B2>
friend no_operator_arrow<B1, B2> operator+(difference_type n, no_operator_arrow<B1, B2> x);
self& operator-=(difference_type n);
self operator-(difference_type n) const;
difference_type operator-(const self& n) const;
reference operator[](difference_type n) const;
};
template<>
struct std::pointer_traits<no_operator_arrow</*DisableArrow=*/true, /*DisableToAddress=*/false>> {
static constexpr int *to_address(const no_operator_arrow<true, false>&);
};
static_assert(std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/false, /*DisableToAddress=*/true>>);
static_assert(!std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/true, /*DisableToAddress=*/true>>);
static_assert(std::contiguous_iterator<no_operator_arrow</*DisableArrow=*/true, /*DisableToAddress=*/false>>);