[PATCH] Refactor std::basic_string_view members and add noexcept

Jonathan Wakely jwakely@redhat.com
Tue Oct 24 13:18:00 GMT 2017


This applies 'noexcept' more liberally in our std::basic_string_view,
anywhere that can't actually throw (even if it has a narrow contract).

I've also refactored some members to remove complex conditional
expressions, because they're not needed with C++14 constexpr, we can
just write the code as normal.

	* include/bits/string_view.tcc (find_first_of, find_last_of)
	(find_first_not_of, find_last_not_of): Add noexcept.
	* include/std/string_view (basic_string_view(const _CharT*))
	(basic_string_view(const _CharT*, size_type))
	(front, back, remove_prefix, remove_suffix, find, rfind)
	(find_first_of, find_first_not_of): Add noexcept.
	(at(size_type), _S_compare(size_type, size_type)): Replace conditional
	expressions with if statements.
	(copy(_CharT*, size_type, size_type), substr(size_type, size_type)):
	Use _M_check for length checks.
	(compare(basic_string_view)): Reformat.
	(_M_check(size_type, const char)): Add noexcept(false).
	(_M_limit(size_type, size_type)): Use noexcept not _GLIBCXX_NOEXCEPT.

Tested powerpc64le-linux, committed to trunk.

-------------- next part --------------
commit 0b6b569b442ab1837cecd140f07df969599eb51a
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Oct 24 13:50:19 2017 +0100

    Refactor std::basic_string_view members and add noexcept
    
            * include/bits/string_view.tcc (find_first_of, find_last_of)
            (find_first_not_of, find_last_not_of): Add noexcept.
            * include/std/string_view (basic_string_view(const _CharT*))
            (basic_string_view(const _CharT*, size_type))
            (front, back, remove_prefix, remove_suffix, find, rfind)
            (find_first_of, find_first_not_of): Add noexcept.
            (at(size_type), _S_compare(size_type, size_type)): Replace conditional
            expressions with if statements.
            (copy(_CharT*, size_type, size_type), substr(size_type, size_type)):
            Use _M_check for length checks.
            (compare(basic_string_view)): Reformat.
            (_M_check(size_type, const char)): Add noexcept(false).
            (_M_limit(size_type, size_type)): Use noexcept not _GLIBCXX_NOEXCEPT.

diff --git a/libstdc++-v3/include/bits/string_view.tcc b/libstdc++-v3/include/bits/string_view.tcc
index 4d98f8668a0..5c53c584381 100644
--- a/libstdc++-v3/include/bits/string_view.tcc
+++ b/libstdc++-v3/include/bits/string_view.tcc
@@ -119,7 +119,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _CharT, typename _Traits>
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
-    find_first_of(const _CharT* __str, size_type __pos, size_type __n) const
+    find_first_of(const _CharT* __str, size_type __pos,
+		  size_type __n) const noexcept
     {
       __glibcxx_requires_string_len(__str, __n);
       for (; __n && __pos < this->_M_len; ++__pos)
@@ -135,7 +136,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _CharT, typename _Traits>
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
-    find_last_of(const _CharT* __str, size_type __pos, size_type __n) const
+    find_last_of(const _CharT* __str, size_type __pos,
+		 size_type __n) const noexcept
     {
       __glibcxx_requires_string_len(__str, __n);
       size_type __size = this->size();
@@ -156,7 +158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _CharT, typename _Traits>
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
-    find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const
+    find_first_not_of(const _CharT* __str, size_type __pos,
+		      size_type __n) const noexcept
     {
       __glibcxx_requires_string_len(__str, __n);
       for (; __pos < this->_M_len; ++__pos)
@@ -179,7 +182,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _CharT, typename _Traits>
     constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
-    find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const
+    find_last_not_of(const _CharT* __str, size_type __pos,
+		     size_type __n) const noexcept
     {
       __glibcxx_requires_string_len(__str, __n);
       size_type __size = this->_M_len;
diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view
index 110a235a4c0..1900b867841 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -96,14 +96,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr basic_string_view(const basic_string_view&) noexcept = default;
 
-      constexpr basic_string_view(const _CharT* __str)
+      constexpr basic_string_view(const _CharT* __str) noexcept
       : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
 	_M_str{__str}
       { }
 
-      constexpr basic_string_view(const _CharT* __str, size_type __len)
-      : _M_len{__len},
-        _M_str{__str}
+      constexpr
+      basic_string_view(const _CharT* __str, size_type __len) noexcept
+      : _M_len{__len}, _M_str{__str}
       { }
 
       constexpr basic_string_view&
@@ -177,17 +177,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr const _CharT&
       at(size_type __pos) const
       {
-	return __pos < this->_M_len
-	     ? *(this->_M_str + __pos)
-	     : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
-					     "(which is %zu) >= this->size() "
-					     "(which is %zu)"),
-					 __pos, this->size()),
-		*this->_M_str);
+	if (__pos >= _M_len)
+	  __throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
+				       "(which is %zu) >= this->size() "
+				       "(which is %zu)"), __pos, this->size());
+	return *(this->_M_str + __pos);
       }
 
       constexpr const _CharT&
-      front() const
+      front() const noexcept
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
 	// __glibcxx_assert(this->_M_len > 0);
@@ -195,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
       constexpr const _CharT&
