#3495: Array::operator[] should not throw

This commit is contained in:
Günter Obiltschnig 2022-03-27 20:02:50 +02:00
parent 292d137909
commit 2ec44c756b

View File

@ -34,11 +34,11 @@ namespace Poco {
template<class T, std::size_t N> template<class T, std::size_t N>
class Array class Array
/// STL container like C-style array replacement class. /// STL container like C-style array replacement class.
/// ///
/// This implementation is based on the idea of Nicolai Josuttis. /// This implementation is based on the idea of Nicolai Josuttis.
/// His original implementation can be found at http://www.josuttis.com/cppcode/array.html . /// His original implementation can be found at http://www.josuttis.com/cppcode/array.html .
{ {
public: public:
typedef T value_type; typedef T value_type;
@ -60,7 +60,7 @@ public:
} }
iterator end() iterator end()
{ {
return elems+N; return elems+N;
} }
@ -83,7 +83,7 @@ public:
} }
reverse_iterator rend() reverse_iterator rend()
{ {
return reverse_iterator(begin()); return reverse_iterator(begin());
} }
@ -92,26 +92,26 @@ public:
return const_reverse_iterator(begin()); return const_reverse_iterator(begin());
} }
reference operator[](size_type i) reference operator[](size_type i)
/// Element access without range check. If the index is not small than the given size, the behavior is undefined. /// Element access without range check. If the index is not small than the given size, the behavior is undefined.
{ {
poco_assert( i < N && "out of range" ); poco_assert_dbg(i < N && "out of range");
return elems[i]; return elems[i];
} }
const_reference operator[](size_type i) const const_reference operator[](size_type i) const
/// Element access without range check. If the index is not small than the given size, the behavior is undefined. /// Element access without range check. If the index is not small than the given size, the behavior is undefined.
{ {
poco_assert( i < N && "out of range" ); poco_assert_dbg(i < N && "out of range");
return elems[i]; return elems[i];
} }
reference at(size_type i) reference at(size_type i)
/// Element access with range check. Throws Poco::InvalidArgumentException if the index is over range. /// Element access with range check. Throws Poco::InvalidArgumentException if the index is over range.
{ {
if(i>=size()) if(i>=size())
throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range"); throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range");
return elems[i]; return elems[i];
} }
const_reference at(size_type i) const const_reference at(size_type i) const
@ -119,71 +119,71 @@ public:
{ {
if(i>=size()) if(i>=size())
throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range"); throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range");
return elems[i]; return elems[i];
} }
reference front() reference front()
{
return elems[0];
}
const_reference front() const
{ {
return elems[0]; return elems[0];
} }
reference back() const_reference front() const
{ {
return elems[N-1]; return elems[0];
} }
const_reference back() const reference back()
{ {
return elems[N-1]; return elems[N-1];
}
const_reference back() const
{
return elems[N-1];
} }
static size_type size() static size_type size()
{ {
return N; return N;
} }
static bool empty() static bool empty()
{ {
return false; return false;
} }
static size_type max_size() static size_type max_size()
{ {
return N; return N;
} }
enum { static_size = N }; enum { static_size = N };
void swap (Array<T,N>& y) void swap (Array<T,N>& y)
{ {
std::swap_ranges(begin(),end(),y.begin()); std::swap_ranges(begin(),end(),y.begin());
} }
const T* data() const const T* data() const
/// Direct access to data (read-only) /// Direct access to data (read-only)
{ {
return elems; return elems;
} }
T* data() T* data()
{ {
return elems; return elems;
} }
T* c_array() T* c_array()
{ {
/// Use array as C array (direct read/write access to data) /// Use array as C array (direct read/write access to data)
return elems; return elems;
} }
template <typename Other> template <typename Other>
Array<T,N>& operator= (const Array<Other,N>& rhs) Array<T,N>& operator= (const Array<Other,N>& rhs)
/// Assignment with type conversion /// Assignment with type conversion
{ {
std::copy(rhs.begin(),rhs.end(), begin()); std::copy(rhs.begin(),rhs.end(), begin());
return *this; return *this;
@ -196,7 +196,7 @@ public:
} }
public: public:
T elems[N]; T elems[N];
/// Fixed-size array of elements of type T, public specifier used to make this class a aggregate. /// Fixed-size array of elements of type T, public specifier used to make this class a aggregate.
}; };
@ -204,49 +204,49 @@ public:
// comparisons // comparisons
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator== (const Array<T,N>& x, const Array<T,N>& y) bool operator== (const Array<T,N>& x, const Array<T,N>& y)
{ {
return std::equal(x.begin(), x.end(), y.begin()); return std::equal(x.begin(), x.end(), y.begin());
} }
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator< (const Array<T,N>& x, const Array<T,N>& y) bool operator< (const Array<T,N>& x, const Array<T,N>& y)
{ {
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
} }
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator!= (const Array<T,N>& x, const Array<T,N>& y) bool operator!= (const Array<T,N>& x, const Array<T,N>& y)
{ {
return !(x==y); return !(x==y);
} }
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator> (const Array<T,N>& x, const Array<T,N>& y) bool operator> (const Array<T,N>& x, const Array<T,N>& y)
{ {
return y<x; return y<x;
} }
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator<= (const Array<T,N>& x, const Array<T,N>& y) bool operator<= (const Array<T,N>& x, const Array<T,N>& y)
{ {
return !(y<x); return !(y<x);
} }
template<class T, std::size_t N> template<class T, std::size_t N>
bool operator>= (const Array<T,N>& x, const Array<T,N>& y) bool operator>= (const Array<T,N>& x, const Array<T,N>& y)
{ {
return !(x<y); return !(x<y);
} }
template<class T, std::size_t N> template<class T, std::size_t N>
inline void swap (Array<T,N>& x, Array<T,N>& y) inline void swap (Array<T,N>& x, Array<T,N>& y)
/// global swap() /// global swap()
{ {
x.swap(y); x.swap(y);