1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_BASE_DCHECKED_VECTOR_H_ 18 #define ART_RUNTIME_BASE_DCHECKED_VECTOR_H_ 19 20 #include <algorithm> 21 #include <type_traits> 22 #include <vector> 23 24 #include "base/logging.h" 25 26 namespace art { 27 28 // Template class serving as a replacement for std::vector<> but adding 29 // DCHECK()s for the subscript operator, front(), back(), pop_back(), 30 // and for insert()/emplace()/erase() positions. 31 // 32 // Note: The element accessor at() is specified as throwing std::out_of_range 33 // but we do not use exceptions, so this accessor is deliberately hidden. 34 // Note: The common pattern &v[0] used to retrieve pointer to the data is not 35 // valid for an empty dchecked_vector<>. Use data() to avoid checking empty(). 36 template <typename T, typename Alloc = std::allocator<T>> 37 class dchecked_vector : private std::vector<T, Alloc> { 38 private: 39 // std::vector<> has a slightly different specialization for bool. We don't provide that. 40 static_assert(!std::is_same<T, bool>::value, "Not implemented for bool."); 41 using Base = std::vector<T, Alloc>; 42 43 public: 44 using typename Base::value_type; 45 using typename Base::allocator_type; 46 using typename Base::reference; 47 using typename Base::const_reference; 48 using typename Base::pointer; 49 using typename Base::const_pointer; 50 using typename Base::iterator; 51 using typename Base::const_iterator; 52 using typename Base::reverse_iterator; 53 using typename Base::const_reverse_iterator; 54 using typename Base::size_type; 55 using typename Base::difference_type; 56 57 // Construct/copy/destroy. 58 dchecked_vector() 59 : Base() { } 60 explicit dchecked_vector(const allocator_type& alloc) 61 : Base(alloc) { } 62 // Note that we cannot forward to std::vector(size_type, const allocator_type&) because it is not 63 // available in C++11, which is the latest GCC can support. http://b/25022512 64 explicit dchecked_vector(size_type n, const allocator_type& alloc = allocator_type()) 65 : Base(alloc) { resize(n); } 66 dchecked_vector(size_type n, 67 const value_type& value, 68 const allocator_type& alloc = allocator_type()) 69 : Base(n, value, alloc) { } 70 template <typename InputIterator> 71 dchecked_vector(InputIterator first, 72 InputIterator last, 73 const allocator_type& alloc = allocator_type()) 74 : Base(first, last, alloc) { } 75 dchecked_vector(const dchecked_vector& src) 76 : Base(src) { } 77 dchecked_vector(const dchecked_vector& src, const allocator_type& alloc) 78 : Base(src, alloc) { } 79 dchecked_vector(dchecked_vector&& src) 80 : Base(std::move(src)) { } 81 dchecked_vector(dchecked_vector&& src, const allocator_type& alloc) 82 : Base(std::move(src), alloc) { } 83 dchecked_vector(std::initializer_list<value_type> il, 84 const allocator_type& alloc = allocator_type()) 85 : Base(il, alloc) { } 86 ~dchecked_vector() = default; 87 dchecked_vector& operator=(const dchecked_vector& src) { 88 Base::operator=(src); 89 return *this; 90 } 91 dchecked_vector& operator=(dchecked_vector&& src) { 92 Base::operator=(std::move(src)); 93 return *this; 94 } 95 dchecked_vector& operator=(std::initializer_list<value_type> il) { 96 Base::operator=(il); 97 return *this; 98 } 99 100 // Iterators. 101 using Base::begin; 102 using Base::end; 103 using Base::rbegin; 104 using Base::rend; 105 using Base::cbegin; 106 using Base::cend; 107 using Base::crbegin; 108 using Base::crend; 109 110 // Capacity. 111 using Base::size; 112 using Base::max_size; 113 using Base::resize; 114 using Base::capacity; 115 using Base::empty; 116 using Base::reserve; 117 using Base::shrink_to_fit; 118 119 // Element access: inherited. 120 // Note: Deliberately not providing at(). 121 using Base::data; 122 123 // Element access: subscript operator. Check index. 124 reference operator[](size_type n) { 125 DCHECK_LT(n, size()); 126 return Base::operator[](n); 127 } 128 const_reference operator[](size_type n) const { 129 DCHECK_LT(n, size()); 130 return Base::operator[](n); 131 } 132 133 // Element access: front(), back(). Check not empty. 134 reference front() { DCHECK(!empty()); return Base::front(); } 135 const_reference front() const { DCHECK(!empty()); return Base::front(); } 136 reference back() { DCHECK(!empty()); return Base::back(); } 137 const_reference back() const { DCHECK(!empty()); return Base::back(); } 138 139 // Modifiers: inherited. 140 using Base::assign; 141 using Base::push_back; 142 using Base::clear; 143 using Base::emplace_back; 144 145 // Modifiers: pop_back(). Check not empty. 146 void pop_back() { DCHECK(!empty()); Base::pop_back(); } 147 148 // Modifiers: swap(). Swap only with another dchecked_vector instead of a plain vector. 149 void swap(dchecked_vector& other) { Base::swap(other); } 150 151 // Modifiers: insert(). Check position. 152 iterator insert(const_iterator position, const value_type& value) { 153 DCHECK(cbegin() <= position && position <= cend()); 154 return Base::insert(position, value); 155 } 156 iterator insert(const_iterator position, size_type n, const value_type& value) { 157 DCHECK(cbegin() <= position && position <= cend()); 158 return Base::insert(position, n, value); 159 } 160 template <typename InputIterator> 161 iterator insert(const_iterator position, InputIterator first, InputIterator last) { 162 DCHECK(cbegin() <= position && position <= cend()); 163 return Base::insert(position, first, last); 164 } 165 iterator insert(const_iterator position, value_type&& value) { 166 DCHECK(cbegin() <= position && position <= cend()); 167 return Base::insert(position, std::move(value)); 168 } 169 iterator insert(const_iterator position, std::initializer_list<value_type> il) { 170 DCHECK(cbegin() <= position && position <= cend()); 171 return Base::insert(position, il); 172 } 173 174 // Modifiers: erase(). Check position. 175 iterator erase(const_iterator position) { 176 DCHECK(cbegin() <= position && position < cend()); 177 return Base::erase(position); 178 } 179 iterator erase(const_iterator first, const_iterator last) { 180 DCHECK(cbegin() <= first && first <= cend()); 181 DCHECK(first <= last && last <= cend()); 182 return Base::erase(first, last); 183 } 184 185 // Modifiers: emplace(). Check position. 186 template <typename... Args> 187 iterator emplace(const_iterator position, Args&&... args) { 188 DCHECK(cbegin() <= position && position <= cend()); 189 Base::emplace(position, std::forward(args...)); 190 } 191 192 // Allocator. 193 using Base::get_allocator; 194 }; 195 196 // Non-member swap(), found by argument-dependent lookup for an unqualified call. 197 template <typename T, typename Alloc> 198 void swap(dchecked_vector<T, Alloc>& lhs, dchecked_vector<T, Alloc>& rhs) { 199 lhs.swap(rhs); 200 } 201 202 // Non-member relational operators. 203 template <typename T, typename Alloc> 204 bool operator==(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 205 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); 206 } 207 template <typename T, typename Alloc> 208 bool operator!=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 209 return !(lhs == rhs); 210 } 211 template <typename T, typename Alloc> 212 bool operator<(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 213 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); 214 } 215 template <typename T, typename Alloc> 216 bool operator<=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 217 return !(rhs < lhs); 218 } 219 template <typename T, typename Alloc> 220 bool operator>(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 221 return rhs < lhs; 222 } 223 template <typename T, typename Alloc> 224 bool operator>=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) { 225 return !(lhs < rhs); 226 } 227 228 } // namespace art 229 230 #endif // ART_RUNTIME_BASE_DCHECKED_VECTOR_H_ 231