blob: d5068b3cf013f443f7446e317dd20e163b2f1c4a [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H
#define TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H
#include "test_macros.h"
#include "test_iterators.h"
template <class>
class assignable_iterator;
template <class It>
class simple_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_;}
simple_iterator() = default;
explicit constexpr simple_iterator(It it) : it_(it) {}
constexpr reference operator*() const {return *it_;}
constexpr simple_iterator& operator++() {++it_; return *this;}
constexpr simple_iterator operator++(int)
{simple_iterator tmp(*this); ++(*this); return tmp;}
};
template <class It>
class value_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_;}
value_iterator() = default;
explicit constexpr value_iterator(It it) : it_(it) {}
constexpr value_type operator*() const {return std::move(*it_);}
constexpr value_iterator& operator++() {++it_; return *this;}
constexpr value_iterator operator++(int)
{value_iterator tmp(*this); ++(*this); return tmp;}
};
template <class It>
class void_plus_plus_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_;}
void_plus_plus_iterator() = default;
explicit constexpr void_plus_plus_iterator(It it) : it_(it) {}
constexpr value_type operator*() const {return std::move(*it_);}
constexpr void_plus_plus_iterator& operator++() {++it_; return *this;}
constexpr void operator++(int) {++(*this);}
};
// Not referenceable, constructible, and not move constructible.
template <class It>
class value_type_not_move_constructible_iterator
{
It it_;
public:
template<class T>
struct hold {
T value_;
hold(T v) : value_(v) {}
hold(const hold&) = delete;
hold(hold&&) = delete;
};
typedef std::input_iterator_tag iterator_category;
typedef typename std::iterator_traits<It>::value_type underlying_value_type;
typedef hold<underlying_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_;}
value_type_not_move_constructible_iterator() = default;
explicit constexpr value_type_not_move_constructible_iterator(It it) : it_(it) {}
constexpr underlying_value_type operator*() const {return std::move(*it_);}
constexpr value_type_not_move_constructible_iterator& operator++() {++it_; return *this;}
constexpr void operator++(int) {++(*this);}
};
template <class It>
class comparable_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_;}
comparable_iterator() = default;
explicit constexpr comparable_iterator(It it) : it_(it) {}
constexpr reference operator*() const {return *it_;}
constexpr comparable_iterator& operator++() {++it_; return *this;}
constexpr comparable_iterator operator++(int)
{comparable_iterator tmp(*this); ++(*this); return tmp;}
friend constexpr bool operator==(const comparable_iterator& lhs, const simple_iterator<It>& rhs) {
return lhs.base() == rhs.base();
}
friend constexpr bool operator==(const simple_iterator<It>& lhs, const comparable_iterator& rhs) {
return lhs.base() == rhs.base();
}
friend constexpr auto operator-(const comparable_iterator& lhs, const simple_iterator<It>& rhs) {
return lhs.base() - rhs.base();
}
friend constexpr auto operator-(const simple_iterator<It>& lhs, const comparable_iterator& rhs) {
return lhs.base() - rhs.base();
}
};
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
{
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_;}
non_const_deref_iterator() = default;
explicit constexpr non_const_deref_iterator(It it) : it_(it) {}
constexpr reference operator*() {return *it_;} // Note: non-const.
constexpr non_const_deref_iterator& operator++() {++it_; return *this;}
constexpr non_const_deref_iterator operator++(int)
{non_const_deref_iterator tmp(*this); ++(*this); return tmp;}
};
template<class T>
struct sentinel_type {
T base;
template<class U>
friend constexpr bool operator==(const sentinel_type& lhs, const U& rhs) { return lhs.base == rhs.base(); }
template<class U>
friend constexpr bool operator==(const U& lhs, const sentinel_type& rhs) { return lhs.base() == rhs.base; }
};
template<class T>
struct sized_sentinel_type {
T base;
template<class U>
friend constexpr bool operator==(const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); }
template<class U>
friend constexpr bool operator==(const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; }
template<class U>
friend constexpr auto operator- (const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); }
template<class U>
friend constexpr auto operator- (const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; }
};
template <class It>
class assignable_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_;}
assignable_iterator() = default;
explicit constexpr assignable_iterator(It it) : it_(it) {}
assignable_iterator(const forward_iterator<It>& it) : it_(it.base()) {}
assignable_iterator(const sentinel_type<It>& it) : it_(it.base) {}
constexpr reference operator*() const {return *it_;}
constexpr assignable_iterator& operator++() {++it_; return *this;}
constexpr assignable_iterator operator++(int)
{assignable_iterator tmp(*this); ++(*this); return tmp;}
assignable_iterator& operator=(const forward_iterator<It> &other) {
it_ = other.base();
return *this;
}
assignable_iterator& operator=(const sentinel_type<It> &other) {
it_ = other.base;
return *this;
}
};
#ifndef TEST_HAS_NO_EXCEPTIONS
template<class T>
struct sentinel_throws_on_convert {
T base;
template<class U>
friend constexpr bool operator==(const sentinel_throws_on_convert& lhs, const U& rhs) { return lhs.base == rhs.base(); }
template<class U>
friend constexpr bool operator==(const U& lhs, const sentinel_throws_on_convert& rhs) { return lhs.base() == rhs.base; }
operator sentinel_type<int*>() const { throw 42; }
};
template <class It>
class maybe_valueless_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_;}
maybe_valueless_iterator() = default;
explicit constexpr maybe_valueless_iterator(It it) : it_(it) {}
maybe_valueless_iterator(const forward_iterator<It>& it) : it_(it.base()) {}
constexpr reference operator*() const {return *it_;}
constexpr maybe_valueless_iterator& operator++() {++it_; return *this;}
constexpr maybe_valueless_iterator operator++(int)
{maybe_valueless_iterator tmp(*this); ++(*this); return tmp;}
maybe_valueless_iterator& operator=(const forward_iterator<It> &other) {
it_ = other.base();
return *this;
}
};
#endif // TEST_HAS_NO_EXCEPTIONS
#endif // TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H