libstdc++: Use constexpr-if for std::basic_string::_S_copy_chars
For C++11 and later we can remove 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 use the optimized memcpy path 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. For C++98 the _S_copy_chars overloads are still needed, but the macros _GLIBCXX_NOEXCEPT and _GLIBCXX20_CONSTEXPR do nothing for C++98, so this change removes them from those overloads. When instantiated in src/c++11/string-inst.cc the removed _GLIBCXX_NOEXCEPT macros would expand to 'noexcept', but in practice that doesn't make any difference for those instantiations. At -O2 the instantiations inline all the calls to _S_copy_chars and the presence or absence of noexcept doesn't change anything in the generated code. 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. Reviewed-by: Tomasz Kaminski <tkaminsk@redhat.com>
This commit is contained in:
parent
ae54d8cb51
commit
648d5c26e2
2 changed files with 25 additions and 9 deletions
|
@ -473,6 +473,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>
|
||||
|
@ -480,31 +482,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
|
||||
|
||||
#if __glibcxx_containers_ranges // C++ >= 23
|
||||
// pre: __n == ranges::distance(__rg). __p+[0,__n) is a valid range.
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue