[libc++] Deprecate std::iterator and remove it as a base class

C++17 deprecated std::iterator and removed it as a base class for all
iterator adaptors. We implement that change, but we still provide a way
to inherit from std::iterator in the few cases where doing otherwise
would be an ABI break.

Supersedes D101729 and the std::iterator base parts of D103101 and D102657.

Differential Revision: https://reviews.llvm.org/D103171
This commit is contained in:
Louis Dionne 2021-05-25 18:15:58 -04:00
parent 5efc3bfd32
commit 1055cb91b4
19 changed files with 269 additions and 134 deletions

View File

@ -94,6 +94,9 @@
# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
// Give reverse_iterator<T> one data member of type T, not two.
// Also, in C++17 and later, don't derive iterator types from std::iterator.
# define _LIBCPP_ABI_NO_ITERATOR_BASES
// Use the smallest possible integer type to represent the index of the variant.
// Previously libc++ used "unsigned int" exclusively.
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION

View File

@ -27,17 +27,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR)
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _OutputIterator, class _Tp>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 raw_storage_iterator
: public iterator<output_iterator_tag,
_Tp, // purposefully not C++03
ptrdiff_t, // purposefully not C++03
_Tp*, // purposefully not C++03
raw_storage_iterator<_OutputIterator, _Tp>&> // purposefully not C++03
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
private:
_OutputIterator __x_;
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
_LIBCPP_INLINE_VISIBILITY explicit raw_storage_iterator(_OutputIterator __x) : __x_(__x) {}
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator*() {return *this;}
_LIBCPP_INLINE_VISIBILITY raw_storage_iterator& operator=(const _Tp& __element)

View File

