For C++11 and later we can remvoe four overloads of _S_copy_chars and
use constexpr-if in the generic _S_copy_chars. This simplifies overload
resolution for _S_copy_chars, and also means that we optimize for other
iterators such as std::vector<char>::iterator.
We still need all the _S_copy_chars overloads to be part of the explicit
instantiation definition, so make them depend on the macro that is
defined by src/c++11/string-inst.cc for that purpose.
libstdc++-v3/ChangeLog:
* include/bits/basic_string.h (_S_copy_chars): Replace overloads
with constexpr-if and extend optimization to all contiguous
iterators.
* src/c++11/string-inst.cc: Extend comment.
---
Tested x86_64-linux.
libstdc++-v3/include/bits/basic_string.h | 31 ++++++++++++++++++------
libstdc++-v3/src/c++11/string-inst.cc | 3 ++-
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/libstdc++-v3/include/bits/basic_string.h
b/libstdc++-v3/include/bits/basic_string.h
index 886e7e6b19e..067c7915c76 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -468,6 +468,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
traits_type::assign(__d, __n, __c);
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
// _S_copy_chars is a separate template to permit specialization
// to optimize for the common case of pointers as iterators.
template<class _Iterator>
@@ -475,31 +477,44 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static void
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
{
+#if __cplusplus >= 201103L
+ using _IterBase = decltype(std::__niter_base(__k1));
+ if constexpr (__or_<is_same<_IterBase, _CharT*>,
+ is_same<_IterBase, const _CharT*>>::value)
+ _S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
+#if __cpp_lib_concepts
+ else if constexpr (contiguous_iterator<_Iterator>
+ && is_same_v<iter_value_t<_Iterator>, _CharT>)
+ {
+ const auto __d = __k2 - __k1;
+ (void) (__k1 + __d); // See P3349R1
+ _S_copy(__p, std::to_address(__k1), static_cast<size_type>(__d));
+ }
+#endif
+ else
+#endif
for (; __k1 != __k2; ++__k1, (void)++__p)
traits_type::assign(*__p, *__k1); // These types are off.
}
+#pragma GCC diagnostic pop
- _GLIBCXX20_CONSTEXPR
+#if __cplusplus < 201103L || defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
static void
- _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
_GLIBCXX_NOEXCEPT
+ _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
- _GLIBCXX20_CONSTEXPR
static void
_S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
- _GLIBCXX_NOEXCEPT
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
- _GLIBCXX20_CONSTEXPR
static void
- _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPT
+ _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
{ _S_copy(__p, __k1, __k2 - __k1); }
- _GLIBCXX20_CONSTEXPR
static void
_S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
- _GLIBCXX_NOEXCEPT
{ _S_copy(__p, __k1, __k2 - __k1); }
+#endif
_GLIBCXX20_CONSTEXPR
static int
diff --git a/libstdc++-v3/src/c++11/string-inst.cc
b/libstdc++-v3/src/c++11/string-inst.cc
index c4864794d40..34df909b31a 100644
--- a/libstdc++-v3/src/c++11/string-inst.cc
+++ b/libstdc++-v3/src/c++11/string-inst.cc
@@ -40,7 +40,8 @@
// replaced by constrained function templates, so that we instantiate the
// pre-C++17 definitions.
// This also causes the instantiation of the non-standard C++0x-era
-// insert(iterator, initializer_list<C>) overload, see PR libstdc++/83328
+// insert(iterator, initializer_list<C>) overload, see PR libstdc++/83328,
+// and overloads of _S_copy_chars for string iterators and pointers.
#define _GLIBCXX_DEFINING_STRING_INSTANTIATIONS 1
#include <string>
--
2.49.0