public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-4063] libstdc++: Use conditional noexcept in std::reverse_iterator [PR 94418] Date: Fri, 1 Oct 2021 19:38:29 +0000 (GMT) [thread overview] Message-ID: <20211001193829.173693857810@sourceware.org> (raw) https://gcc.gnu.org/g:d335d73889d897d073b987b4323db05317fccad3 commit r12-4063-gd335d73889d897d073b987b4323db05317fccad3 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Apr 28 11:40:47 2021 +0100 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: --- libstdc++-v3/include/bits/stl_iterator.h | 20 ++++- .../24_iterators/reverse_iterator/noexcept.cc | 92 ++++++++++++++++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) 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()), "" ); +}
reply other threads:[~2021-10-01 19:38 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20211001193829.173693857810@sourceware.org \ --to=redi@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
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).