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