diff mbox

[v3] More noexcept for vectors

Message ID alpine.DEB.2.02.1309141228580.9493@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Sept. 14, 2013, 10:37 a.m. UTC
Hello,

this patch passes bootstrap+testsuite. The guarantees given by the 
standard on allocators are a bit weird, but I see there is already DR2016 
taking care of it.

2013-09-14  Marc Glisse  <marc.glisse@inria.fr>

 	PR libstdc++/58338
 	* include/bits/stl_vector.h
 	(_Vector_impl::_Vector_impl(_Tp_alloc_type const&),
 	_Vector_impl::_Vector_impl(_Tp_alloc_type&&),
 	_Vector_impl::_M_swap_data,
 	_Vector_base::_Vector_base(const allocator_type&),
 	_Vector_base::_Vector_base(allocator_type&&),
 	_Vector_base::_Vector_base(_Vector_base&&),
 	vector::vector(const allocator_type&), vector::operator[],
 	vector::operator[] const, vector::front, vector::front const,
 	vector::back, vector::back const, vector::pop_back,
 	vector::_M_erase_at_end): Mark as noexcept.
 	(vector::~vector): Remove useless noexcept.

Comments

Paolo Carlini Sept. 14, 2013, 3:03 p.m. UTC | #1
Hi,

Marc Glisse <marc.glisse@inria.fr> ha scritto:
>Hello,
>
>this patch passes bootstrap+testsuite. The guarantees given by the
>standard on allocators are a bit weird, but I see there is already
>DR2016
>taking care of it.

Patch looks good to me, thanks!

Paolo
Paolo Carlini Sept. 14, 2013, 3:14 p.m. UTC | #2
... what about debug-mode (and profile-mode)? Is in principle possible to detect the noexcepts? If we can't exclude that, we should probably change at the same time the special modes too. Otherwise seems just matter of consistency?

Paolo
Marc Glisse Sept. 14, 2013, 3:34 p.m. UTC | #3
On Sat, 14 Sep 2013, Paolo Carlini wrote:

> ... what about debug-mode (and profile-mode)? Is in principle possible 
> to detect the noexcepts? If we can't exclude that, we should probably 
> change at the same time the special modes too. Otherwise seems just 
> matter of consistency?

I was going one file at a time, and the priority is clearly 
"release"-mode, since this is about performance. I don't think there is 
anything wrong with debug-mode having a different exception specification 
(it is already binary-incompatible with the default mode) but I understand 
why people may want to keep some consistency. I can do vector in the other 
modes next if you want.
Paolo Carlini Sept. 14, 2013, 3:53 p.m. UTC | #4
Hi,

>I was going one file at a time, and the priority is clearly
>"release"-mode, since this is about performance. I don't think there is
>
>anything wrong with debug-mode having a different exception
>specification
>(it is already binary-incompatible with the default mode) but I
>understand 
>why people may want to keep some consistency. I can do vector in the
>other
>modes next if you want.

Yes, please. As boring as it may seem, I'm trying to convince myself and the other contributors to keep the modes up to date and consistent as much as possible. If one day we figure out that we can't, we don't have enough man power it will mean we have to remove the special modes (or only some of them) from svn.

Thanks!
Paolo
diff mbox