@ -93,7 +93,7 @@ template<class I>
template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator
struct iterator // deprecated in C++17
{
typedef T value_type;
typedef Distance difference_type;
@ -137,7 +137,7 @@ namespace ranges {
template <class Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<Iterator>::iterator_category,
: public iterator<typename iterator_traits<Iterator>::iterator_category, // until C++17
typename iterator_traits<Iterator>::value_type,
typename iterator_traits<Iterator>::difference_type,
typename iterator_traits<Iterator>::pointer,
@ -343,7 +343,7 @@ constexpr move_iterator<Iterator> make_move_iterator(const Iterator& i);
template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator
: public iterator<input_iterator_tag, T, Distance, const T*, const T&>
: public iterator<input_iterator_tag, T, Distance, const T*, const T&> // until C++17
{
public:
typedef charT char_type;
@ -370,7 +370,7 @@ bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
template <class T, class charT = char, class traits = char_traits<charT> >
class ostream_iterator
: public iterator<output_iterator_tag, void, void, void ,void>
: public iterator<output_iterator_tag, void, void, void ,void> // until C++17
{
public:
typedef charT char_type;
@ -390,7 +390,7 @@ public:
template<class charT, class traits = char_traits<charT> >
class istreambuf_iterator
: public iterator<input_iterator_tag, charT,
: public iterator<input_iterator_tag, charT, // until C++17
typename traits::off_type, unspecified,
charT>
{
@ -423,7 +423,7 @@ bool operator!=(const istreambuf_iterator<charT,traits>& a,
template <class charT, class traits = char_traits<charT> >
class ostreambuf_iterator
: public iterator<output_iterator_tag, void, void, void, void>
: public iterator<output_iterator_tag, void, void, void, void> // until C++17
{
public:
typedef charT char_type;
@ -509,7 +509,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template<class _Category, class _Tp, class _Distance = ptrdiff_t,
class _Pointer = _Tp*, class _Reference = _Tp&>
struct _LIBCPP_TEMPLATE_VIS iterator
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 iterator
{
typedef _Tp value_type;
typedef _Distance difference_type;
@ -628,16 +628,22 @@ template <class _Tp>
struct __is_stashing_iterator<_Tp, typename __void_t<typename _Tp::__stashing_iterator_tag>::type>
: true_type {};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Iter>
class _LIBCPP_TEMPLATE_VIS reverse_iterator
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<typename iterator_traits<_Iter>::iterator_category,
typename iterator_traits<_Iter>::value_type,
typename iterator_traits<_Iter>::difference_type,
typename iterator_traits<_Iter>::pointer,
typename iterator_traits<_Iter>::reference>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
private:
/*mutable*/ _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break
#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
_Iter __t; // no longer used as of LWG #2360, not removed due to ABI break
#endif
static_assert(!__is_stashing_iterator<_Iter>::value,
"The specified iterator type cannot be used with reverse_iterator; "
@ -653,12 +659,15 @@ public:
typedef _If<__is_cpp17_random_access_iterator<_Iter>::value,
random_access_iterator_tag,
typename iterator_traits<_Iter>::iterator_category> iterator_category;
typedef typename iterator_traits<_Iter>::value_type value_type;
#if _LIBCPP_STD_VER > 17
typedef _If<__is_cpp17_random_access_iterator<_Iter>::value,
random_access_iterator_tag,
bidirectional_iterator_tag> iterator_concept;
#endif
#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator() : __t(), current() {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
@ -670,6 +679,19 @@ public:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator& operator=(const reverse_iterator<_Up>& __u)
{ __t = current = __u.base(); return *this; }
#else
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator() : current() {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
explicit reverse_iterator(_Iter __x) : current(__x) {}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator(const reverse_iterator<_Up>& __u) : current(__u.base()) {}
template <class _Up>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator& operator=(const reverse_iterator<_Up>& __u)
{ current = __u.base(); return *this; }
#endif
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
_Iter base() const {return current;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
@ -780,17 +802,22 @@ reverse_iterator<_Iter> make_reverse_iterator(_Iter __i)
}
#endif
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Container>
class _LIBCPP_TEMPLATE_VIS back_insert_iterator
: public iterator<output_iterator_tag,
void,
void,
void,
void>
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
protected:
_Container* container;
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef _Container container_type;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit back_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {}
@ -813,17 +840,22 @@ back_inserter(_Container& __x)
return back_insert_iterator<_Container>(__x);
}
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Container>
class _LIBCPP_TEMPLATE_VIS front_insert_iterator
: public iterator<output_iterator_tag,
void,
void,
void,
void>
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
protected:
_Container* container;
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef _Container container_type;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit front_insert_iterator(_Container& __x) : container(_VSTD::addressof(__x)) {}
@ -846,18 +878,23 @@ front_inserter(_Container& __x)
return front_insert_iterator<_Container>(__x);
}
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Container>
class _LIBCPP_TEMPLATE_VIS insert_iterator
: public iterator<output_iterator_tag,
void,
void,
void,
void>
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
protected:
_Container* container;
typename _Container::iterator iter;
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef _Container container_type;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 insert_iterator(_Container& __x, typename _Container::iterator __i)
@ -881,12 +918,21 @@ inserter(_Container& __x, typename _Container::iterator __i)
return insert_iterator<_Container>(__x, __i);
}
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Tp, class _CharT = char,
class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t>
class _LIBCPP_TEMPLATE_VIS istream_iterator
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<input_iterator_tag, _Tp, _Distance, const _Tp*, const _Tp&>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
public:
typedef input_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
typedef _CharT char_type;
typedef _Traits traits_type;
typedef basic_istream<_CharT,_Traits> istream_type;
@ -943,10 +989,14 @@ operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
return !(__x == __y);
}
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Tp, class _CharT = char, class _Traits = char_traits<_CharT> >
class _LIBCPP_TEMPLATE_VIS ostream_iterator
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
@ -982,13 +1032,22 @@ public:
_LIBCPP_INLINE_VISIBILITY ostream_iterator& operator++(int) {return *this;}
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template<class _CharT, class _Traits>
class _LIBCPP_TEMPLATE_VIS istreambuf_iterator
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<input_iterator_tag, _CharT,
typename _Traits::off_type, _CharT*,
_CharT>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
public:
typedef input_iterator_tag iterator_category;
typedef _CharT value_type;
typedef typename _Traits::off_type difference_type;
typedef _CharT* pointer;
typedef _CharT reference;
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename _Traits::int_type int_type;
@ -1052,10 +1111,14 @@ bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a,
const istreambuf_iterator<_CharT,_Traits>& __b)
{return !__a.equal(__b);}
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _CharT, class _Traits>
class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator
#if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
: public iterator<output_iterator_tag, void, void, void, void>
#endif
{
_LIBCPP_SUPPRESS_DEPRECATED_POP
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;

View File

@ -154,11 +154,7 @@ bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // constexpr
template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,
T, // purposefully not C++03
ptrdiff_t, // purposefully not C++03
T*, // purposefully not C++03
raw_storage_iterator&> // purposefully not C++03
: public iterator<output_iterator_tag, void, void, void, void> // until C++17
{
public:
explicit raw_storage_iterator(OutputIterator x);

View File

@ -24,26 +24,41 @@
#include <iterator>
struct OtherTag : std::input_iterator_tag {};
struct OtherTagTwo : std::output_iterator_tag {};
struct MyIter : std::iterator<std::random_access_iterator_tag, char> {
using iterator_concept = int;
};
struct MyIter2 : std::iterator<OtherTag, char> {
struct MyIter {
using iterator_category = std::random_access_iterator_tag;
using iterator_concept = int;
using value_type = char;
using difference_type = std::ptrdiff_t;
using pointer = char*;
using reference = char&;
};
struct MyIter2 {
using iterator_category = OtherTag;
using value_type = char;
using difference_type = std::ptrdiff_t;
using pointer = char*;
using reference = char&;
};
struct MyIter3 {};
struct Empty {};
struct EmptyWithSpecial {};
namespace std {
template <>
struct iterator_traits<MyIter3>
: std::iterator<OtherTagTwo, char> {};
struct std::iterator_traits<MyIter3> {
using iterator_category = OtherTagTwo;
using value_type = char;
using difference_type = std::ptrdiff_t;
using pointer = char*;
using reference = char&;
};
template <>
struct iterator_traits<EmptyWithSpecial> {
struct std::iterator_traits<EmptyWithSpecial> {
// empty non-default.
};
} // namespace std
int main(int, char**) {
// If the qualified-id ITER_TRAITS(I)::iterator_concept is valid and names a type,

View File

@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// 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
// ITER_TRAITS(I)
// For a type I, let ITER_TRAITS(I) denote the type I if iterator_traits<I> names
// a specialization generated from the primary template. Otherwise,
// ITER_TRAITS(I) denotes iterator_traits<I>.
#include <iterator>
#include <type_traits>
#include "test_iterators.h"
struct A : random_access_iterator<int*> {};
struct B : random_access_iterator<int*> {};
struct C : random_access_iterator<int*> {};
struct D : random_access_iterator<int*> {};
template<> struct std::iterator_traits<B> {};
template<> struct std::iterator_traits<C> : std::iterator_traits<A> {};
template<> struct std::iterator_traits<D> : std::iterator_traits<int*> {};
static_assert(std::is_same<std::_ITER_TRAITS<int*>, std::iterator_traits<int*>>::value, "");
static_assert(std::is_same<std::_ITER_TRAITS<A>, A>::value, "");
static_assert(std::is_same<std::_ITER_TRAITS<B>, std::iterator_traits<B>>::value, "");
static_assert(std::is_same<std::_ITER_TRAITS<C>, std::iterator_traits<C>>::value, "");
static_assert(std::is_same<std::_ITER_TRAITS<D>, std::iterator_traits<D>>::value, "");

View File

@ -1,47 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
// ITER_TRAITS(I)
// For a type I, let ITER_TRAITS(I) denote the type I if iterator_traits<I> names
// a specialization generated from the primary template. Otherwise,
// ITER_TRAITS(I) denotes iterator_traits<I>.
#include "test_macros.h"
#include <iterator>
struct MyIter : std::iterator<std::random_access_iterator_tag, char> {};
struct MyIter2 : std::iterator<std::random_access_iterator_tag, char> {};
struct MyIter3 : std::iterator<std::random_access_iterator_tag, char> {};
namespace std {
template <>
struct iterator_traits<MyIter>
: iterator_traits<std::iterator<std::random_access_iterator_tag, char> > {};
template <>
struct iterator_traits<MyIter2>
: std::iterator<std::random_access_iterator_tag, char> {};
} // namespace std
int main(int, char**) {
ASSERT_SAME_TYPE(std::_ITER_TRAITS<char*>, std::iterator_traits<char*>);
{
using ClassIter = std::reverse_iterator<char*>;
ASSERT_SAME_TYPE(std::_ITER_TRAITS<ClassIter>, ClassIter);
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter3>, MyIter3);
}
{
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter>, std::iterator_traits<MyIter>);
ASSERT_SAME_TYPE(std::_ITER_TRAITS<MyIter2>, std::iterator_traits<MyIter2>);
}
return 0;
}

View File

@ -0,0 +1,15 @@
//===----------------------------------------------------------------------===//
//
// 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
// std::iterator
#include <iterator>
std::iterator<std::input_iterator_tag, char> it; // expected-warning-re {{'iterator<{{.+}}>' is deprecated}}

View File

@ -19,6 +19,8 @@
// typedef Category iterator_category;
// };
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
#include <iterator>
#include <type_traits>

View File

@ -52,6 +52,11 @@ test()
static_assert((std::is_same<typename R::reference, void>::value), "");
static_assert((std::is_same<typename R::pointer, void>::value), "");
static_assert((std::is_same<typename R::iterator_category, std::output_iterator_tag>::value), "");
#if TEST_STD_VER <= 14
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, R>::value), "");
#endif
}
int main(int, char**)

View File

@ -53,6 +53,11 @@ test()
static_assert((std::is_same<typename R::reference, void>::value), "");
static_assert((std::is_same<typename R::pointer, void>::value), "");
static_assert((std::is_same<typename R::iterator_category, std::output_iterator_tag>::value), "");
#if TEST_STD_VER <= 14
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, R>::value), "");
#endif
}
int main(int, char**)

View File

@ -56,6 +56,11 @@ test()
static_assert((std::is_same<typename R::reference, void>::value), "");
static_assert((std::is_same<typename R::pointer, void>::value), "");
static_assert((std::is_same<typename R::iterator_category, std::output_iterator_tag>::value), "");
#if TEST_STD_VER <= 14
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, R>::value), "");
#endif
}
int main(int, char**)

