Create a 'comma_iterator' class that overloads operator, and asserts when it's called. Add tests to mismatch to make sure it can't be blindsided by such an evil iterator. More tests for other algorithms forthcoming. Thanks to STL for pointing this out at CppCon and Yakov Galka for opening LWG issue #2133

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@217902 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Marshall Clow 2014-09-16 20:38:11 +00:00
parent 4413ab09d5
commit 270f8e01e8
3 changed files with 121 additions and 0 deletions

View File

@ -36,6 +36,14 @@ int main()
input_iterator<const int*>(ia+3),
input_iterator<const int*>(ib+3))));
assert(std::mismatch(comma_iterator<const int*>(ia),
comma_iterator<const int*>(ia + sa),
comma_iterator<const int*>(ib)) ==
(std::pair<comma_iterator<const int*>,
comma_iterator<const int*> >(
comma_iterator<const int*>(ia+3),
comma_iterator<const int*>(ib+3))));
#ifdef HAS_FOUR_ITERATOR_VERSION
assert(std::mismatch(input_iterator<const int*>(ia),
input_iterator<const int*>(ia + sa),

View File

@ -39,6 +39,14 @@ int main()
input_iterator<const int*> >(
input_iterator<const int*>(ia+3),
input_iterator<const int*>(ib+3))));
assert(std::mismatch(comma_iterator<const int*>(ia),
comma_iterator<const int*>(ia + sa),
comma_iterator<const int*>(ib),
std::equal_to<int>()) ==
(std::pair<comma_iterator<const int*>,
comma_iterator<const int*> >(
comma_iterator<const int*>(ia+3),
comma_iterator<const int*>(ib+3))));
#ifdef HAS_FOUR_ITERATOR_VERSION
assert(std::mismatch(input_iterator<const int*>(ia),
input_iterator<const int*>(ia + sa),

View File

@ -284,6 +284,108 @@ operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y
return x.base() - y.base();
}
template <class It>
class comma_iterator
{
It it_;
template <class U> friend class comma_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;
It base() const {return it_;}
comma_iterator() : it_() {}
explicit comma_iterator(It it) : it_(it) {}
template <class U>
comma_iterator(const comma_iterator<U>& u) :it_(u.it_) {}
reference operator*() const {return *it_;}
pointer operator->() const {return it_;}
comma_iterator& operator++() {++it_; return *this;}
comma_iterator operator++(int)
{comma_iterator tmp(*this); ++(*this); return tmp;}
comma_iterator& operator--() {--it_; return *this;}
comma_iterator operator--(int)
{comma_iterator tmp(*this); --(*this); return tmp;}
comma_iterator& operator+=(difference_type n) {it_ += n; return *this;}
comma_iterator operator+(difference_type n) const
{comma_iterator tmp(*this); tmp += n; return tmp;}
friend comma_iterator operator+(difference_type n, comma_iterator x)
{x += n; return x;}
comma_iterator& operator-=(difference_type n) {return *this += -n;}
comma_iterator operator-(difference_type n) const
{comma_iterator tmp(*this); tmp -= n; return tmp;}
reference operator[](difference_type n) const {return it_[n];}
template <typename T>
void operator,(const T &) { assert(false); }
};
template <class T, class U>
inline
bool
operator==(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return x.base() == y.base();
}
template <class T, class U>
inline
bool
operator!=(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return !(x == y);
}
template <class T, class U>
inline
bool
operator<(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return x.base() < y.base();
}
template <class T, class U>
inline
bool
operator<=(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return !(y < x);
}
template <class T, class U>
inline
bool
operator>(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return y < x;
}
template <class T, class U>
inline
bool
operator>=(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return !(x < y);
}
template <class T, class U>
inline
typename std::iterator_traits<T>::difference_type
operator-(const comma_iterator<T>& x, const comma_iterator<U>& y)
{
return x.base() - y.base();
}
template <class Iter>
inline Iter base(output_iterator<Iter> i) { return i.base(); }
@ -299,6 +401,9 @@ inline Iter base(bidirectional_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline Iter base(random_access_iterator<Iter> i) { return i.base(); }
template <class Iter>
inline Iter base(comma_iterator<Iter> i) { return i.base(); }
template <class Iter> // everything else
inline Iter base(Iter i) { return i; }