* [committed] libstdc++: Use conditional noexcept in std::reverse_iterator [PR 94418]
@ 2021-10-01 19:40 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-10-01 19:40 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 930 bytes --]
This adds a noexcept-specifier to each constructor and assignment
operator of std::reverse_iterator so that they are noexcept when the
corresponding operation on the underlying iterator is noexcept.
The std::reverse_iterator class template already requires that the
operations on the underlying type are valid, so we don't need to use the
std::is_nothrow_xxx traits to protect against errors when the expression
isn't even valid. We can just use a noexcept operator to test if the
expression can throw, without the overhead of redundantly checking if
the initialization/assignment would be valid.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
PR libstdc++/94418
* include/bits/stl_iterator.h (reverse_iterator): Use
conditional noexcept on constructors and assignment operators.
* testsuite/24_iterators/reverse_iterator/noexcept.cc: New test.
Tested powerpc64le-linux. Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 7215 bytes --]
commit d335d73889d897d073b987b4323db05317fccad3
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed Apr 28 11:40:47 2021
libstdc++: Use conditional noexcept in std::reverse_iterator [PR 94418]
This adds a noexcept-specifier to each constructor and assignment
operator of std::reverse_iterator so that they are noexcept when the
corresponding operation on the underlying iterator is noexcept.
The std::reverse_iterator class template already requires that the
operations on the underlying type are valid, so we don't need to use the
std::is_nothrow_xxx traits to protect against errors when the expression
isn't even valid. We can just use a noexcept operator to test if the
expression can throw, without the overhead of redundantly checking if
the initialization/assignment would be valid.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
PR libstdc++/94418
* include/bits/stl_iterator.h (reverse_iterator): Use
conditional noexcept on constructors and assignment operators.
* testsuite/24_iterators/reverse_iterator/noexcept.cc: New test.
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 004d767224d..4973f792b56 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -174,20 +174,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 235 No specification of default ctor for reverse_iterator
// 1012. reverse_iterator default ctor should value initialize
_GLIBCXX17_CONSTEXPR
- reverse_iterator() : current() { }
+ reverse_iterator()
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator()))
+ : current()
+ { }
/**
* This %iterator will move in the opposite direction that @p x does.
*/
explicit _GLIBCXX17_CONSTEXPR
- reverse_iterator(iterator_type __x) : current(__x) { }
+ reverse_iterator(iterator_type __x)
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x)))
+ : current(__x)
+ { }
/**
* The copy constructor is normal.
*/
_GLIBCXX17_CONSTEXPR
reverse_iterator(const reverse_iterator& __x)
- : current(__x.current) { }
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current)))
+ : current(__x.current)
+ { }
#if __cplusplus >= 201103L
reverse_iterator& operator=(const reverse_iterator&) = default;
@@ -203,7 +211,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
_GLIBCXX17_CONSTEXPR
reverse_iterator(const reverse_iterator<_Iter>& __x)
- : current(__x.current) { }
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(__x.current)))
+ : current(__x.current)
+ { }
#if __cplusplus >= 201103L
template<typename _Iter>
@@ -214,6 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX17_CONSTEXPR
reverse_iterator&
operator=(const reverse_iterator<_Iter>& __x)
+ _GLIBCXX_NOEXCEPT_IF(noexcept(current = __x.current))
{
current = __x.current;
return *this;
@@ -226,6 +237,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NODISCARD
_GLIBCXX17_CONSTEXPR iterator_type
base() const
+ _GLIBCXX_NOEXCEPT_IF(noexcept(_Iterator(current)))
{ return current; }
/**
diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc
new file mode 100644
index 00000000000..df4b1b0763d
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/noexcept.cc
@@ -0,0 +1,92 @@
+// { dg-do compile { target c++11 } }
+
+#include <iterator>
+
+template<typename T, bool Nothrow>
+struct bidi
+{
+ using value_type = T;
+ using pointer = T*;
+ using reference = T&;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ T* ptr;
+
+ bidi(T* ptr = nullptr) noexcept(Nothrow) : ptr(ptr) { }
+
+ bidi(const bidi& iter) noexcept(Nothrow) : ptr(iter.ptr) { }
+
+ template<typename U>
+ bidi(const bidi<U, Nothrow>& iter) noexcept(Nothrow) : ptr(iter.ptr) { }
+
+ bidi& operator=(const bidi& iter) noexcept(Nothrow)
+ {
+ ptr = iter.ptr;
+ return *this;
+ }
+
+ template<typename U>
+ bidi& operator=(const bidi<U, Nothrow>& iter) noexcept(Nothrow)
+ {
+ ptr = iter.ptr;
+ return *this;
+ }
+
+ bidi& operator++() { ++ptr; return *this; }
+ bidi& operator--() { --ptr; return *this; }
+ bidi operator++(int) { bidi tmp = *this; ++ptr; return tmp; }
+ bidi operator--(int) { bidi tmp = *this; --ptr; return tmp; }
+
+ reference operator*() const { return *ptr; }
+ pointer operator->() const { return ptr; }
+};
+
+void
+test01()
+{
+ using B1 = bidi<int, true>;
+ using R1 = std::reverse_iterator<B1>;
+ static_assert( std::is_nothrow_default_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_copy_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_move_constructible<R1>(), "" );
+ static_assert( std::is_nothrow_copy_assignable<R1>(), "" );
+ static_assert( std::is_nothrow_move_assignable<R1>(), "" );
+ static_assert( std::is_nothrow_constructible<R1, const B1&>(), "" );
+ static_assert( std::is_nothrow_constructible<R1, B1>(), "" );
+
+ using B2 = bidi<const int, true>;
+ using R2 = std::reverse_iterator<B2>;
+ // Test conversions from reverse_iterator<B1> to reverse_iterator<B2>.
+ static_assert( std::is_nothrow_constructible<R2, const R1&>(), "" );
+ static_assert( std::is_nothrow_assignable<R2&, const R1&>(), "" );
+ // And from B1 to reverse_iterator<B2>.
+ static_assert( std::is_nothrow_constructible<R2, const B2&>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, B2>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, const B1&>(), "" );
+ static_assert( std::is_nothrow_constructible<R2, B1>(), "" );
+
+ using B3 = bidi<int, false>;
+ using R3 = std::reverse_iterator<B3>;
+ static_assert( ! std::is_nothrow_default_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_copy_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_move_constructible<R3>(), "" );
+ static_assert( ! std::is_nothrow_copy_assignable<R3>(), "" );
+ static_assert( ! std::is_nothrow_move_assignable<R3>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R3, const B3&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R3, B3>(), "" );
+
+ using B4 = bidi<const int, false>;
+ using R4 = std::reverse_iterator<B4>;
+ // Test conversions from reverse_iterator<B3> to reverse_iterator<B4>.
+ static_assert( ! std::is_nothrow_constructible<R4, const R3&>(), "" );
+ static_assert( ! std::is_nothrow_assignable<R4&, const R3&>(), "" );
+ // And from B3 to reverse_iterator<B4>.
+ static_assert( ! std::is_nothrow_constructible<R4, const B4&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, B4>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, const B3&>(), "" );
+ static_assert( ! std::is_nothrow_constructible<R4, B3>(), "" );
+
+ static_assert( noexcept(std::declval<R1&>().base()), "" );
+ static_assert( ! noexcept(std::declval<R3&>().base()), "" );
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-10-01 19:40 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-01 19:40 [committed] libstdc++: Use conditional noexcept in std::reverse_iterator [PR 94418] Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).