View File

@ -49,6 +49,11 @@ test()
static_assert((std::is_same<typename R::difference_type, typename T::difference_type>::value), "");
static_assert((std::is_same<typename R::reference, typename T::reference>::value), "");
static_assert((std::is_same<typename R::pointer, typename std::iterator_traits<It>::pointer>::value), "");
#if TEST_STD_VER <= 14
typedef std::iterator<typename T::iterator_category, typename T::value_type> iterator_base;
static_assert((std::is_base_of<iterator_base, R>::value), "");
#endif
#if TEST_STD_VER > 17
if constexpr (std::is_same_v<typename T::iterator_category, std::contiguous_iterator_tag>) {
static_assert((std::is_same<typename R::iterator_category, std::random_access_iterator_tag>::value), "");

View File

@ -10,9 +10,7 @@
// template <class T, class charT = char, class traits = char_traits<charT>,
// class Distance = ptrdiff_t>
// class istream_iterator
// : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
// {
// class istream_iterator {
// public:
// typedef charT char_type;
// typedef traits traits_type;
@ -40,41 +38,41 @@
int main(int, char**)
{
{
typedef std::istream_iterator<double> I1; // double is trivially destructible
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I1,
std::iterator<std::input_iterator_tag, double, std::ptrdiff_t,
const double*, const double&> >::value), "");
#else
typedef std::iterator<std::input_iterator_tag, double, std::ptrdiff_t, double const*, double const&> iterator_base;
static_assert((std::is_base_of<iterator_base, I1>::value), "");
#endif
static_assert((std::is_same<I1::iterator_category, std::input_iterator_tag>::value), "");
static_assert((std::is_same<I1::value_type, double>::value), "");
static_assert((std::is_same<I1::difference_type, std::ptrdiff_t>::value), "");
static_assert((std::is_same<I1::pointer, const double*>::value), "");
static_assert((std::is_same<I1::reference, const double&>::value), "");
#endif
static_assert((std::is_same<I1::char_type, char>::value), "");
static_assert((std::is_same<I1::traits_type, std::char_traits<char> >::value), "");
static_assert((std::is_same<I1::istream_type, std::istream>::value), "");
static_assert( std::is_trivially_copy_constructible<I1>::value, "");
static_assert( std::is_trivially_destructible<I1>::value, "");
}
{
typedef std::istream_iterator<unsigned, wchar_t> I2; // unsigned is trivially destructible
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I2,
std::iterator<std::input_iterator_tag, unsigned, std::ptrdiff_t,
const unsigned*, const unsigned&> >::value), "");
#else
typedef std::iterator<std::input_iterator_tag, unsigned, std::ptrdiff_t, const unsigned*, const unsigned&> iterator_base;
static_assert((std::is_base_of<iterator_base, I2>::value), "");
#endif
static_assert((std::is_same<I2::iterator_category, std::input_iterator_tag>::value), "");
static_assert((std::is_same<I2::value_type, unsigned>::value), "");
static_assert((std::is_same<I2::difference_type, std::ptrdiff_t>::value), "");
static_assert((std::is_same<I2::pointer, const unsigned*>::value), "");
static_assert((std::is_same<I2::reference, const unsigned&>::value), "");
#endif
static_assert((std::is_same<I2::char_type, wchar_t>::value), "");
static_assert((std::is_same<I2::traits_type, std::char_traits<wchar_t> >::value), "");
static_assert((std::is_same<I2::istream_type, std::wistream>::value), "");
static_assert( std::is_trivially_copy_constructible<I2>::value, "");
static_assert( std::is_trivially_destructible<I2>::value, "");
}
typedef std::istream_iterator<std::string> I3; // string is NOT trivially destructible
static_assert(!std::is_trivially_copy_constructible<I3>::value, "");

