[gcc r15-5719] libstdc++: Simplify std::list assignment using 'if constexpr'
Jonathan Wakely
redi@gcc.gnu.org
Wed Nov 27 12:35:30 GMT 2024
https://gcc.gnu.org/g:281ac0ef1001aac1b4f4223c5dbba725a5cffb43
commit r15-5719-g281ac0ef1001aac1b4f4223c5dbba725a5cffb43
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Nov 25 21:57:57 2024 +0000
libstdc++: Simplify std::list assignment using 'if constexpr'
Use diagnostic pragmas to allow using `if constexpr` in C++11 mode, so
that we don't need to use tag dispatching.
The _M_move_assign overloads that were previously used for tag
dispatching are no longer used, but are retained here (at least for the
default config) so that an explicit instantiation will still define
those members. This ensures that old code which expects an explicit
instantiation in some other translation unit will still link. I'm not
sure if that's really needed, we should probably have a policy about
whether we support explicit instantiations where the declaration and
definition use different versions of the headers.
libstdc++-v3/ChangeLog:
* include/bits/stl_list.h (operator=(list&&)): Use if constexpr
instead of dispatching to _M_move_assign.
(_M_move_assign): Do not define for versioned namespace.
Diff:
---
libstdc++-v3/include/bits/stl_list.h | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 7deb04b4bfe4..3f92de42996e 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -935,6 +935,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
operator=(const list& __x);
#if __cplusplus >= 201103L
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
/**
* @brief %List move assignment operator.
* @param __x A %list of identical element and allocator types.
@@ -952,9 +954,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
constexpr bool __move_storage =
_Node_alloc_traits::_S_propagate_on_move_assign()
|| _Node_alloc_traits::_S_always_equal();
- _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
+ if constexpr (!__move_storage)
+ {
+ if (__x._M_get_Node_allocator() != this->_M_get_Node_allocator())
+ {
+ // The rvalue's allocator cannot be moved, or is not equal,
+ // so we need to individually move each element.
+ _M_assign_dispatch(std::make_move_iterator(__x.begin()),
+ std::make_move_iterator(__x.end()),
+ __false_type{});
+ return *this;
+ }
+ }
+
+ this->clear();
+ this->_M_move_nodes(std::move(__x));
+
+ if constexpr (_Node_alloc_traits::_S_propagate_on_move_assign())
+ this->_M_get_Node_allocator()
+ = std::move(__x._M_get_Node_allocator());
+
return *this;
}
+#pragma GCC diagnostic pop
/**
* @brief %List initializer list assignment operator.
@@ -2156,7 +2178,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
const_iterator
_M_resize_pos(size_type& __new_size) const;
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L && ! _GLIBCXX_INLINE_VERSION
+ // XXX GLIBCXX_ABI Deprecated
+ // These are unused and only kept so that explicit instantiations will
+ // continue to define the symbols.
void
_M_move_assign(list&& __x, true_type) noexcept
{
More information about the Libstdc++-cvs
mailing list