-      back() const
+      back() const noexcept
       {
 	// TODO: Assert to restore in a way compatible with the constexpr.
 	// __glibcxx_assert(this->_M_len > 0);
@@ -209,7 +207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // [string.view.modifiers], modifiers:
 
       constexpr void
-      remove_prefix(size_type __n)
+      remove_prefix(size_type __n) noexcept
       {
 	__glibcxx_assert(this->_M_len >= __n);
 	this->_M_str += __n;
@@ -217,7 +215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
       constexpr void
-      remove_suffix(size_type __n)
+      remove_suffix(size_type __n) noexcept
       { this->_M_len -= __n; }
 
       constexpr void
@@ -235,38 +233,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
       {
 	__glibcxx_requires_string_len(__str, __n);
-	if (__pos > this->_M_len)
-	  __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos "
-				       "(which is %zu) > this->size() "
-				       "(which is %zu)"),
-				   __pos, this->size());
-	size_type __rlen{std::min(__n, size_type{this->_M_len  - __pos})};
+	__pos = _M_check(__pos, "basic_string_view::copy");
+	const size_type __rlen = std::min(__n, _M_len - __pos);
 	for (auto __begin = this->_M_str + __pos,
 	     __end = __begin + __rlen; __begin != __end;)
 	  *__str++ = *__begin++;
 	return __rlen;
       }
 
-
-      // [string.view.ops], string operations:
-
       constexpr basic_string_view
-      substr(size_type __pos, size_type __n=npos) const
+      substr(size_type __pos, size_type __n = npos) const noexcept(false)
       {
-	return __pos <= this->_M_len
-	     ? basic_string_view{this->_M_str + __pos,
-				std::min(__n, size_type{this->_M_len  - __pos})}
-	     : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos "
-					     "(which is %zu) > this->size() "
-					     "(which is %zu)"),
-				     __pos, this->size()), basic_string_view{});
+	__pos = _M_check(__pos, "basic_string_view::substr");
+	const size_type __rlen = std::min(__n, _M_len - __pos);
+	return basic_string_view{_M_str + __pos, __rlen};
       }
 
       constexpr int
       compare(basic_string_view __str) const noexcept
       {
-	int __ret = traits_type::compare(this->_M_str, __str._M_str,
-					 std::min(this->_M_len, __str._M_len));
+	const size_type __rlen = std::min(this->_M_len, __str._M_len);
+	int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen);
 	if (__ret == 0)
 	  __ret = _S_compare(this->_M_len, __str._M_len);
 	return __ret;
@@ -279,7 +266,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr int
       compare(size_type __pos1, size_type __n1,
 	      basic_string_view __str, size_type __pos2, size_type __n2) const
-      { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
+      {
+	return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2));
+      }
 
       constexpr int
       compare(const _CharT* __str) const noexcept
@@ -291,7 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr int
       compare(size_type __pos1, size_type __n1,
-	      const _CharT* __str, size_type __n2) const
+	      const _CharT* __str, size_type __n2) const noexcept(false)
       {
 	return this->substr(__pos1, __n1)
 		   .compare(basic_string_view(__str, __n2));
@@ -302,13 +291,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return this->find(__str._M_str, __pos, __str._M_len); }
 
       constexpr size_type
-      find(_CharT __c, size_type __pos=0) const noexcept;
+      find(_CharT __c, size_type __pos = 0) const noexcept;
 
       constexpr size_type
       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
-      find(const _CharT* __str, size_type __pos=0) const noexcept
+      find(const _CharT* __str, size_type __pos = 0) const noexcept
       { return this->find(__str, __pos, traits_type::length(__str)); }
 
       constexpr size_type
@@ -350,7 +339,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return this->rfind(__c, __pos); }
 
       constexpr size_type
-      find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
+      find_last_of(const _CharT* __str, size_type __pos,
+		   size_type __n) const noexcept;
 
       constexpr size_type
       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
@@ -366,7 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr size_type
       find_first_not_of(const _CharT* __str,
-			size_type __pos, size_type __n) const;
+			size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
@@ -385,7 +375,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       constexpr size_type
       find_last_not_of(const _CharT* __str,
-		       size_type __pos, size_type __n) const;
+		       size_type __pos, size_type __n) const noexcept;
 
       constexpr size_type
       find_last_not_of(const _CharT* __str,
@@ -396,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
       constexpr size_type
-      _M_check(size_type __pos, const char* __s) const
+      _M_check(size_type __pos, const char* __s) const noexcept(false)
       {
 	if (__pos > this->size())
 	  __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
@@ -407,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // NB: _M_limit doesn't check for a bad __pos value.
       constexpr size_type
-      _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT
+      _M_limit(size_type __pos, size_type __off) const noexcept
       {
 	const bool __testoff =  __off < this->size() - __pos;
 	return __testoff ? __off : this->size() - __pos;
@@ -418,11 +408,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static constexpr int
       _S_compare(size_type __n1, size_type __n2) noexcept
       {
-	return difference_type{__n1 - __n2} > std::numeric_limits<int>::max()
-	     ? std::numeric_limits<int>::max()
-	     : difference_type{__n1 - __n2} < std::numeric_limits<int>::min()
-	     ? std::numeric_limits<int>::min()
-	     : static_cast<int>(difference_type{__n1 - __n2});
+	const difference_type __diff{__n1 - __n2};
+	if (__diff > std::numeric_limits<int>::max())
+	  return std::numeric_limits<int>::max();
+	if (__diff < std::numeric_limits<int>::min())
+	  return std::numeric_limits<int>::min();
+	return static_cast<int>(__diff);
       }
 
       size_t	    _M_len;


More information about the Libstdc++ mailing list