View File

@ -9,11 +9,7 @@
// <iterator>
// template<class charT, class traits = char_traits<charT> >
// class istreambuf_iterator
// : public iterator<input_iterator_tag, charT,
// typename traits::off_type, charT*,
// charT>
// {
// class istreambuf_iterator {
// public:
// ...
// proxy operator++(int);

View File

@ -9,11 +9,7 @@
// <iterator>
// template<class charT, class traits = char_traits<charT> >
// class istreambuf_iterator
// : public iterator<input_iterator_tag, charT,
// typename traits::off_type, unspecified,
// charT>
// {
// class istreambuf_iterator {
// public:
// typedef charT char_type;
// typedef traits traits_type;
@ -33,7 +29,12 @@
int main(int, char**)
{
{
typedef std::istreambuf_iterator<char> I1;
#if TEST_STD_VER <= 14
typedef std::iterator<std::input_iterator_tag, char, std::char_traits<char>::off_type, char*, char> iterator_base;
static_assert((std::is_base_of<iterator_base, I1>::value), "");
#endif
static_assert((std::is_same<I1::iterator_category, std::input_iterator_tag>::value), "");
static_assert((std::is_same<I1::value_type, char>::value), "");
static_assert((std::is_same<I1::difference_type, std::char_traits<char>::off_type>::value), "");
@ -47,8 +48,14 @@ int main(int, char**)
static_assert((std::is_nothrow_default_constructible<I1>::value), "" );
static_assert((std::is_trivially_copy_constructible<I1>::value), "" );
static_assert((std::is_trivially_destructible<I1>::value), "" );
}
{
typedef std::istreambuf_iterator<wchar_t> I2;
#if TEST_STD_VER <= 14
typedef std::iterator<std::input_iterator_tag, wchar_t, std::char_traits<wchar_t>::off_type, wchar_t*, wchar_t> iterator_base;
static_assert((std::is_base_of<iterator_base, I2>::value), "");
#endif
static_assert((std::is_same<I2::iterator_category, std::input_iterator_tag>::value), "");
static_assert((std::is_same<I2::value_type, wchar_t>::value), "");
static_assert((std::is_same<I2::difference_type, std::char_traits<wchar_t>::off_type>::value), "");
@ -62,6 +69,7 @@ int main(int, char**)
static_assert((std::is_nothrow_default_constructible<I2>::value), "" );
static_assert((std::is_trivially_copy_constructible<I2>::value), "" );
static_assert((std::is_trivially_destructible<I2>::value), "" );
}
return 0;
}

