teak-llvm/libcxx/test/support/test_iterators.h
Chandler Carruth 57b08b0944 Update more file headers across all of the LLVM projects in the monorepo
to reflect the new license. These used slightly different spellings that
defeated my regular expressions.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351648
2019-01-19 10:56:40 +00:00

552 lines
17 KiB
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 ITERATORS_H
#define ITERATORS_H
#include <iterator>
#include <stdexcept>
#include <cstddef>
#include <cassert>
#include "test_macros.h"
#if TEST_STD_VER >= 11
#define DELETE_FUNCTION = delete
#else
#define DELETE_FUNCTION
#endif
template <class It>
class output_iterator
{
It it_;
template <class U> friend class output_iterator;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef It pointer;
typedef typename std::iterator_traits<It>::reference reference;
It base() const {return it_;}
output_iterator () {}
explicit output_iterator(It it) : it_(it) {}
template <class U>
output_iterator(const output_iterator<U>& u) :it_(u.it_) {}
reference operator*() const {return *it_;}
output_iterator& operator++() {++it_; return *this;}
output_iterator operator++(int)
{output_iterator tmp(*this); ++(*this); return tmp;}
template <class T>
void operator,(T const &) DELETE_FUNCTION;
};
template <class It,
class ItTraits = It>
class input_iterator
{
typedef std::iterator_traits<ItTraits> Traits;
It it_;
template <class U, class T> friend class input_iterator;
public:
typedef std::input_iterator_tag iterator_category;
typedef typename Traits::value_type value_type;
typedef typename Traits::difference_type difference_type;
typedef It pointer;
typedef typename Traits::reference reference;
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
TEST_CONSTEXPR_CXX14 input_iterator() : it_() {}
explicit TEST_CONSTEXPR_CXX14 input_iterator(It it) : it_(it) {}
template <class U, class T>
TEST_CONSTEXPR_CXX14 input_iterator(const input_iterator<U, T>& u) :it_(u.it_) {}
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
TEST_CONSTEXPR_CXX14 input_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 input_iterator operator++(int)
{input_iterator tmp(*this); ++(*this); return tmp;}
friend TEST_CONSTEXPR_CXX14 bool operator==(const input_iterator& x, const input_iterator& y)
{return x.it_ == y.it_;}
friend TEST_CONSTEXPR_CXX14 bool operator!=(const input_iterator& x, const input_iterator& y)
{return !(x == y);}
template <class T>
void operator,(T const &) DELETE_FUNCTION;
};
template <class T, class TV, class U, class UV>
inline
bool
operator==(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
{
return x.base() == y.base();
}
template <class T, class TV, class U, class UV>
inline
bool
operator!=(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y)
{
return !(x == y);
}
template <class It>
class forward_iterator
{
It it_;
template <class U> friend class forward_iterator;
public:
typedef std::forward_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;
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
TEST_CONSTEXPR_CXX14 forward_iterator() : it_() {}
explicit TEST_CONSTEXPR_CXX14 forward_iterator(It it) : it_(it) {}
template <class U>
TEST_CONSTEXPR_CXX14 forward_iterator(const forward_iterator<U>& u) :it_(u.it_) {}
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
TEST_CONSTEXPR_CXX14 forward_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 forward_iterator operator++(int)
{forward_iterator tmp(*this); ++(*this); return tmp;}
friend TEST_CONSTEXPR_CXX14 bool operator==(const forward_iterator& x, const forward_iterator& y)
{return x.it_ == y.it_;}
friend TEST_CONSTEXPR_CXX14 bool operator!=(const forward_iterator& x, const forward_iterator& y)
{return !(x == y);}
template <class T>
void operator,(T const &) DELETE_FUNCTION;
};
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator==(const forward_iterator<T>& x, const forward_iterator<U>& y)
{
return x.base() == y.base();
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator!=(const forward_iterator<T>& x, const forward_iterator<U>& y)
{
return !(x == y);
}
template <class It>
class bidirectional_iterator
{
It it_;
template <class U> friend class bidirectional_iterator;
public:
typedef std::bidirectional_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;
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
TEST_CONSTEXPR_CXX14 bidirectional_iterator() : it_() {}
explicit TEST_CONSTEXPR_CXX14 bidirectional_iterator(It it) : it_(it) {}
template <class U>
TEST_CONSTEXPR_CXX14 bidirectional_iterator(const bidirectional_iterator<U>& u) :it_(u.it_) {}
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 bidirectional_iterator operator++(int)
{bidirectional_iterator tmp(*this); ++(*this); return tmp;}
TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator--() {--it_; return *this;}
TEST_CONSTEXPR_CXX14 bidirectional_iterator operator--(int)
{bidirectional_iterator tmp(*this); --(*this); return tmp;}
template <class T>
void operator,(T const &) DELETE_FUNCTION;
};
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator==(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
{
return x.base() == y.base();
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator!=(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y)
{
return !(x == y);
}
template <class It>
class random_access_iterator
{
It it_;
template <class U> friend class random_access_iterator;
public:
typedef std::random_access_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;
TEST_CONSTEXPR_CXX14 It base() const {return it_;}
TEST_CONSTEXPR_CXX14 random_access_iterator() : it_() {}
explicit TEST_CONSTEXPR_CXX14 random_access_iterator(It it) : it_(it) {}
template <class U>
TEST_CONSTEXPR_CXX14 random_access_iterator(const random_access_iterator<U>& u) :it_(u.it_) {}
TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;}
TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;}
TEST_CONSTEXPR_CXX14 random_access_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 random_access_iterator operator++(int)
{random_access_iterator tmp(*this); ++(*this); return tmp;}
TEST_CONSTEXPR_CXX14 random_access_iterator& operator--() {--it_; return *this;}
TEST_CONSTEXPR_CXX14 random_access_iterator operator--(int)
{random_access_iterator tmp(*this); --(*this); return tmp;}
TEST_CONSTEXPR_CXX14 random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;}
TEST_CONSTEXPR_CXX14 random_access_iterator operator+(difference_type n) const
{random_access_iterator tmp(*this); tmp += n; return tmp;}
friend TEST_CONSTEXPR_CXX14 random_access_iterator operator+(difference_type n, random_access_iterator x)
{x += n; return x;}
TEST_CONSTEXPR_CXX14 random_access_iterator& operator-=(difference_type n) {return *this += -n;}
TEST_CONSTEXPR_CXX14 random_access_iterator operator-(difference_type n) const
{random_access_iterator tmp(*this); tmp -= n; return tmp;}
TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const {return it_[n];}
template <class T>
void operator,(T const &) DELETE_FUNCTION;
};
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator==(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return x.base() == y.base();
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator!=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return !(x == y);
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator<(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return x.base() < y.base();
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator<=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return !(y < x);
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator>(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return y < x;
}
template <class T, class U>
inline
bool TEST_CONSTEXPR_CXX14
operator>=(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return !(x < y);
}
template <class T, class U>
inline TEST_CONSTEXPR_CXX14
typename std::iterator_traits<T>::difference_type
operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y)
{
return x.base() - y.base();
}
template <class Iter>
inline TEST_CONSTEXPR_CXX14 Iter base(output_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline TEST_CONSTEXPR_CXX14 Iter base(input_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline TEST_CONSTEXPR_CXX14 Iter base(forward_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline TEST_CONSTEXPR_CXX14 Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline TEST_CONSTEXPR_CXX14 Iter base(random_access_iterator<Iter> i) { return i.base(); }
template <class Iter> // everything else
inline TEST_CONSTEXPR_CXX14 Iter base(Iter i) { return i; }
template <typename T>
struct ThrowingIterator {
typedef std::bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef const T value_type;
typedef const T * pointer;
typedef const T & reference;
enum ThrowingAction { TAIncrement, TADecrement, TADereference, TAAssignment, TAComparison };
// Constructors
ThrowingIterator ()
: begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference), index_(0) {}
ThrowingIterator (const T *first, const T *last, size_t index = 0, ThrowingAction action = TADereference)
: begin_(first), end_(last), current_(first), action_(action), index_(index) {}
ThrowingIterator (const ThrowingIterator &rhs)
: begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_), action_(rhs.action_), index_(rhs.index_) {}
ThrowingIterator & operator= (const ThrowingIterator &rhs)
{
if (action_ == TAAssignment)
{
if (index_ == 0)
#ifndef TEST_HAS_NO_EXCEPTIONS
throw std::runtime_error ("throw from iterator assignment");
#else
assert(false);
#endif
else
--index_;
}
begin_ = rhs.begin_;
end_ = rhs.end_;
current_ = rhs.current_;
action_ = rhs.action_;
index_ = rhs.index_;
return *this;
}
// iterator operations
reference operator*() const
{
if (action_ == TADereference)
{
if (index_ == 0)
#ifndef TEST_HAS_NO_EXCEPTIONS
throw std::runtime_error ("throw from iterator dereference");
#else
assert(false);
#endif
else
--index_;
}
return *current_;
}
ThrowingIterator & operator++()
{
if (action_ == TAIncrement)
{
if (index_ == 0)
#ifndef TEST_HAS_NO_EXCEPTIONS
throw std::runtime_error ("throw from iterator increment");
#else
assert(false);
#endif
else
--index_;
}
++current_;
return *this;
}
ThrowingIterator operator++(int)
{
ThrowingIterator temp = *this;
++(*this);
return temp;
}
ThrowingIterator & operator--()
{
if (action_ == TADecrement)
{
if (index_ == 0)
#ifndef TEST_HAS_NO_EXCEPTIONS
throw std::runtime_error ("throw from iterator decrement");
#else
assert(false);
#endif
else
--index_;
}
--current_;
return *this;
}
ThrowingIterator operator--(int) {
ThrowingIterator temp = *this;
--(*this);
return temp;
}
bool operator== (const ThrowingIterator &rhs) const
{
if (action_ == TAComparison)
{
if (index_ == 0)
#ifndef TEST_HAS_NO_EXCEPTIONS
throw std::runtime_error ("throw from iterator comparison");
#else
assert(false);
#endif
else
--index_;
}
bool atEndL = current_ == end_;
bool atEndR = rhs.current_ == rhs.end_;
if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
if (atEndL) return true; // both are at the end (or empty)
return current_ == rhs.current_;
}
private:
const T* begin_;
const T* end_;
const T* current_;
ThrowingAction action_;
mutable size_t index_;
};
template <typename T>
bool operator== (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
{ return a.operator==(b); }
template <typename T>
bool operator!= (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b)
{ return !a.operator==(b); }
template <typename T>
struct NonThrowingIterator {
typedef std::bidirectional_iterator_tag iterator_category;
typedef ptrdiff_t difference_type;
typedef const T value_type;
typedef const T * pointer;
typedef const T & reference;
// Constructors
NonThrowingIterator ()
: begin_(nullptr), end_(nullptr), current_(nullptr) {}
NonThrowingIterator (const T *first, const T* last)
: begin_(first), end_(last), current_(first) {}
NonThrowingIterator (const NonThrowingIterator &rhs)
: begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_) {}
NonThrowingIterator & operator= (const NonThrowingIterator &rhs) TEST_NOEXCEPT
{
begin_ = rhs.begin_;
end_ = rhs.end_;
current_ = rhs.current_;
return *this;
}
// iterator operations
reference operator*() const TEST_NOEXCEPT
{
return *current_;
}
NonThrowingIterator & operator++() TEST_NOEXCEPT
{
++current_;
return *this;
}
NonThrowingIterator operator++(int) TEST_NOEXCEPT
{
NonThrowingIterator temp = *this;
++(*this);
return temp;
}
NonThrowingIterator & operator--() TEST_NOEXCEPT
{
--current_;
return *this;
}
NonThrowingIterator operator--(int) TEST_NOEXCEPT
{
NonThrowingIterator temp = *this;
--(*this);
return temp;
}
bool operator== (const NonThrowingIterator &rhs) const TEST_NOEXCEPT
{
bool atEndL = current_ == end_;
bool atEndR = rhs.current_ == rhs.end_;
if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not.
if (atEndL) return true; // both are at the end (or empty)
return current_ == rhs.current_;
}
private:
const T* begin_;
const T* end_;
const T* current_;
};
template <typename T>
bool operator== (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
{ return a.operator==(b); }
template <typename T>
bool operator!= (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT
{ return !a.operator==(b); }
#undef DELETE_FUNCTION
#endif // ITERATORS_H