Vendor import of libc++ release_38 branch r257836:
https://llvm.org/svn/llvm-project/libcxx/branches/release_38@257836
This commit is contained in:
parent
043da5ce84
commit
dfd66a522f
@ -1687,25 +1687,6 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const
|
||||
}
|
||||
|
||||
// copy
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator
|
||||
{
|
||||
static const bool value = is_pointer<_Iter>::value;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator<move_iterator<_Iter> >
|
||||
{
|
||||
static const bool value = is_pointer<_Iter>::value;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator<__wrap_iter<_Iter> >
|
||||
{
|
||||
static const bool value = is_pointer<_Iter>::value;
|
||||
};
|
||||
|
||||
template <class _Iter>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_Iter
|
||||
|
@ -437,6 +437,12 @@ struct __is_bidirectional_iterator : public __has_iterator_category_convertible_
|
||||
template <class _Tp>
|
||||
struct __is_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {};
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_exactly_input_iterator
|
||||
: public integral_constant<bool,
|
||||
__has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value &&
|
||||
!__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {};
|
||||
|
||||
template<class _Category, class _Tp, class _Distance = ptrdiff_t,
|
||||
class _Pointer = _Tp*, class _Reference = _Tp&>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY iterator
|
||||
@ -1404,6 +1410,23 @@ operator+(typename __wrap_iter<_Iter>::difference_type __n,
|
||||
return __x;
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator
|
||||
: public _LIBCPP_BOOL_CONSTANT(is_pointer<_Iter>::value) {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator<move_iterator<_Iter> >
|
||||
: public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator<reverse_iterator<_Iter> >
|
||||
: public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_is_trivial_iterator<__wrap_iter<_Iter> >
|
||||
: public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {};
|
||||
|
||||
|
||||
template <class _Tp, size_t _Np>
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp*
|
||||
|
114
include/string
114
include/string
@ -1201,6 +1201,30 @@ _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __basic_string_common<true>)
|
||||
#pragma warning( pop )
|
||||
#endif // _LIBCPP_MSVC
|
||||
|
||||
#ifdef _LIBCPP_NO_EXCEPTIONS
|
||||
template <class _Iter>
|
||||
struct __libcpp_string_gets_noexcept_iterator_impl : public true_type {};
|
||||
#elif defined(_LIBCPP_HAS_NO_NOEXCEPT)
|
||||
template <class _Iter>
|
||||
struct __libcpp_string_gets_noexcept_iterator_impl : public false_type {};
|
||||
#else
|
||||
template <class _Iter, bool = __is_forward_iterator<_Iter>::value>
|
||||
struct __libcpp_string_gets_noexcept_iterator_impl : public _LIBCPP_BOOL_CONSTANT((
|
||||
noexcept(++(declval<_Iter&>())) &&
|
||||
is_nothrow_assignable<_Iter&, _Iter>::value &&
|
||||
noexcept(declval<_Iter>() == declval<_Iter>()) &&
|
||||
noexcept(*declval<_Iter>())
|
||||
)) {};
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_string_gets_noexcept_iterator_impl<_Iter, false> : public false_type {};
|
||||
#endif
|
||||
|
||||
|
||||
template <class _Iter>
|
||||
struct __libcpp_string_gets_noexcept_iterator
|
||||
: public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value || __libcpp_string_gets_noexcept_iterator_impl<_Iter>::value) {};
|
||||
|
||||
#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
|
||||
|
||||
template <class _CharT, size_t = sizeof(_CharT)>
|
||||
@ -1495,15 +1519,16 @@ public:
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
basic_string&
|
||||
>::type
|
||||
append(_InputIterator __first, _InputIterator __last);
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
basic_string&
|
||||
>::type
|
||||
append(_ForwardIterator __first, _ForwardIterator __last);
|
||||
@ -1535,15 +1560,16 @@ public:
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
basic_string&
|
||||
>::type
|
||||
assign(_InputIterator __first, _InputIterator __last);
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
basic_string&
|
||||
>::type
|
||||
assign(_ForwardIterator __first, _ForwardIterator __last);
|
||||
@ -1564,15 +1590,16 @@ public:
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
iterator
|
||||
>::type
|
||||
insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
iterator
|
||||
>::type
|
||||
insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last);
|
||||
@ -1817,8 +1844,7 @@ private:
|
||||
template <class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value,
|
||||
void
|
||||
>::type
|
||||
__init(_InputIterator __first, _InputIterator __last);
|
||||
@ -2195,8 +2221,7 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template <class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value,
|
||||
void
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last)
|
||||
@ -2494,15 +2519,14 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator <_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
clear();
|
||||
for (; __first != __last; ++__first)
|
||||
push_back(*__first);
|
||||
basic_string __temp(__first, __last, __alloc());
|
||||
assign(__temp.data(), __temp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2510,7 +2534,8 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last)
|
||||
@ -2643,14 +2668,14 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
__is_exactly_input_iterator<_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
push_back(*__first);
|
||||
basic_string __temp (__first, __last, __alloc());
|
||||
append(__temp.data(), __temp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -2658,7 +2683,8 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _ForwardIterator __last)
|
||||
@ -2774,9 +2800,9 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _InputIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_input_iterator <_InputIterator>::value &&
|
||||
!__is_forward_iterator<_InputIterator>::value,
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
__is_exactly_input_iterator<_InputIterator>::value
|
||||
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
@ -2785,24 +2811,16 @@ basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIt
|
||||
"string::insert(iterator, range) called with an iterator not"
|
||||
" referring to this string");
|
||||
#endif
|
||||
size_type __old_sz = size();
|
||||
difference_type __ip = __pos - begin();
|
||||
for (; __first != __last; ++__first)
|
||||
push_back(*__first);
|
||||
pointer __p = __get_pointer();
|
||||
_VSTD::rotate(__p + __ip, __p + __old_sz, __p + size());
|
||||
#if _LIBCPP_DEBUG_LEVEL >= 2
|
||||
return iterator(this, __p + __ip);
|
||||
#else
|
||||
return iterator(__p + __ip);
|
||||
#endif
|
||||
basic_string __temp(__first, __last, __alloc());
|
||||
return insert(__pos, __temp.data(), __temp.data() + __temp.size());
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
template<class _ForwardIterator>
|
||||
typename enable_if
|
||||
<
|
||||
__is_forward_iterator<_ForwardIterator>::value,
|
||||
__is_forward_iterator<_ForwardIterator>::value
|
||||
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
|
||||
typename basic_string<_CharT, _Traits, _Allocator>::iterator
|
||||
>::type
|
||||
basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last)
|
||||
@ -3005,22 +3023,8 @@ typename enable_if
|
||||
basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2,
|
||||
_InputIterator __j1, _InputIterator __j2)
|
||||
{
|
||||
for (; true; ++__i1, ++__j1)
|
||||
{
|
||||
if (__i1 == __i2)
|
||||
{
|
||||
if (__j1 != __j2)
|
||||
insert(__i1, __j1, __j2);
|
||||
break;
|
||||
}
|
||||
if (__j1 == __j2)
|
||||
{
|
||||
erase(__i1, __i2);
|
||||
break;
|
||||
}
|
||||
traits_type::assign(const_cast<value_type&>(*__i1), *__j1);
|
||||
}
|
||||
return *this;
|
||||
basic_string __temp(__j1, __j2, __alloc());
|
||||
return this->replace(__i1, __i2, __temp);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
|
187
test/libcxx/iterators/trivial_iterators.pass.cpp
Normal file
187
test/libcxx/iterators/trivial_iterators.pass.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
// <iterator>
|
||||
|
||||
// __libcpp_is_trivial_iterator<Tp>
|
||||
|
||||
// __libcpp_is_trivial_iterator determines if an iterator is a "trivial" one,
|
||||
// that can be used w/o worrying about its operations throwing exceptions.
|
||||
// Pointers are trivial iterators. Libc++ has three "iterator wrappers":
|
||||
// reverse_iterator, move_iterator, and __wrap_iter. If the underlying iterator
|
||||
// is trivial, then those are as well.
|
||||
//
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
|
||||
#define DELETE_FUNCTION = delete
|
||||
#else
|
||||
#define DELETE_FUNCTION
|
||||
#endif
|
||||
|
||||
class T; // incomplete
|
||||
|
||||
class my_input_iterator_tag : public std::input_iterator_tag {};
|
||||
|
||||
template <class It>
|
||||
class my_input_iterator
|
||||
{
|
||||
It it_;
|
||||
|
||||
template <class U> friend class input_iterator;
|
||||
public:
|
||||
typedef my_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;
|
||||
|
||||
It base() const {return it_;}
|
||||
|
||||
my_input_iterator() : it_() {}
|
||||
explicit my_input_iterator(It it) : it_(it) {}
|
||||
template <class U>
|
||||
my_input_iterator(const input_iterator<U>& u) :it_(u.it_) {}
|
||||
|
||||
reference operator*() const {return *it_;}
|
||||
pointer operator->() const {return it_;}
|
||||
|
||||
my_input_iterator& operator++() {++it_; return *this;}
|
||||
my_input_iterator operator++(int)
|
||||
{my_input_iterator tmp(*this); ++(*this); return tmp;}
|
||||
|
||||
friend bool operator==(const my_input_iterator& x, const my_input_iterator& y)
|
||||
{return x.it_ == y.it_;}
|
||||
friend bool operator!=(const my_input_iterator& x, const my_input_iterator& y)
|
||||
{return !(x == y);}
|
||||
|
||||
template <class T>
|
||||
void operator,(T const &) DELETE_FUNCTION;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
bool
|
||||
operator==(const my_input_iterator<T>& x, const my_input_iterator<U>& y)
|
||||
{
|
||||
return x.base() == y.base();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline
|
||||
bool
|
||||
operator!=(const my_input_iterator<T>& x, const my_input_iterator<U>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// basic tests
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<char *>::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<const char *>::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<int *>::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<T *>::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::move_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::move_iterator<const char *> >::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::move_iterator<int *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::move_iterator<T *> > ::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::reverse_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::reverse_iterator<const char *> >::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::reverse_iterator<int *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::reverse_iterator<T *> > ::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::__wrap_iter<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::__wrap_iter<const char *> >::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::__wrap_iter<int *> > ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::__wrap_iter<T *> > ::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::reverse_iterator<std::__wrap_iter<char *> > > ::value), "");
|
||||
|
||||
// iterators in the libc++ test suite
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<output_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<input_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<forward_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<bidirectional_iterator<char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<random_access_iterator<char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<ThrowingIterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_is_trivial_iterator<NonThrowingIterator <char *> >::value), "");
|
||||
|
||||
|
||||
// Iterator classification
|
||||
static_assert(( std::__is_input_iterator <char *>::value), "" );
|
||||
static_assert(( std::__is_forward_iterator <char *>::value), "" );
|
||||
static_assert(( std::__is_bidirectional_iterator<char *>::value), "" );
|
||||
static_assert(( std::__is_random_access_iterator<char *>::value), "" );
|
||||
static_assert((!std::__is_exactly_input_iterator<char *>::value), "" );
|
||||
|
||||
static_assert(( std::__is_input_iterator <input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_forward_iterator <input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_bidirectional_iterator<input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_random_access_iterator<input_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_exactly_input_iterator<input_iterator<char *> >::value), "" );
|
||||
|
||||
static_assert(( std::__is_input_iterator <forward_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_forward_iterator <forward_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_bidirectional_iterator<forward_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_random_access_iterator<forward_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_exactly_input_iterator<forward_iterator<char *> >::value), "" );
|
||||
|
||||
static_assert(( std::__is_input_iterator <bidirectional_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_forward_iterator <bidirectional_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_bidirectional_iterator<bidirectional_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_random_access_iterator<bidirectional_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_exactly_input_iterator<bidirectional_iterator<char *> >::value), "" );
|
||||
|
||||
static_assert(( std::__is_input_iterator <random_access_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_forward_iterator <random_access_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_bidirectional_iterator<random_access_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_random_access_iterator<random_access_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_exactly_input_iterator<random_access_iterator<char *> >::value), "" );
|
||||
|
||||
static_assert(( std::__is_input_iterator <my_input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_forward_iterator <my_input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_bidirectional_iterator<my_input_iterator<char *> >::value), "" );
|
||||
static_assert((!std::__is_random_access_iterator<my_input_iterator<char *> >::value), "" );
|
||||
static_assert(( std::__is_exactly_input_iterator<my_input_iterator<char *> >::value), "" );
|
||||
|
||||
//
|
||||
// iterators from libc++'s containers
|
||||
//
|
||||
|
||||
// string
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::vector<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::vector<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::vector<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::vector<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
// vector
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::basic_string<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::basic_string<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::basic_string<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::basic_string<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
|
||||
// Initializer list (which has no reverse iterators)
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::initializer_list<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_is_trivial_iterator<std::initializer_list<char>::const_iterator> ::value), "");
|
||||
#endif
|
||||
|
||||
}
|
79
test/libcxx/strings/iterators.exceptions.pass.cpp
Normal file
79
test/libcxx/strings/iterators.exceptions.pass.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
// <iterator>
|
||||
|
||||
// __libcpp_is_trivial_iterator<Tp>
|
||||
|
||||
// __libcpp_string_gets_noexcept_iterator determines if an iterator can be used
|
||||
// w/o worrying about whether or not certain operations can throw.
|
||||
// This gives us a "fast path for string operations"
|
||||
//
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// basic tests
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<char *>::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<const char *>::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::move_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::move_iterator<const char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<const char *> >::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::__wrap_iter<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::__wrap_iter<const char *> >::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<std::__wrap_iter<char *> > > ::value), "");
|
||||
|
||||
// iterators in the libc++ test suite
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<output_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<input_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<forward_iterator <char *> >::value), "");
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<bidirectional_iterator<char *> >::value), "");
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<random_access_iterator<char *> >::value), "");
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<ThrowingIterator <char *> >::value), "");
|
||||
|
||||
#if __has_feature(cxx_noexcept)
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value), "");
|
||||
#else
|
||||
static_assert((!std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value), "");
|
||||
#endif
|
||||
|
||||
//
|
||||
// iterators from libc++'s containers
|
||||
//
|
||||
|
||||
// string
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
// vector
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
|
||||
// Initializer list (which has no reverse iterators)
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::initializer_list<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::initializer_list<char>::const_iterator> ::value), "");
|
||||
#endif
|
||||
}
|
79
test/libcxx/strings/iterators.noexcept.pass.cpp
Normal file
79
test/libcxx/strings/iterators.noexcept.pass.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
// <iterator>
|
||||
|
||||
// __libcpp_is_trivial_iterator<Tp>
|
||||
|
||||
// __libcpp_string_gets_noexcept_iterator determines if an iterator can be used
|
||||
// w/o worrying about whether or not certain operations can throw.
|
||||
// This gives us a "fast path for string operations".
|
||||
//
|
||||
// When exceptions are disabled, all iterators should get this "fast path"
|
||||
//
|
||||
|
||||
#define _LIBCPP_NO_EXCEPTIONS
|
||||
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// basic tests
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<char *>::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<const char *>::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::move_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::move_iterator<const char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<const char *> >::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::__wrap_iter<char *> > ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::__wrap_iter<const char *> >::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::reverse_iterator<std::__wrap_iter<char *> > > ::value), "");
|
||||
|
||||
// iterators in the libc++ test suite
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<output_iterator <char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<input_iterator <char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<forward_iterator <char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<bidirectional_iterator<char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<random_access_iterator<char *> >::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<ThrowingIterator <char *> >::value), "");
|
||||
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<NonThrowingIterator <char *> >::value), "");
|
||||
|
||||
//
|
||||
// iterators from libc++'s containers
|
||||
//
|
||||
|
||||
// string
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::vector<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
// vector
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::const_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::reverse_iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::basic_string<char>::const_reverse_iterator>::value), "");
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
|
||||
// Initializer list (which has no reverse iterators)
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::initializer_list<char>::iterator> ::value), "");
|
||||
static_assert(( std::__libcpp_string_gets_noexcept_iterator<std::initializer_list<char>::const_iterator> ::value), "");
|
||||
#endif
|
||||
}
|
@ -24,7 +24,7 @@ int main()
|
||||
s.append({'a', 'b', 'c'});
|
||||
assert(s == "123abc");
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
S s("123");
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "../../input_iterator.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
|
||||
template <class S, class It>
|
||||
@ -27,6 +27,20 @@ test(S s, It first, It last, S expected)
|
||||
assert(s == expected);
|
||||
}
|
||||
|
||||
template <class S, class It>
|
||||
void
|
||||
test_exceptions(S s, It first, It last)
|
||||
{
|
||||
S aCopy = s;
|
||||
try {
|
||||
s.append(first, last);
|
||||
assert(false);
|
||||
}
|
||||
catch (...) {}
|
||||
assert(s.__invariants());
|
||||
assert(s == aCopy);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@ -87,7 +101,7 @@ int main()
|
||||
test(S("12345678901234567890"), input_iterator<const char*>(s), input_iterator<const char*>(s+52),
|
||||
S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
@ -147,4 +161,17 @@ int main()
|
||||
S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
#endif
|
||||
{ // test iterator operations that throw
|
||||
typedef std::string S;
|
||||
typedef ThrowingIterator<char> TIter;
|
||||
typedef input_iterator<TIter> IIter;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter());
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter());
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter());
|
||||
|
||||
test_exceptions(S(), TIter(s, s+10, 4, TIter::TAIncrement), TIter());
|
||||
test_exceptions(S(), TIter(s, s+10, 5, TIter::TADereference), TIter());
|
||||
test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int main()
|
||||
test(S("12345678901234567890"), "12345678901234567890",
|
||||
S("1234567890123456789012345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), "", S());
|
||||
|
@ -48,7 +48,7 @@ int main()
|
||||
test(S("12345678901234567890"), "12345678901234567890", 20,
|
||||
S("1234567890123456789012345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), "", 0, S());
|
||||
|
@ -33,7 +33,7 @@ int main()
|
||||
test(S("12345"), 'a', S("12345a"));
|
||||
test(S("12345678901234567890"), 'a', S("12345678901234567890a"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), 'a', S(1, 'a'));
|
||||
|
@ -43,7 +43,7 @@ int main()
|
||||
test(S("12345678901234567890"), 1, 'a', S("12345678901234567890a"));
|
||||
test(S("12345678901234567890"), 10, 'a', S("12345678901234567890aaaaaaaaaa"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), 0, 'a', S());
|
||||
|
@ -51,7 +51,7 @@ int main()
|
||||
test(S("12345678901234567890"), S("12345678901234567890"),
|
||||
S("1234567890123456789012345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), S(), S());
|
||||
|
@ -80,7 +80,7 @@ int main()
|
||||
test(S("12345678901234567890"), S("12345678901234567890"), 5, 10,
|
||||
S("123456789012345678906789012345"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), S(), 0, 0, S());
|
||||
|
@ -24,7 +24,7 @@ int main()
|
||||
s.assign({'a', 'b', 'c'});
|
||||
assert(s == "abc");
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
S s("123");
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "../../input_iterator.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
|
||||
template <class S, class It>
|
||||
@ -27,6 +27,20 @@ test(S s, It first, It last, S expected)
|
||||
assert(s == expected);
|
||||
}
|
||||
|
||||
template <class S, class It>
|
||||
void
|
||||
test_exceptions(S s, It first, It last)
|
||||
{
|
||||
S aCopy = s;
|
||||
try {
|
||||
s.assign(first, last);
|
||||
assert(false);
|
||||
}
|
||||
catch (...) {}
|
||||
assert(s.__invariants());
|
||||
assert(s == aCopy);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@ -147,4 +161,17 @@ int main()
|
||||
S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
#endif
|
||||
{ // test iterator operations that throw
|
||||
typedef std::string S;
|
||||
typedef ThrowingIterator<char> TIter;
|
||||
typedef input_iterator<TIter> IIter;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter());
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter());
|
||||
test_exceptions(S(), IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter());
|
||||
|
||||
test_exceptions(S(), TIter(s, s+10, 4, TIter::TAIncrement), TIter());
|
||||
test_exceptions(S(), TIter(s, s+10, 5, TIter::TADereference), TIter());
|
||||
test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int main()
|
||||
test(S("12345678901234567890"), "12345678901234567890",
|
||||
S("12345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), "", S());
|
||||
|
@ -48,7 +48,7 @@ int main()
|
||||
test(S("12345678901234567890"), "12345678901234567890", 20,
|
||||
S("12345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), "", 0, S());
|
||||
|
@ -52,7 +52,7 @@ int main()
|
||||
test(S("12345678901234567890"), S("12345678901234567890"),
|
||||
S("12345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), S(), S());
|
||||
|
@ -43,7 +43,7 @@ int main()
|
||||
test(S("12345678901234567890"), 1, 'a', S(1, 'a'));
|
||||
test(S("12345678901234567890"), 10, 'a', S(10, 'a'));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), 0, 'a', S());
|
||||
|
@ -51,7 +51,7 @@ int main()
|
||||
test(S("12345678901234567890"), S("12345678901234567890"),
|
||||
S("12345678901234567890"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), S(), S());
|
||||
|
@ -80,7 +80,7 @@ int main()
|
||||
test(S("12345678901234567890"), S("12345678901234567890"), 5, 10,
|
||||
S("6789012345"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(), S(), 0, 0, S());
|
||||
|
@ -56,7 +56,7 @@ int main()
|
||||
test(s, s.begin()+5, 'B', S("a567AB1432dcb"));
|
||||
test(s, s.begin()+6, 'C', S("a567ABC1432dcb"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
S s;
|
||||
|
@ -29,7 +29,7 @@ int main()
|
||||
assert(i - s.begin() == 3);
|
||||
assert(s == "123abc456");
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
S s("123456");
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "../../input_iterator.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
|
||||
template <class S, class It>
|
||||
@ -33,6 +33,21 @@ test(S s, typename S::difference_type pos, It first, It last, S expected)
|
||||
assert(s == expected);
|
||||
}
|
||||
|
||||
template <class S, class It>
|
||||
void
|
||||
test_exceptions(S s, typename S::difference_type pos, It first, It last)
|
||||
{
|
||||
typename S::const_iterator p = s.cbegin() + pos;
|
||||
S aCopy = s;
|
||||
try {
|
||||
s.insert(p, first, last);
|
||||
assert(false);
|
||||
}
|
||||
catch (...) {}
|
||||
assert(s.__invariants());
|
||||
assert(s == aCopy);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@ -80,7 +95,7 @@ int main()
|
||||
test(S("12345678901234567890"), 20, input_iterator<const char*>(s), input_iterator<const char*>(s+52),
|
||||
S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
@ -127,6 +142,19 @@ int main()
|
||||
S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
#endif
|
||||
{ // test iterator operations that throw
|
||||
typedef std::string S;
|
||||
typedef ThrowingIterator<char> TIter;
|
||||
typedef input_iterator<TIter> IIter;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
test_exceptions(S(), 0, IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter());
|
||||
test_exceptions(S(), 0, IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter());
|
||||
test_exceptions(S(), 0, IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter());
|
||||
|
||||
test_exceptions(S(), 0, TIter(s, s+10, 4, TIter::TAIncrement), TIter());
|
||||
test_exceptions(S(), 0, TIter(s, s+10, 5, TIter::TADereference), TIter());
|
||||
test_exceptions(S(), 0, TIter(s, s+10, 6, TIter::TAComparison), TIter());
|
||||
}
|
||||
#if _LIBCPP_DEBUG >= 1
|
||||
{
|
||||
std::string v;
|
||||
|
@ -101,7 +101,7 @@ int main()
|
||||
test(S("abcdefghijklmnopqrst"), 20, 10, '1', S("abcdefghijklmnopqrst1111111111"));
|
||||
test(S("abcdefghijklmnopqrst"), 20, 20, '1', S("abcdefghijklmnopqrst11111111111111111111"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, 0, '1', S(""));
|
||||
|
@ -124,7 +124,7 @@ int main()
|
||||
test(S("abcdefghijklmnopqrst"), 21, "1234567890", S("can't happen"));
|
||||
test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", S("can't happen"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, "", S(""));
|
||||
|
@ -365,7 +365,7 @@ int main()
|
||||
test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 19, S("can't happen"));
|
||||
test(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, "", 0, S(""));
|
||||
|
@ -125,7 +125,7 @@ int main()
|
||||
test(S("abcdefghijklmnopqrst"), 21, 10, '1', S("can't happen"));
|
||||
test(S("abcdefghijklmnopqrst"), 21, 20, '1', S("can't happen"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, 0, '1', S(""));
|
||||
|
@ -124,7 +124,7 @@ int main()
|
||||
test(S("abcdefghijklmnopqrst"), 21, S("1234567890"), S("can't happen"));
|
||||
test(S("abcdefghijklmnopqrst"), 21, S("12345678901234567890"), S("can't happen"));
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test(S(""), 0, S(""), S(""));
|
||||
|
@ -1746,7 +1746,7 @@ int main()
|
||||
test29<S>();
|
||||
test30<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -24,7 +24,7 @@ int main()
|
||||
s.replace(s.cbegin() + 3, s.cbegin() + 6, {'a', 'b', 'c'});
|
||||
assert(s == "123abc456");
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
S s("123def456");
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "min_allocator.h"
|
||||
#include "test_iterators.h"
|
||||
|
||||
template <class S, class It>
|
||||
void
|
||||
@ -34,6 +35,22 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, It f, It l, S ex
|
||||
assert(s.size() == old_size - xlen + rlen);
|
||||
}
|
||||
|
||||
template <class S, class It>
|
||||
void
|
||||
test_exceptions(S s, typename S::size_type pos1, typename S::size_type n1, It f, It l)
|
||||
{
|
||||
typename S::const_iterator first = s.begin() + pos1;
|
||||
typename S::const_iterator last = s.begin() + pos1 + n1;
|
||||
S aCopy = s;
|
||||
try {
|
||||
s.replace(first, last, f, l);
|
||||
assert(false);
|
||||
}
|
||||
catch (...) {}
|
||||
assert(s.__invariants());
|
||||
assert(s == aCopy);
|
||||
}
|
||||
|
||||
const char* str = "12345678901234567890";
|
||||
|
||||
template <class S>
|
||||
@ -959,7 +976,7 @@ int main()
|
||||
test7<S>();
|
||||
test8<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
@ -973,4 +990,17 @@ int main()
|
||||
test8<S>();
|
||||
}
|
||||
#endif
|
||||
{ // test iterator operations that throw
|
||||
typedef std::string S;
|
||||
typedef ThrowingIterator<char> TIter;
|
||||
typedef input_iterator<TIter> IIter;
|
||||
const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter());
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter());
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter());
|
||||
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 4, TIter::TAIncrement), TIter());
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 5, TIter::TADereference), TIter());
|
||||
test_exceptions(S("abcdefghijklmnopqrst"), 10, 5, TIter(s, s+10, 6, TIter::TAComparison), TIter());
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -959,7 +959,7 @@ int main()
|
||||
test7<S>();
|
||||
test8<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -275,7 +275,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -274,7 +274,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -365,7 +365,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -1308,7 +1308,7 @@ int main()
|
||||
test10<S>();
|
||||
test11<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -364,7 +364,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -362,7 +362,7 @@ int main()
|
||||
test1<S>();
|
||||
test2<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -5903,7 +5903,7 @@ int main()
|
||||
test54<S>();
|
||||
test55<S>();
|
||||
}
|
||||
#if __cplusplus >= 201103L
|
||||
#if TEST_STD_VER >= 11
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
|
||||
test0<S>();
|
||||
|
@ -11,8 +11,11 @@
|
||||
#define ITERATORS_H
|
||||
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
|
||||
#define DELETE_FUNCTION = delete
|
||||
#else
|
||||
@ -324,6 +327,202 @@ inline Iter base(random_access_iterator<Iter> i) { return i.base(); }
|
||||
template <class Iter> // everything else
|
||||
inline 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)
|
||||
throw std::runtime_error ("throw from iterator assignment");
|
||||
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)
|
||||
throw std::runtime_error ("throw from iterator dereference");
|
||||
else
|
||||
--index_;
|
||||
}
|
||||
return *current_;
|
||||
}
|
||||
|
||||
ThrowingIterator & operator++()
|
||||
{
|
||||
if (action_ == TAIncrement)
|
||||
{
|
||||
if (index_ == 0)
|
||||
throw std::runtime_error ("throw from iterator increment");
|
||||
else
|
||||
--index_;
|
||||
}
|
||||
++current_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ThrowingIterator operator++(int)
|
||||
{
|
||||
ThrowingIterator temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
ThrowingIterator & operator--()
|
||||
{
|
||||
if (action_ == TADecrement)
|
||||
{
|
||||
if (index_ == 0)
|
||||
throw std::runtime_error ("throw from iterator decrement");
|
||||
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)
|
||||
throw std::runtime_error ("throw from iterator comparison");
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user