View File

@ -10,9 +10,7 @@
// template <class T, class charT = char, class traits = char_traits<charT>,
// class Distance = ptrdiff_t>
// class ostream_iterator
// : public iterator<output_iterator_tag, void, void, void, void>
// {
// class ostream_iterator {
// public:
// typedef charT char_type;
// typedef traits traits_type;
@ -27,11 +25,12 @@
int main(int, char**)
{
{
typedef std::ostream_iterator<double> I1;
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I1,
std::iterator<std::output_iterator_tag, void, void, void, void> >::value), "");
#else
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, I1>::value), "");
#endif
static_assert((std::is_same<I1::iterator_category, std::output_iterator_tag>::value), "");
static_assert((std::is_same<I1::value_type, void>::value), "");
#if TEST_STD_VER <= 17
@ -41,15 +40,17 @@ int main(int, char**)
#endif
static_assert((std::is_same<I1::pointer, void>::value), "");
static_assert((std::is_same<I1::reference, void>::value), "");
#endif
static_assert((std::is_same<I1::char_type, char>::value), "");
static_assert((std::is_same<I1::traits_type, std::char_traits<char> >::value), "");
static_assert((std::is_same<I1::ostream_type, std::ostream>::value), "");
}
{
typedef std::ostream_iterator<unsigned, wchar_t> I2;
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I2,
std::iterator<std::output_iterator_tag, void, void, void, void> >::value), "");
#else
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, I2>::value), "");
#endif
static_assert((std::is_same<I2::iterator_category, std::output_iterator_tag>::value), "");
static_assert((std::is_same<I2::value_type, void>::value), "");
#if TEST_STD_VER <= 17
@ -59,10 +60,10 @@ int main(int, char**)
#endif
static_assert((std::is_same<I2::pointer, void>::value), "");
static_assert((std::is_same<I2::reference, void>::value), "");
#endif
static_assert((std::is_same<I2::char_type, wchar_t>::value), "");
static_assert((std::is_same<I2::traits_type, std::char_traits<wchar_t> >::value), "");
static_assert((std::is_same<I2::ostream_type, std::wostream>::value), "");
}
return 0;
}

