mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-19 00:55:13 +08:00
libstdc++: Implement constexpr std::basic_string for C++20
This is only supported for the cxx11 ABI, not for COW strings. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string, operator""s): Add constexpr for C++20. (basic_string::basic_string(basic_string&&)): Only copy initialized portion of the buffer. (basic_string::basic_string(basic_string&&, const Alloc&)): Likewise. * include/bits/basic_string.tcc (basic_string): Add constexpr for C++20. (basic_string::swap(basic_string&)): Only copy initialized portions of the buffers. (basic_string::_M_replace): Add constexpr implementation that doesn't depend on pointer comparisons. * include/bits/cow_string.h: Adjust comment. * include/ext/type_traits.h (__is_null_pointer): Add constexpr. * include/std/string (erase, erase_if): Add constexpr. * include/std/version (__cpp_lib_constexpr_string): Update value. * testsuite/21_strings/basic_string/cons/char/constexpr.cc: New test. * testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc: New test. * testsuite/21_strings/basic_string/literals/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc: New test. * testsuite/21_strings/basic_string/version.cc: New test.
This commit is contained in:
parent
59434931fb
commit
b96e2ff9d8
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
basic_string<_CharT, _Traits, _Alloc>::npos;
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
swap(basic_string& __s) _GLIBCXX_NOEXCEPT
|
||||
@ -70,16 +71,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
_CharT __tmp_data[_S_local_capacity + 1];
|
||||
traits_type::copy(__tmp_data, __s._M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
__s.length() + 1);
|
||||
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
length() + 1);
|
||||
traits_type::copy(_M_local_buf, __tmp_data,
|
||||
_S_local_capacity + 1);
|
||||
__s.length() + 1);
|
||||
}
|
||||
else if (__s.length())
|
||||
{
|
||||
traits_type::copy(_M_local_buf, __s._M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
__s.length() + 1);
|
||||
_M_length(__s.length());
|
||||
__s._M_set_length(0);
|
||||
return;
|
||||
@ -87,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
else if (length())
|
||||
{
|
||||
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
length() + 1);
|
||||
__s._M_length(length());
|
||||
_M_set_length(0);
|
||||
return;
|
||||
@ -97,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
const size_type __tmp_capacity = __s._M_allocated_capacity;
|
||||
traits_type::copy(__s._M_local_buf, _M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
length() + 1);
|
||||
_M_data(__s._M_data());
|
||||
__s._M_data(__s._M_local_buf);
|
||||
_M_capacity(__tmp_capacity);
|
||||
@ -108,7 +109,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
if (__s._M_is_local())
|
||||
{
|
||||
traits_type::copy(_M_local_buf, __s._M_local_buf,
|
||||
_S_local_capacity + 1);
|
||||
__s.length() + 1);
|
||||
__s._M_data(_M_data());
|
||||
_M_data(_M_local_buf);
|
||||
}
|
||||
@ -128,6 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::pointer
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_create(size_type& __capacity, size_type __old_capacity)
|
||||
@ -159,6 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
// pointers, calling for a different coding style.
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
template<typename _InIterator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_construct(_InIterator __beg, _InIterator __end,
|
||||
@ -202,6 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
template<typename _InIterator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_construct(_InIterator __beg, _InIterator __end,
|
||||
@ -233,6 +237,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_construct(size_type __n, _CharT __c)
|
||||
@ -250,6 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_assign(const basic_string& __str)
|
||||
@ -276,6 +282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
reserve(size_type __res)
|
||||
@ -296,6 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
|
||||
@ -320,6 +328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_erase(size_type __pos, size_type __n)
|
||||
@ -333,6 +342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
reserve()
|
||||
@ -368,6 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
resize(size_type __n, _CharT __c)
|
||||
@ -380,6 +391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>&
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_append(const _CharT* __s, size_type __n)
|
||||
@ -400,6 +412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
template<typename _InputIterator>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>&
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_replace_dispatch(const_iterator __i1, const_iterator __i2,
|
||||
@ -415,6 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>&
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
|
||||
@ -444,6 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>&
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
_M_replace(size_type __pos, size_type __len1, const _CharT* __s,
|
||||
@ -459,6 +474,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
pointer __p = this->_M_data() + __pos;
|
||||
|
||||
const size_type __how_much = __old_size - __pos - __len1;
|
||||
#if __cpp_lib_is_constant_evaluated
|
||||
if (__builtin_is_constant_evaluated())
|
||||
{
|
||||
auto __newp = this->_M_get_allocator().allocate(__new_size);
|
||||
_S_copy(__newp, this->_M_data(), __pos);
|
||||
_S_copy(__newp + __pos, __s, __len2);
|
||||
_S_copy(__newp + __pos + __len2, __p + __len1, __how_much);
|
||||
_S_copy(this->_M_data(), __newp, __new_size);
|
||||
this->_M_get_allocator().deallocate(__newp, __new_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (_M_disjunct(__s))
|
||||
{
|
||||
if (__how_much && __len1 != __len2)
|
||||
@ -502,6 +529,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
copy(_CharT* __s, size_type __n, size_type __pos) const
|
||||
@ -535,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
else
|
||||
__p = _M_data();
|
||||
struct _Terminator {
|
||||
~_Terminator() { _M_this->_M_set_length(_M_r); }
|
||||
constexpr ~_Terminator() { _M_this->_M_set_length(_M_r); }
|
||||
basic_string* _M_this;
|
||||
size_type _M_r;
|
||||
};
|
||||
@ -548,7 +576,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#endif // _GLIBCXX_USE_CXX11_ABI
|
||||
|
||||
#if __cpp_lib_constexpr_string >= 201907L
|
||||
# define _GLIBCXX_STRING_CONSTEXPR constexpr
|
||||
#else
|
||||
# define _GLIBCXX_STRING_CONSTEXPR
|
||||
#endif
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>
|
||||
operator+(const _CharT* __lhs,
|
||||
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
||||
@ -569,6 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
basic_string<_CharT, _Traits, _Alloc>
|
||||
operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
|
||||
{
|
||||
@ -587,6 +623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -623,6 +660,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
||||
@ -641,6 +679,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
rfind(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -663,6 +702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
||||
@ -680,6 +720,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -696,6 +737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -718,6 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -731,6 +774,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
||||
@ -742,6 +786,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
|
||||
@ -764,6 +809,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
|
||||
@ -784,6 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
int
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
compare(size_type __pos, size_type __n, const basic_string& __str) const
|
||||
@ -799,6 +846,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
int
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
compare(size_type __pos1, size_type __n1, const basic_string& __str,
|
||||
@ -817,6 +865,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
int
|
||||
basic_string<_CharT, _Traits, _Alloc>::
|
||||
compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT
|
||||
@ -832,6 +881,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
int
|
||||
basic_string <_CharT, _Traits, _Alloc>::
|
||||
compare(size_type __pos, size_type __n1, const _CharT* __s) const
|
||||
@ -848,6 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
_GLIBCXX_STRING_CONSTEXPR
|
||||
int
|
||||
basic_string <_CharT, _Traits, _Alloc>::
|
||||
compare(size_type __pos, size_type __n1, const _CharT* __s,
|
||||
@ -863,6 +914,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
return __r;
|
||||
}
|
||||
|
||||
#undef _GLIBCXX_STRING_CONSTEXPR
|
||||
|
||||
// 21.3.7.9 basic_string::getline and operators
|
||||
template<typename _CharT, typename _Traits, typename _Alloc>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
|
@ -35,7 +35,7 @@
|
||||
#if ! _GLIBCXX_USE_CXX11_ABI
|
||||
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
// Support P1032R1 in C++20 (but not P0980R1 yet).
|
||||
// Support P1032R1 in C++20 (but not P0980R1 for COW strings).
|
||||
# define __cpp_lib_constexpr_string 201811L
|
||||
#elif __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
|
||||
// Support P0426R1 changes to char_traits in C++17.
|
||||
|
@ -148,17 +148,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// For use in string and vstring.
|
||||
template<typename _Type>
|
||||
_GLIBCXX_CONSTEXPR
|
||||
inline bool
|
||||
__is_null_pointer(_Type* __ptr)
|
||||
{ return __ptr == 0; }
|
||||
|
||||
template<typename _Type>
|
||||
_GLIBCXX_CONSTEXPR
|
||||
inline bool
|
||||
__is_null_pointer(_Type)
|
||||
{ return false; }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
inline bool
|
||||
constexpr bool
|
||||
__is_null_pointer(std::nullptr_t)
|
||||
{ return true; }
|
||||
#endif
|
||||
|
@ -116,6 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc,
|
||||
typename _Predicate>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
|
||||
{
|
||||
@ -129,6 +130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Alloc, typename _Up>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
|
||||
erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
|
||||
{
|
||||
|
@ -232,7 +232,11 @@
|
||||
#define __cpp_lib_constexpr_memory 201811L
|
||||
#define __cpp_lib_constexpr_numeric 201911L
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
# define __cpp_lib_constexpr_string 201811L
|
||||
# if _GLIBCXX_USE_CXX11_ABI
|
||||
# define __cpp_lib_constexpr_string 201907L
|
||||
# else
|
||||
# define __cpp_lib_constexpr_string 201811L
|
||||
# endif
|
||||
#endif
|
||||
#define __cpp_lib_constexpr_string_view 201811L
|
||||
#define __cpp_lib_constexpr_tuple 201811L
|
||||
|
@ -0,0 +1,174 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef __cpp_lib_constexpr_string
|
||||
# error "Feature-test macro for constexpr std::string missing in <string>"
|
||||
#elif __cpp_lib_constexpr_string != 201907L
|
||||
# error "Feature-test macro for constexpr std::string has wrong value in <string>"
|
||||
#endif
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using C = char;
|
||||
using T = std::char_traits<C>;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : std::allocator<T>
|
||||
{
|
||||
using std::allocator<T>::allocator;
|
||||
|
||||
constexpr explicit Alloc(int p) : personality(p) { }
|
||||
|
||||
template<typename U>
|
||||
constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
|
||||
|
||||
int personality = 0;
|
||||
|
||||
constexpr Alloc select_on_container_copy_construction() const
|
||||
{ return Alloc(-1); }
|
||||
|
||||
constexpr bool operator==(const Alloc& a) const noexcept
|
||||
{ return personality == a.personality; }
|
||||
};
|
||||
|
||||
constexpr bool
|
||||
test_default_ctor()
|
||||
{
|
||||
std::basic_string<C> s0;
|
||||
VERIFY( s0.empty() );
|
||||
|
||||
std::basic_string<C> s1(std::allocator<C>{});
|
||||
VERIFY( s1.empty() );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s2;
|
||||
VERIFY( s2.empty() );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s3(Alloc<C>(3));
|
||||
VERIFY( s3.empty() );
|
||||
VERIFY( s3.get_allocator().personality == 3 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_default_ctor() );
|
||||
|
||||
constexpr bool
|
||||
test_cstr()
|
||||
{
|
||||
const C cs[] = "This has an embedded \0 null";
|
||||
const auto len = (sizeof(cs) - 1)/sizeof(C);
|
||||
|
||||
std::basic_string<C> s1(cs);
|
||||
VERIFY( s1.length() == 21 );
|
||||
std::basic_string<C> s2(cs, std::allocator<C>{});
|
||||
VERIFY( s2 == s1 );
|
||||
|
||||
std::basic_string<C> s3(cs, len);
|
||||
VERIFY( s3.length() == len );
|
||||
VERIFY( s3[len] == '\0' );
|
||||
std::basic_string<C> s4(cs, len, std::allocator<C>{});
|
||||
VERIFY( s4 == s3 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s5(cs);
|
||||
VERIFY( s5 == std::basic_string_view<C>(s1) );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s6(cs, Alloc<C>(6));
|
||||
VERIFY( s6 == std::basic_string_view<C>(s1) );
|
||||
VERIFY( s6.get_allocator().personality == 6 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s7(cs, len, Alloc<C>(7));
|
||||
VERIFY( s7 == std::basic_string_view<C>(s3) );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_cstr() );
|
||||
|
||||
constexpr bool
|
||||
test_copy()
|
||||
{
|
||||
const std::basic_string<C> short_string = "sh";
|
||||
const std::basic_string<C> long_string = "string longer than the SSO buffer";
|
||||
|
||||
std::basic_string<C> s1 = short_string;
|
||||
VERIFY( s1 == short_string );
|
||||
std::basic_string<C> s2(short_string, s1.get_allocator());
|
||||
VERIFY( s2 == short_string );
|
||||
|
||||
std::basic_string<C> s3 = long_string;
|
||||
VERIFY( s3 == long_string );
|
||||
std::basic_string<C> s4(long_string, s1.get_allocator());
|
||||
VERIFY( s4 == long_string );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> a_short_string = short_string.c_str();
|
||||
std::basic_string<C, T, Alloc<C>> a_long_string = long_string.c_str();
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s5(a_short_string);
|
||||
VERIFY( s5 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s6(a_short_string, s5.get_allocator());
|
||||
VERIFY( s6 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s7(a_short_string, Alloc<C>(7));
|
||||
VERIFY( s7 == a_short_string );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s8 = a_long_string;
|
||||
VERIFY( s8 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s9(a_long_string, s5.get_allocator());
|
||||
VERIFY( s9 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s10(a_long_string, Alloc<C>(10));
|
||||
VERIFY( s10 == a_long_string );
|
||||
VERIFY( s10.get_allocator().personality == 10 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_copy() );
|
||||
|
||||
constexpr bool
|
||||
test_move()
|
||||
{
|
||||
const std::basic_string<C> short_string = "sh";
|
||||
const std::basic_string<C> long_string = "string longer than the SSO buffer";
|
||||
|
||||
std::basic_string<C> s0 = short_string;
|
||||
|
||||
std::basic_string<C> s1 = std::move(s0);
|
||||
VERIFY( s1 == short_string );
|
||||
std::basic_string<C> s2(std::move(s1), std::allocator<C>());
|
||||
VERIFY( s2 == short_string );
|
||||
|
||||
s0 = long_string;
|
||||
std::basic_string<C> s3 = std::move(s0);
|
||||
VERIFY( s3 == long_string );
|
||||
std::basic_string<C> s4(std::move(s3), s1.get_allocator());
|
||||
VERIFY( s4 == long_string );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> a_short_string = short_string.c_str();
|
||||
std::basic_string<C, T, Alloc<C>> a_long_string = long_string.c_str();
|
||||
|
||||
auto sa0 = a_short_string;
|
||||
std::basic_string<C, T, Alloc<C>> s5 = std::move(sa0);
|
||||
VERIFY( s5 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s6(std::move(s5), sa0.get_allocator());
|
||||
VERIFY( s6 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s7(std::move(s6), Alloc<C>(7));
|
||||
VERIFY( s7 == a_short_string );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
sa0 = a_long_string;
|
||||
std::basic_string<C, T, Alloc<C>> s8 = std::move(sa0);
|
||||
VERIFY( s8 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s9(std::move(s8), s5.get_allocator());
|
||||
VERIFY( s9 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s10(std::move(s9), Alloc<C>(10));
|
||||
VERIFY( s10 == a_long_string );
|
||||
VERIFY( s10.get_allocator().personality == 10 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_move() );
|
@ -0,0 +1,174 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef __cpp_lib_constexpr_string
|
||||
# error "Feature-test macro for constexpr std::string missing in <string>"
|
||||
#elif __cpp_lib_constexpr_string != 201907L
|
||||
# error "Feature-test macro for constexpr std::string has wrong value in <string>"
|
||||
#endif
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using C = wchar_t;
|
||||
using T = std::char_traits<C>;
|
||||
|
||||
template<typename T>
|
||||
struct Alloc : std::allocator<T>
|
||||
{
|
||||
using std::allocator<T>::allocator;
|
||||
|
||||
constexpr explicit Alloc(int p) : personality(p) { }
|
||||
|
||||
template<typename U>
|
||||
constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
|
||||
|
||||
int personality = 0;
|
||||
|
||||
constexpr Alloc select_on_container_copy_construction() const
|
||||
{ return Alloc(-1); }
|
||||
|
||||
constexpr bool operator==(const Alloc& a) const noexcept
|
||||
{ return personality == a.personality; }
|
||||
};
|
||||
|
||||
constexpr bool
|
||||
test_default_ctor()
|
||||
{
|
||||
std::basic_string<C> s0;
|
||||
VERIFY( s0.empty() );
|
||||
|
||||
std::basic_string<C> s1(std::allocator<C>{});
|
||||
VERIFY( s1.empty() );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s2;
|
||||
VERIFY( s2.empty() );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s3(Alloc<C>(3));
|
||||
VERIFY( s3.empty() );
|
||||
VERIFY( s3.get_allocator().personality == 3 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_default_ctor() );
|
||||
|
||||
constexpr bool
|
||||
test_cstr()
|
||||
{
|
||||
const C cs[] = L"This has an embedded \0 null";
|
||||
const auto len = (sizeof(cs) - 1)/sizeof(C);
|
||||
|
||||
std::basic_string<C> s1(cs);
|
||||
VERIFY( s1.length() == 21 );
|
||||
std::basic_string<C> s2(cs, std::allocator<C>{});
|
||||
VERIFY( s2 == s1 );
|
||||
|
||||
std::basic_string<C> s3(cs, len);
|
||||
VERIFY( s3.length() == len );
|
||||
VERIFY( s3[len] == L'\0' );
|
||||
std::basic_string<C> s4(cs, len, std::allocator<C>{});
|
||||
VERIFY( s4 == s3 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s5(cs);
|
||||
VERIFY( s5 == std::basic_string_view<C>(s1) );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s6(cs, Alloc<C>(6));
|
||||
VERIFY( s6 == std::basic_string_view<C>(s1) );
|
||||
VERIFY( s6.get_allocator().personality == 6 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s7(cs, len, Alloc<C>(7));
|
||||
VERIFY( s7 == std::basic_string_view<C>(s3) );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_cstr() );
|
||||
|
||||
constexpr bool
|
||||
test_copy()
|
||||
{
|
||||
const std::basic_string<C> short_string = L"sh";
|
||||
const std::basic_string<C> long_string = L"string longer than the SSO buffer";
|
||||
|
||||
std::basic_string<C> s1 = short_string;
|
||||
VERIFY( s1 == short_string );
|
||||
std::basic_string<C> s2(short_string, s1.get_allocator());
|
||||
VERIFY( s2 == short_string );
|
||||
|
||||
std::basic_string<C> s3 = long_string;
|
||||
VERIFY( s3 == long_string );
|
||||
std::basic_string<C> s4(long_string, s1.get_allocator());
|
||||
VERIFY( s4 == long_string );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> a_short_string = short_string.c_str();
|
||||
std::basic_string<C, T, Alloc<C>> a_long_string = long_string.c_str();
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s5(a_short_string);
|
||||
VERIFY( s5 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s6(a_short_string, s5.get_allocator());
|
||||
VERIFY( s6 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s7(a_short_string, Alloc<C>(7));
|
||||
VERIFY( s7 == a_short_string );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> s8 = a_long_string;
|
||||
VERIFY( s8 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s9(a_long_string, s5.get_allocator());
|
||||
VERIFY( s9 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s10(a_long_string, Alloc<C>(10));
|
||||
VERIFY( s10 == a_long_string );
|
||||
VERIFY( s10.get_allocator().personality == 10 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_copy() );
|
||||
|
||||
constexpr bool
|
||||
test_move()
|
||||
{
|
||||
const std::basic_string<C> short_string = L"sh";
|
||||
const std::basic_string<C> long_string = L"string longer than the SSO buffer";
|
||||
|
||||
std::basic_string<C> s0 = short_string;
|
||||
|
||||
std::basic_string<C> s1 = std::move(s0);
|
||||
VERIFY( s1 == short_string );
|
||||
std::basic_string<C> s2(std::move(s1), std::allocator<C>());
|
||||
VERIFY( s2 == short_string );
|
||||
|
||||
s0 = long_string;
|
||||
std::basic_string<C> s3 = std::move(s0);
|
||||
VERIFY( s3 == long_string );
|
||||
std::basic_string<C> s4(std::move(s3), s1.get_allocator());
|
||||
VERIFY( s4 == long_string );
|
||||
|
||||
std::basic_string<C, T, Alloc<C>> a_short_string = short_string.c_str();
|
||||
std::basic_string<C, T, Alloc<C>> a_long_string = long_string.c_str();
|
||||
|
||||
auto sa0 = a_short_string;
|
||||
std::basic_string<C, T, Alloc<C>> s5 = std::move(sa0);
|
||||
VERIFY( s5 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s6(std::move(s5), sa0.get_allocator());
|
||||
VERIFY( s6 == a_short_string );
|
||||
std::basic_string<C, T, Alloc<C>> s7(std::move(s6), Alloc<C>(7));
|
||||
VERIFY( s7 == a_short_string );
|
||||
VERIFY( s7.get_allocator().personality == 7 );
|
||||
|
||||
sa0 = a_long_string;
|
||||
std::basic_string<C, T, Alloc<C>> s8 = std::move(sa0);
|
||||
VERIFY( s8 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s9(std::move(s8), s5.get_allocator());
|
||||
VERIFY( s9 == a_long_string );
|
||||
std::basic_string<C, T, Alloc<C>> s10(std::move(s9), Alloc<C>(10));
|
||||
VERIFY( s10 == a_long_string );
|
||||
VERIFY( s10.get_allocator().personality == 10 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_move() );
|
@ -0,0 +1,22 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_literals()
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
auto s = "narrow string"s;
|
||||
auto sw = L"wide string"s;
|
||||
auto s8 = u8"UTF-8 string"s;
|
||||
auto su = u"UTF-16 string"s;
|
||||
auto sU = U"UTF-32 string"s;
|
||||
|
||||
return !s.empty() && !sw.empty() && !s8.empty() && !su.empty() && !sU.empty();
|
||||
}
|
||||
|
||||
static_assert( test_literals() );
|
@ -0,0 +1,52 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_insert()
|
||||
{
|
||||
std::string s;
|
||||
s.insert(0, "one");
|
||||
VERIFY( s == "one" );
|
||||
s.insert(0, "eleventy-");
|
||||
VERIFY( s == "eleventy-one" );
|
||||
s.insert(6, "ses at ten thirteen", 15);
|
||||
VERIFY( s == "elevenses at ten thirty-one" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_insert() );
|
||||
|
||||
constexpr bool
|
||||
test_replace()
|
||||
{
|
||||
std::string s = "abcdef";
|
||||
s.replace(2, 1, s.c_str(), 3);
|
||||
VERIFY( s == "ababcdef" );
|
||||
s.replace(0, 2, "", 0);
|
||||
VERIFY( s == "abcdef" );
|
||||
s.replace(1, 4, "ardwol", 6);
|
||||
VERIFY( s == "aardwolf" );
|
||||
s.replace(4, 0, "vark not wolf");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_replace() );
|
||||
|
||||
constexpr bool
|
||||
test_erasure()
|
||||
{
|
||||
std::string s = "Spiritualized Electric Mainline";
|
||||
std::erase(s, 'i');
|
||||
VERIFY( s == "Sprtualzed Electrc Manlne" );
|
||||
std::erase_if(s, [](char c) { return c == 'l'; });
|
||||
VERIFY( s == "Sprtuazed Eectrc Manne" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_erasure() );
|
@ -0,0 +1,49 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using C = char;
|
||||
using T = std::char_traits<C>;
|
||||
|
||||
constexpr bool
|
||||
test_swap()
|
||||
{
|
||||
std::basic_string<C> s0;
|
||||
s0.swap(s0);
|
||||
VERIFY( s0.empty() );
|
||||
std::basic_string<C> s00;
|
||||
s0.swap(s00);
|
||||
VERIFY( s0.empty() );
|
||||
VERIFY( s00.empty() );
|
||||
|
||||
std::basic_string<C> s1 = "s1";
|
||||
s1.swap(s0);
|
||||
VERIFY( s1.empty() );
|
||||
VERIFY( ! s0.empty() );
|
||||
s1.swap(s0);
|
||||
VERIFY( s0.empty() );
|
||||
VERIFY( ! s1.empty() );
|
||||
|
||||
std::basic_string<C> s2 = "quite a long string, but not very long";
|
||||
s2.swap(s1);
|
||||
VERIFY( s2.length() == 2 );
|
||||
VERIFY( s1.length() == 38 );
|
||||
s2.swap(s1);
|
||||
VERIFY( s1.length() == 2 );
|
||||
VERIFY( s2.length() == 38 );
|
||||
|
||||
swap(s2, s0);
|
||||
VERIFY( s2.empty() );
|
||||
VERIFY( s0.length() == 38 );
|
||||
|
||||
auto s3 = s0;
|
||||
swap(s3, s0);
|
||||
VERIFY( s3 == s0 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_swap() );
|
@ -0,0 +1,49 @@
|
||||
// { dg-options "-std=gnu++20" }
|
||||
// { dg-do compile { target c++20 } }
|
||||
// { dg-require-effective-target cxx11-abi }
|
||||
|
||||
#include <string>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using C = wchar_t;
|
||||
using T = std::char_traits<C>;
|
||||
|
||||
constexpr bool
|
||||
test_swap()
|
||||
{
|
||||
std::basic_string<C> s0;
|
||||
s0.swap(s0);
|
||||
VERIFY( s0.empty() );
|
||||
std::basic_string<C> s00;
|
||||
s0.swap(s00);
|
||||
VERIFY( s0.empty() );
|
||||
VERIFY( s00.empty() );
|
||||
|
||||
std::basic_string<C> s1 = L"s1";
|
||||
s1.swap(s0);
|
||||
VERIFY( s1.empty() );
|
||||
VERIFY( ! s0.empty() );
|
||||
s1.swap(s0);
|
||||
VERIFY( s0.empty() );
|
||||
VERIFY( ! s1.empty() );
|
||||
|
||||
std::basic_string<C> s2 = L"quite a long string, but not very long";
|
||||
s2.swap(s1);
|
||||
VERIFY( s2.length() == 2 );
|
||||
VERIFY( s1.length() == 38 );
|
||||
s2.swap(s1);
|
||||
VERIFY( s1.length() == 2 );
|
||||
VERIFY( s2.length() == 38 );
|
||||
|
||||
swap(s2, s0);
|
||||
VERIFY( s2.empty() );
|
||||
VERIFY( s0.length() == 38 );
|
||||
|
||||
auto s3 = s0;
|
||||
swap(s3, s0);
|
||||
VERIFY( s3 == s0 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( test_swap() );
|
25
libstdc++-v3/testsuite/21_strings/basic_string/version.cc
Normal file
25
libstdc++-v3/testsuite/21_strings/basic_string/version.cc
Normal file
@ -0,0 +1,25 @@
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
#include <version>
|
||||
|
||||
#ifndef __cpp_lib_constexpr_string
|
||||
# error "Feature-test macro for constexpr std::string missing in <version>"
|
||||
#endif
|
||||
|
||||
#if __cplusplus == 201703L
|
||||
# if __cpp_lib_constexpr_string != 201611L
|
||||
# error "Feature-test macro for constexpr std::string has wrong value for C++17 in <version>"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if __cplusplus == 202002L
|
||||
# if _GLIBCXX_USE_CXX11_ABI
|
||||
# if __cpp_lib_constexpr_string != 201907L
|
||||
# error "Feature-test macro for constexpr std::string has wrong value for C++20 in <version>"
|
||||
# endif
|
||||
# else // COW strings
|
||||
# if __cpp_lib_constexpr_string != 201811L
|
||||
# error "Feature-test macro for constexpr std::string has wrong value for C++20 in <version>"
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user