Patch

Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h	(revision 202588)
+++ include/bits/stl_vector.h	(working copy)
@@ -80,32 +80,32 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       : public _Tp_alloc_type
       {
 	pointer _M_start;
 	pointer _M_finish;
 	pointer _M_end_of_storage;
 
 	_Vector_impl()
 	: _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
 	{ }
 
-	_Vector_impl(_Tp_alloc_type const& __a)
+	_Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT
 	: _Tp_alloc_type(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
 	{ }
 
 #if __cplusplus >= 201103L
-	_Vector_impl(_Tp_alloc_type&& __a)
+	_Vector_impl(_Tp_alloc_type&& __a) noexcept
 	: _Tp_alloc_type(std::move(__a)),
 	  _M_start(0), _M_finish(0), _M_end_of_storage(0)
 	{ }
 #endif
 
-	void _M_swap_data(_Vector_impl& __x)
+	void _M_swap_data(_Vector_impl& __x) _GLIBCXX_NOEXCEPT
 	{
 	  std::swap(_M_start, __x._M_start);
 	  std::swap(_M_finish, __x._M_finish);
 	  std::swap(_M_end_of_storage, __x._M_end_of_storage);
 	}
       };
       
     public:
       typedef _Alloc allocator_type;
 
@@ -117,36 +117,36 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
       { return *static_cast<const _Tp_alloc_type*>(&this->_M_impl); }
 
       allocator_type
       get_allocator() const _GLIBCXX_NOEXCEPT
       { return allocator_type(_M_get_Tp_allocator()); }
 
       _Vector_base()
       : _M_impl() { }
 
-      _Vector_base(const allocator_type& __a)
+      _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT
       : _M_impl(__a) { }
 
       _Vector_base(size_t __n)
       : _M_impl()
       { _M_create_storage(__n); }
 
       _Vector_base(size_t __n, const allocator_type& __a)
       : _M_impl(__a)
       { _M_create_storage(__n); }
 
 #if __cplusplus >= 201103L
-      _Vector_base(_Tp_alloc_type&& __a)
+      _Vector_base(_Tp_alloc_type&& __a) noexcept
       : _M_impl(std::move(__a)) { }
 
-      _Vector_base(_Vector_base&& __x)
+      _Vector_base(_Vector_base&& __x) noexcept
       : _M_impl(std::move(__x._M_get_Tp_allocator()))
       { this->_M_impl._M_swap_data(__x._M_impl); }
 
       _Vector_base(_Vector_base&& __x, const allocator_type& __a)
       : _M_impl(__a)
       {
 	if (__x.get_allocator() == __a)
 	  this->_M_impl._M_swap_data(__x._M_impl);
 	else
 	  {
@@ -246,21 +246,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @brief  Default constructor creates no elements.
        */
       vector()
       : _Base() { }
 
       /**
        *  @brief  Creates a %vector with no elements.
        *  @param  __a  An allocator object.
        */
       explicit
-      vector(const allocator_type& __a)
+      vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
       : _Base(__a) { }
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Creates a %vector with default constructed elements.
        *  @param  __n  The number of elements to initially create.
        *  @param  __a  An allocator.
        *
        *  This constructor fills the %vector with @a __n default
        *  constructed elements.
@@ -404,21 +404,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  _M_initialize_dispatch(__first, __last, _Integral());
 	}
 #endif
 
       /**
        *  The dtor only erases the elements, and note that if the
        *  elements themselves are pointers, the pointed-to memory is
        *  not touched in any way.  Managing the pointer is the user's
        *  responsibility.
        */
-      ~vector() _GLIBCXX_NOEXCEPT
+      ~vector()
       { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
 		      _M_get_Tp_allocator()); }
 
       /**
        *  @brief  %Vector assignment operator.
        *  @param  __x  A %vector of identical element and allocator types.
        *
        *  All the elements of @a __x are copied, but any extra memory in
        *  @a __x (for fast expansion) will not be copied.  Unlike the
        *  copy constructor, the allocator object is not copied.
@@ -760,36 +760,36 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @param __n The index of the element for which data should be
        *  accessed.
        *  @return  Read/write reference to data.
        *
        *  This operator allows for easy, array-style, data access.
        *  Note that data access with this operator is unchecked and
        *  out_of_range lookups are not defined. (For checked lookups
        *  see at().)
        */
       reference
-      operator[](size_type __n)
+      operator[](size_type __n) _GLIBCXX_NOEXCEPT
       { return *(this->_M_impl._M_start + __n); }
 
       /**
        *  @brief  Subscript access to the data contained in the %vector.
        *  @param __n The index of the element for which data should be
        *  accessed.
        *  @return  Read-only (constant) reference to data.
        *
        *  This operator allows for easy, array-style, data access.
        *  Note that data access with this operator is unchecked and
        *  out_of_range lookups are not defined. (For checked lookups
        *  see at().)
        */
       const_reference
-      operator[](size_type __n) const
+      operator[](size_type __n) const _GLIBCXX_NOEXCEPT
       { return *(this->_M_impl._M_start + __n); }
 
     protected:
       /// Safety check used only from at().
       void
       _M_range_check(size_type __n) const
       {
 	if (__n >= this->size())
 	  __throw_out_of_range(__N("vector::_M_range_check"));
       }
@@ -829,45 +829,45 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	_M_range_check(__n);
 	return (*this)[__n];
       }
 
       /**
        *  Returns a read/write reference to the data at the first
        *  element of the %vector.
        */
       reference
-      front()
+      front() _GLIBCXX_NOEXCEPT
       { return *begin(); }
 
       /**
        *  Returns a read-only (constant) reference to the data at the first
        *  element of the %vector.
        */
       const_reference
-      front() const
+      front() const _GLIBCXX_NOEXCEPT
       { return *begin(); }
 
       /**
        *  Returns a read/write reference to the data at the last
        *  element of the %vector.
        */
       reference
-      back()
+      back() _GLIBCXX_NOEXCEPT
       { return *(end() - 1); }
       
       /**
        *  Returns a read-only (constant) reference to the data at the
        *  last element of the %vector.
        */
       const_reference
-      back() const
+      back() const _GLIBCXX_NOEXCEPT
       { return *(end() - 1); }
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 464. Suggestion for new member functions in standard containers.
       // data access
       /**
        *   Returns a pointer such that [data(), data() + size()) is a valid
        *   range.  For a non-empty %vector, data() == &front().
        */
 #if __cplusplus >= 201103L
@@ -927,21 +927,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /**
        *  @brief  Removes last element.
        *
        *  This is a typical stack operation. It shrinks the %vector by one.
        *
        *  Note that no data is returned, and if the last element's
        *  data is needed, it should be retrieved before pop_back() is
        *  called.
        */
       void
-      pop_back()
+      pop_back() _GLIBCXX_NOEXCEPT
       {
 	--this->_M_impl._M_finish;
 	_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
       }
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Inserts an object in %vector before specified iterator.
        *  @param  __position  A const_iterator into the %vector.
        *  @param  __args  Arguments.
@@ -1408,21 +1408,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	const size_type __len = size() + std::max(size(), __n);
 	return (__len < size() || __len > max_size()) ? max_size() : __len;
       }
 
       // Internal erase functions follow.
 
       // Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
       // _M_assign_aux.
       void
-      _M_erase_at_end(pointer __pos)
+      _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT
       {
 	std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
 	this->_M_impl._M_finish = __pos;
       }
 
       iterator
       _M_erase(iterator __position);
 
       iterator
       _M_erase(iterator __first, iterator __last);