View File

@ -9,9 +9,7 @@
// <iterator>
// template <class charT, class traits = char_traits<charT> >
// class ostreambuf_iterator
// : public iterator<output_iterator_tag, void, void, void, void>
// {
// class ostreambuf_iterator {
// public:
// typedef charT char_type;
// typedef traits traits_type;
@ -28,11 +26,12 @@
int main(int, char**)
{
{
typedef std::ostreambuf_iterator<char> I1;
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I1,
std::iterator<std::output_iterator_tag, void, void, void, void> >::value), "");
#else
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, I1>::value), "");
#endif
static_assert((std::is_same<I1::iterator_category, std::output_iterator_tag>::value), "");
static_assert((std::is_same<I1::value_type, void>::value), "");
#if TEST_STD_VER <= 17
@ -42,17 +41,18 @@ int main(int, char**)
#endif
static_assert((std::is_same<I1::pointer, void>::value), "");
static_assert((std::is_same<I1::reference, void>::value), "");
#endif
static_assert((std::is_same<I1::char_type, char>::value), "");
static_assert((std::is_same<I1::traits_type, std::char_traits<char> >::value), "");
static_assert((std::is_same<I1::streambuf_type, std::streambuf>::value), "");
static_assert((std::is_same<I1::ostream_type, std::ostream>::value), "");
}
{
typedef std::ostreambuf_iterator<wchar_t> I2;
#if TEST_STD_VER <= 14
static_assert((std::is_convertible<I2,
std::iterator<std::output_iterator_tag, void, void, void, void> >::value), "");
#else
typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_base;
static_assert((std::is_base_of<iterator_base, I2>::value), "");
#endif
static_assert((std::is_same<I2::iterator_category, std::output_iterator_tag>::value), "");
static_assert((std::is_same<I2::value_type, void>::value), "");
#if TEST_STD_VER <= 17
@ -62,11 +62,11 @@ int main(int, char**)
#endif
static_assert((std::is_same<I2::pointer, void>::value), "");
static_assert((std::is_same<I2::reference, void>::value), "");
#endif
static_assert((std::is_same<I2::char_type, wchar_t>::value), "");
static_assert((std::is_same<I2::traits_type, std::char_traits<wchar_t> >::value), "");
static_assert((std::is_same<I2::streambuf_type, std::wstreambuf>::value), "");
static_assert((std::is_same<I2::ostream_type, std::wostream>::value), "");
}
return 0;
}

View File

@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
// raw_storage_iterator associated types
#include <memory>
#include <type_traits>
struct T;
typedef T* OutputIt;
typedef std::raw_storage_iterator<OutputIt, T> It;
static_assert(std::is_same<It::iterator_category, std::output_iterator_tag>::value, "");
static_assert(std::is_same<It::value_type, void>::value, "");
static_assert(std::is_same<It::difference_type, void>::value, "");
static_assert(std::is_same<It::pointer, void>::value, "");
static_assert(std::is_same<It::reference, void>::value, "");