1 // { dg-do compile } 2 // { dg-require-effective-target c++11 } 3 // { dg-options "-O3 -fno-tree-dce" } 4 5 template < typename, typename, template < typename > class _Op, typename... _Args > struct __detector { 6 using type = _Op< _Args... >; 7 }; 8 template < typename _Default, template < typename > class _Op, typename... _Args > using __detected_or = __detector< _Default, void, _Op, _Args... >; 9 template < typename _Default, template < typename > class _Op, typename... _Args > using __detected_or_t = typename __detected_or< _Default, _Op, _Args... >::type; 10 template < typename, typename > struct __replace_first_arg; 11 template < template < typename > class _Template, typename _Up, typename _Tp, typename... _Types > struct __replace_first_arg< _Template< _Tp, _Types... >, _Up > { 12 using type = _Template< _Up >; 13 }; 14 template < class > class min_pointer; 15 class MoveOnly; 16 struct pointer_traits { 17 template < typename _Up > using rebind = typename __replace_first_arg< min_pointer< int >, _Up >::type; 18 }; 19 template < typename _Iterator > class __normal_iterator { 20 public: __normal_iterator(_Iterator); 21 }; 22 struct __allocator_traits_base { 23 template < typename _Tp > using __pointer = typename _Tp::pointer; 24 }; 25 template < typename _Alloc > struct allocator_traits : __allocator_traits_base { 26 typedef typename _Alloc::value_type value_type; 27 using pointer = __detected_or_t< value_type, __pointer, _Alloc >; 28 template < typename _Tp > struct _Ptr { 29 using type = pointer_traits::rebind< _Tp >; 30 }; 31 using const_pointer = typename _Ptr< value_type >::type; 32 using size_type = int; 33 static pointer allocate(_Alloc __a, size_type __n) { 34 return __a.allocate(__n); 35 } 36 }; 37 template < typename _ForwardIterator, typename _Allocator > void _Destroy(_ForwardIterator __first, _ForwardIterator __last, _Allocator) { 38 for (; 39 __first != __last; 40 ++__first) ; 41 } 42 template < typename _InputIterator, typename _ForwardIterator, typename _Allocator > _ForwardIterator __uninitialized_copy_a(_InputIterator, _ForwardIterator, _Allocator); 43 template < typename _InputIterator, typename _ForwardIterator, typename _Allocator > _ForwardIterator __uninitialized_move_if_noexcept_a(_InputIterator __last, _ForwardIterator __result, _Allocator __alloc) { 44 return __uninitialized_copy_a(__last, __result, __alloc); 45 } 46 template < typename _ForwardIterator, typename _Size, typename _Allocator > _ForwardIterator __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, _Allocator) { 47 for (; 48 __n; 49 --__n, ++__first) ; 50 return __first; 51 } 52 template < typename _Alloc > struct _Vector_base { 53 typedef _Alloc _Tp_alloc_type; 54 typedef typename _Tp_alloc_type ::pointer pointer; 55 struct _Vector_impl_data { 56 pointer _M_start; 57 pointer _M_finish; 58 pointer _M_end_of_storage; 59 }; 60 struct _Vector_impl : _Tp_alloc_type, _Vector_impl_data { 61 _Vector_impl(_Tp_alloc_type) { 62 } 63 }; 64 _Vector_base(long __n, _Alloc __a) : _M_impl(__a) { 65 _M_impl._M_end_of_storage = _M_impl._M_start + __n; 66 } 67 _Vector_impl _M_impl; 68 pointer _M_allocate(long __n) { 69 return __n ? allocator_traits< _Tp_alloc_type >::allocate(_M_impl, __n) : pointer(); 70 } 71 }; 72 template < typename, typename _Alloc > class vector : _Vector_base< _Alloc > { 73 public: typedef typename _Alloc::pointer pointer; 74 typedef __normal_iterator< typename allocator_traits< _Alloc >::const_pointer > const_iterator; 75 typedef _Alloc allocator_type; 76 vector(long __n, allocator_type __a = allocator_type()) : _Vector_base< _Alloc >(__n, __a) { 77 this->_M_impl._M_finish = __uninitialized_default_n_a(this->_M_impl._M_start, __n, 0); 78 } 79 ~vector() { 80 _Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, 0); 81 } 82 const_iterator cbegin() { 83 return this->_M_impl._M_start; 84 } 85 typename _Alloc::value_type operator[](long) { 86 return *this->_M_impl._M_start; 87 } 88 void insert(const_iterator, MoveOnly &&) { 89 if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) ; 90 else _M_realloc_insert(); 91 } 92 template < typename... > void _M_realloc_insert(); 93 }; 94 template < typename _Tp, typename _Alloc > template < typename... > void vector< _Tp, _Alloc >::_M_realloc_insert() { 95 long __trans_tmp_6 = this->_M_impl._M_finish - this->_M_impl._M_start; 96 pointer __old_start = this->_M_impl._M_start; 97 pointer __old_finish = this->_M_impl._M_finish; 98 pointer __new_start(this->_M_allocate(__trans_tmp_6)); 99 pointer __new_finish = __uninitialized_move_if_noexcept_a(__old_finish, __new_finish, 0); 100 _Destroy(__old_start, __old_finish, 0); 101 this->_M_impl._M_start = __new_start; 102 this->_M_impl._M_finish = __new_finish; 103 } 104 class MoveOnly { 105 int data_; 106 public: bool operator==(MoveOnly) { 107 return data_; 108 } 109 }; 110 void __assert_fail(); 111 template < class T > class min_pointer { 112 T *ptr_; 113 min_pointer(T *p) : ptr_(p) { 114 } 115 public: min_pointer() = default; 116 T operator*() { 117 return *ptr_; 118 } 119 void operator++() { 120 ++ptr_; 121 } 122 void operator+=(long n) { 123 ptr_ += n; 124 } 125 min_pointer operator+(long n) { 126 min_pointer tmp(*this); 127 tmp += n; 128 return tmp; 129 } 130 friend long operator-(min_pointer x, min_pointer y) { 131 return x.ptr_ - y.ptr_; 132 } 133 friend bool operator==(min_pointer x, min_pointer y) { 134 return x.ptr_ == y.ptr_; 135 } 136 friend bool operator!=(min_pointer x, min_pointer y) { 137 return !(x == y); 138 } 139 friend class min_allocator; 140 }; 141 class min_allocator { 142 public: typedef MoveOnly value_type; 143 typedef min_pointer< MoveOnly > pointer; 144 pointer allocate(long) { 145 return static_cast< MoveOnly * >(operator new(sizeof(MoveOnly))); 146 } 147 }; 148 int main() { 149 vector< int, min_allocator > v(100); 150 v.insert(v.cbegin(), MoveOnly()); 151 int j = 0; 152 for (; 153 j < 10; 154 ++j) v[j] == MoveOnly() ? void() : __assert_fail(); 155 } 156