// Components for manipulating sequences of characters -*- C++ -*-
-// Copyright (C) 1997-2016 Free Software Foundation, Inc.
+// Copyright (C) 1997-2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
#include <initializer_list>
#endif
+#if __cplusplus >= 201703L
+# include <string_view>
+#endif
+
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Value returned by various member functions when they fail.
static const size_type npos = static_cast<size_type>(-1);
- private:
+ protected:
// type used for positions in insert, erase etc.
#if __cplusplus < 201103L
typedef iterator __const_iterator;
typedef const_iterator __const_iterator;
#endif
+ private:
+#if __cplusplus >= 201703L
+ // A helper type for avoiding boiler-plate.
+ typedef basic_string_view<_CharT, _Traits> __sv_type;
+
+ template<typename _Tp, typename _Res>
+ using _If_sv = enable_if_t<
+ __and_<is_convertible<const _Tp&, __sv_type>,
+ __not_<is_convertible<const _Tp*, const basic_string*>>,
+ __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
+ _Res>;
+
+ // Allows an implicit conversion to __sv_type.
+ static __sv_type
+ _S_to_string_view(__sv_type __svt) noexcept
+ { return __svt; }
+
+ // Wraps a string_view by explicit conversion and thus
+ // allows to add an internal constructor that does not
+ // participate in overload resolution when a string_view
+ // is provided.
+ struct __sv_wrapper
+ {
+ explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
+ __sv_type _M_sv;
+ };
+
+ /**
+ * @brief Only internally used: Construct string from a string view
+ * wrapper.
+ * @param __svw string view wrapper.
+ * @param __a Allocator to use.
+ */
+ explicit
+ basic_string(__sv_wrapper __svw, const _Alloc& __a)
+ : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
+#endif
+
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : allocator_type // TODO check __is_final
{
}
void
- _M_assign(const basic_string& __rcs);
+ _M_assign(const basic_string&);
void
_M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
_Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
{ _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2583. no way to supply an allocator for basic_string(str, pos)
/**
* @brief Construct string as copy of a substring.
* @param __str Source string.
* @param __pos Index of first character to copy from.
- * @param __n Number of characters to copy (default remainder).
+ * @param __a Allocator to use.
+ */
+ basic_string(const basic_string& __str, size_type __pos,
+ const _Alloc& __a = _Alloc())
+ : _M_dataplus(_M_local_data(), __a)
+ {
+ const _CharT* __start = __str._M_data()
+ + __str._M_check(__pos, "basic_string::basic_string");
+ _M_construct(__start, __start + __str._M_limit(__pos, npos));
+ }
+
+ /**
+ * @brief Construct string as copy of a substring.
+ * @param __str Source string.
+ * @param __pos Index of first character to copy from.
+ * @param __n Number of characters to copy.
*/
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2402. [this constructor] shouldn't use Allocator()
basic_string(const basic_string& __str, size_type __pos,
- size_type __n = npos)
+ size_type __n)
: _M_dataplus(_M_local_data())
{
const _CharT* __start = __str._M_data()
* @brief Construct string as copy of a substring.
* @param __str Source string.
* @param __pos Index of first character to copy from.
- * @param __n Number of characters to copy (default remainder).
+ * @param __n Number of characters to copy.
* @param __a Allocator to use.
*/
basic_string(const basic_string& __str, size_type __pos,
* @param __s Source C string.
* @param __a Allocator to use (default is default allocator).
*/
+#if __cpp_deduction_guides && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3076. basic_string CTAD ambiguity
+ template<typename = _RequireAllocator<_Alloc>>
+#endif
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
: _M_dataplus(_M_local_data(), __a)
{ _M_construct(__s, __s ? __s + traits_type::length(__s) : __s+npos); }
* @param __c Character to use.
* @param __a Allocator to use (default is default allocator).
*/
+#if __cpp_deduction_guides && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3076. basic_string CTAD ambiguity
+ template<typename = _RequireAllocator<_Alloc>>
+#endif
basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
: _M_dataplus(_M_local_data(), __a)
{ _M_construct(__n, __c); }
: _M_dataplus(_M_local_data(), __a)
{ _M_construct(__beg, __end); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Construct string from a substring of a string_view.
+ * @param __t Source object convertible to string view.
+ * @param __pos The index of the first character to copy from __t.
+ * @param __n The number of characters to copy from __t.
+ * @param __a Allocator to use.
+ */
+ template<typename _Tp, typename = _If_sv<_Tp, void>>
+ basic_string(const _Tp& __t, size_type __pos, size_type __n,
+ const _Alloc& __a = _Alloc())
+ : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
+
+ /**
+ * @brief Construct string from a string_view.
+ * @param __t Source object convertible to string view.
+ * @param __a Allocator to use (default is default allocator).
+ */
+ template<typename _Tp, typename = _If_sv<_Tp, void>>
+ explicit
+ basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
+ : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
+#endif // C++17
+
/**
* @brief Destroy the string instance.
*/
basic_string&
operator=(const basic_string& __str)
{
-#if __cplusplus >= 201103L
- if (_Alloc_traits::_S_propagate_on_copy_assign())
- {
- if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
- && _M_get_allocator() != __str._M_get_allocator())
- {
- // replacement allocator cannot free existing storage
- _M_destroy(_M_allocated_capacity);
- _M_data(_M_local_data());
- _M_set_length(0);
- }
- std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
- }
-#endif
return this->assign(__str);
}
* The contents of @a str are moved into this string (without copying).
* @a str is a valid, but unspecified string.
**/
- // PR 58265, this should be noexcept.
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2063. Contradictory requirements for string move assignment
basic_string&
// Replace allocator if POCMA is true.
std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
- if (!__str._M_is_local()
- && (_Alloc_traits::_S_propagate_on_move_assign()
- || _Alloc_traits::_S_always_equal()))
+ if (__str._M_is_local())
+ {
+ // We've always got room for a short string, just copy it.
+ if (__str.size())
+ this->_S_copy(_M_data(), __str._M_data(), __str.size());
+ _M_set_length(__str.size());
+ }
+ else if (_Alloc_traits::_S_propagate_on_move_assign()
+ || _Alloc_traits::_S_always_equal()
+ || _M_get_allocator() == __str._M_get_allocator())
{
+ // Just move the allocated pointer, our allocator can free it.
pointer __data = nullptr;
size_type __capacity;
if (!_M_is_local())
{
if (_Alloc_traits::_S_always_equal())
{
+ // __str can reuse our existing storage.
__data = _M_data();
__capacity = _M_allocated_capacity;
}
- else
+ else // __str can't use it, so free it.
_M_destroy(_M_allocated_capacity);
}
else
__str._M_data(__str._M_local_buf);
}
- else
- assign(__str);
+ else // Need to do a deep copy
+ assign(__str);
__str.clear();
return *this;
}
}
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Set value to string constructed from a string_view.
+ * @param __svt An object convertible to string_view.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ operator=(const _Tp& __svt)
+ { return this->assign(__svt); }
+
+ /**
+ * @brief Convert to a string_view.
+ * @return A string_view.
+ */
+ operator __sv_type() const noexcept
+ { return __sv_type(data(), size()); }
+#endif // C++17
+
// Iterators:
/**
* Returns a read/write iterator that points to the first character in
* Returns true if the %string is empty. Equivalent to
* <code>*this == ""</code>.
*/
- bool
+ _GLIBCXX_NODISCARD bool
empty() const _GLIBCXX_NOEXCEPT
{ return this->size() == 0; }
{ return this->append(__l.begin(), __l.size()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Append a string_view.
+ * @param __svt An object convertible to string_view to be appended.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ operator+=(const _Tp& __svt)
+ { return this->append(__svt); }
+#endif // C++17
+
/**
* @brief Append a string to this string.
* @param __str The string to append.
* remainder of @a __str is appended.
*/
basic_string&
- append(const basic_string& __str, size_type __pos, size_type __n)
+ append(const basic_string& __str, size_type __pos, size_type __n = npos)
{ return _M_append(__str._M_data()
+ __str._M_check(__pos, "basic_string::append"),
__str._M_limit(__pos, __n)); }
append(_InputIterator __first, _InputIterator __last)
{ return this->replace(end(), end(), __first, __last); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Append a string_view.
+ * @param __svt An object convertible to string_view to be appended.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ append(const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->append(__sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Append a range of characters from a string_view.
+ * @param __svt An object convertible to string_view to be appended from.
+ * @param __pos The position in the string_view to append from.
+ * @param __n The number of characters to append from the string_view.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ append(const _Tp& __svt, size_type __pos, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return _M_append(__sv.data()
+ + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+ std::__sv_limit(__sv.size(), __pos, __n));
+ }
+#endif // C++17
+
/**
* @brief Append a single character.
* @param __c Character to append.
basic_string&
assign(const basic_string& __str)
{
+#if __cplusplus >= 201103L
+ if (_Alloc_traits::_S_propagate_on_copy_assign())
+ {
+ if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
+ && _M_get_allocator() != __str._M_get_allocator())
+ {
+ // Propagating allocator cannot free existing storage so must
+ // deallocate it before replacing current allocator.
+ if (__str.size() <= _S_local_capacity)
+ {
+ _M_destroy(_M_allocated_capacity);
+ _M_data(_M_local_data());
+ _M_set_length(0);
+ }
+ else
+ {
+ const auto __len = __str.size();
+ auto __alloc = __str._M_get_allocator();
+ // If this allocation throws there are no effects:
+ auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
+ _M_destroy(_M_allocated_capacity);
+ _M_data(__ptr);
+ _M_capacity(__len);
+ _M_set_length(__len);
+ }
+ }
+ std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
+ }
+#endif
this->_M_assign(__str);
return *this;
}
* __str, the remainder of @a __str is used.
*/
basic_string&
- assign(const basic_string& __str, size_type __pos, size_type __n)
+ assign(const basic_string& __str, size_type __pos, size_type __n = npos)
{ return _M_replace(size_type(0), this->size(), __str._M_data()
+ __str._M_check(__pos, "basic_string::assign"),
__str._M_limit(__pos, __n)); }
{ return this->assign(__l.begin(), __l.size()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Set value from a string_view.
+ * @param __svt The source object convertible to string_view.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ assign(const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->assign(__sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Set value from a range of characters in a string_view.
+ * @param __svt The source object convertible to string_view.
+ * @param __pos The position in the string_view to assign from.
+ * @param __n The number of characters to assign.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return _M_replace(size_type(0), this->size(),
+ __sv.data()
+ + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
+ std::__sv_limit(__sv.size(), __pos, __n));
+ }
+#endif // C++17
+
#if __cplusplus >= 201103L
/**
* @brief Insert multiple characters.
* @param __l The initializer_list of characters to insert.
* @throw std::length_error If new length exceeds @c max_size().
*/
+ iterator
+ insert(const_iterator __p, initializer_list<_CharT> __l)
+ { return this->insert(__p, __l.begin(), __l.end()); }
+
+#ifdef _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
+ // See PR libstdc++/83328
void
insert(iterator __p, initializer_list<_CharT> __l)
{
_GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
this->insert(__p - begin(), __l.begin(), __l.size());
}
+#endif
#endif // C++11
/**
* @brief Insert value of a string.
- * @param __pos1 Iterator referencing location in string to insert at.
+ * @param __pos1 Position in string to insert at.
* @param __str The string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
/**
* @brief Insert a substring.
- * @param __pos1 Iterator referencing location in string to insert at.
- * @param __str The string to insert.
+ * @param __pos1 Position in string to insert at.
+ * @param __str The string to insert.
* @param __pos2 Start of characters in str to insert.
* @param __n Number of characters to insert.
* @return Reference to this string.
*/
basic_string&
insert(size_type __pos1, const basic_string& __str,
- size_type __pos2, size_type __n)
+ size_type __pos2, size_type __n = npos)
{ return this->replace(__pos1, size_type(0), __str._M_data()
+ __str._M_check(__pos2, "basic_string::insert"),
__str._M_limit(__pos2, __n)); }
/**
* @brief Insert a C substring.
- * @param __pos Iterator referencing location in string to insert at.
+ * @param __pos Position in string to insert at.
* @param __s The C string to insert.
* @param __n The number of characters to insert.
* @return Reference to this string.
/**
* @brief Insert a C string.
- * @param __pos Iterator referencing location in string to insert at.
+ * @param __pos Position in string to insert at.
* @param __s The C string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
return iterator(_M_data() + __pos);
}
+#if __cplusplus >= 201703L
+ /**
+ * @brief Insert a string_view.
+ * @param __pos Position in string to insert at.
+ * @param __svt The object convertible to string_view to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ insert(size_type __pos, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->insert(__pos, __sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Insert a string_view.
+ * @param __pos1 Position in string to insert at.
+ * @param __svt The object convertible to string_view to insert from.
+ * @param __pos2 Start of characters in str to insert.
+ * @param __n The number of characters to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ insert(size_type __pos1, const _Tp& __svt,
+ size_type __pos2, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos1, size_type(0),
+ __sv.data()
+ + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
+ std::__sv_limit(__sv.size(), __pos2, __n));
+ }
+#endif // C++17
+
/**
* @brief Remove characters.
* @param __pos Index of first character to remove (default 0).
basic_string&
erase(size_type __pos = 0, size_type __n = npos)
{
- this->_M_erase(_M_check(__pos, "basic_string::erase"),
- _M_limit(__pos, __n));
+ _M_check(__pos, "basic_string::erase");
+ if (__n == npos)
+ this->_M_set_length(__pos);
+ else if (__n != 0)
+ this->_M_erase(__pos, _M_limit(__pos, __n));
return *this;
}
_GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last
&& __last <= end());
const size_type __pos = __first - begin();
- this->_M_erase(__pos, __last - __first);
+ if (__last == end())
+ this->_M_set_length(__pos);
+ else
+ this->_M_erase(__pos, __last - __first);
return iterator(this->_M_data() + __pos);
}
*/
basic_string&
replace(size_type __pos1, size_type __n1, const basic_string& __str,
- size_type __pos2, size_type __n2)
+ size_type __pos2, size_type __n2 = npos)
{ return this->replace(__pos1, __n1, __str._M_data()
+ __str._M_check(__pos2, "basic_string::replace"),
__str._M_limit(__pos2, __n2)); }
{ return this->replace(__i1, __i2, __l.begin(), __l.size()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __pos The position to replace at.
+ * @param __n The number of characters to replace.
+ * @param __svt The object convertible to string_view to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(size_type __pos, size_type __n, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos, __n, __sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __pos1 The position to replace at.
+ * @param __n1 The number of characters to replace.
+ * @param __svt The object convertible to string_view to insert from.
+ * @param __pos2 The position in the string_view to insert from.
+ * @param __n2 The number of characters to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(size_type __pos1, size_type __n1, const _Tp& __svt,
+ size_type __pos2, size_type __n2 = npos)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos1, __n1,
+ __sv.data()
+ + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+ std::__sv_limit(__sv.size(), __pos2, __n2));
+ }
+
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __i1 An iterator referencing the start position
+ to replace at.
+ * @param __i2 An iterator referencing the end position
+ for the replace.
+ * @param __svt The object convertible to string_view to insert from.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__i1 - begin(), __i2 - __i1, __sv);
+ }
+#endif // C++17
+
private:
template<class _Integer>
basic_string&
/**
* @brief Return const pointer to contents.
*
- * This is a handle to internal data. Do not modify or dire things may
- * happen.
+ * This is a pointer to internal data. It is undefined to modify
+ * the contents through the returned pointer. To get a pointer that
+ * allows modifying the contents use @c &str[0] instead,
+ * (or in C++17 the non-const @c str.data() overload).
*/
const _CharT*
data() const _GLIBCXX_NOEXCEPT
{ return _M_data(); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Return non-const pointer to contents.
+ *
+ * This is a pointer to the character sequence held by the string.
+ * Modifying the characters in the sequence is allowed.
+ */
+ _CharT*
+ data() noexcept
+ { return _M_data(); }
+#endif
+
/**
* @brief Return copy of allocator used to construct this string.
*/
* npos.
*/
size_type
- find(const _CharT* __s, size_type __pos, size_type __n) const;
+ find(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a string.
*/
size_type
find(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a string_view.
+ * @param __svt The object convertible to string_view to locate.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of start of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find position of a C string.
* @param __s C string to locate.
* it begins. If not found, returns npos.
*/
size_type
- find(const _CharT* __s, size_type __pos = 0) const
+ find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find(__s, __pos, traits_type::length(__s));
*/
size_type
rfind(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->rfind(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a string_view.
+ * @param __svt The object convertible to string_view to locate.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of start of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ rfind(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->rfind(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find last position of a C substring.
* @param __s C string to locate.
* npos.
*/
size_type
- rfind(const _CharT* __s, size_type __pos, size_type __n) const;
+ rfind(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a C string.
*/
size_type
find_first_of(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_first_of(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a character of a string_view.
+ * @param __svt An object convertible to string_view containing
+ * characters to locate.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_first_of(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_first_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find position of a character of C substring.
* @param __s String containing characters to locate.
* returns npos.
*/
size_type
- find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
+ find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a character of C string.
*/
size_type
find_first_of(const _CharT* __s, size_type __pos = 0) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_first_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_last_of(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_last_of(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a character of string.
+ * @param __svt An object convertible to string_view containing
+ * characters to locate.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_last_of(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_last_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find last position of a character of C substring.
* @param __s C string containing characters to locate.
* returns npos.
*/
size_type
- find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
+ find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a character of C string.
*/
size_type
find_last_of(const _CharT* __s, size_type __pos = npos) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_last_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_first_not_of(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_first_not_of(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a character not in a string_view.
+ * @param __svt A object convertible to string_view containing
+ * characters to avoid.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_first_not_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find position of a character not in C substring.
* @param __s C string containing characters to avoid.
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos,
- size_type __n) const;
+ size_type __n) const _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a character not in C string.
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos = 0) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_first_not_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_first_not_of(_CharT __c, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT;
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a character not in string.
*/
size_type
find_last_not_of(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_last_not_of(__str.data(), __pos, __str.size()); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a character not in a string_view.
+ * @param __svt An object convertible to string_view containing
+ * characters to avoid.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_last_not_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find last position of a character not in C substring.
* @param __s C string containing characters to avoid.
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos,
- size_type __n) const;
+ size_type __n) const _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a character not in C string.
* @param __s C string containing characters to avoid.
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos = npos) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_last_not_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_last_not_of(_CharT __c, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT;
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Get a substring.
return __r;
}
+#if __cplusplus >= 201703L
+ /**
+ * @brief Compare to a string_view.
+ * @param __svt An object convertible to string_view to compare against.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(const _Tp& __svt) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ const size_type __size = this->size();
+ const size_type __osize = __sv.size();
+ const size_type __len = std::min(__size, __osize);
+
+ int __r = traits_type::compare(_M_data(), __sv.data(), __len);
+ if (!__r)
+ __r = _S_compare(__size, __osize);
+ return __r;
+ }
+
+ /**
+ * @brief Compare to a string_view.
+ * @param __pos A position in the string to start comparing from.
+ * @param __n The number of characters to compare.
+ * @param __svt An object convertible to string_view to compare
+ * against.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(size_type __pos, size_type __n, const _Tp& __svt) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return __sv_type(*this).substr(__pos, __n).compare(__sv);
+ }
+
+ /**
+ * @brief Compare to a string_view.
+ * @param __pos1 A position in the string to start comparing from.
+ * @param __n1 The number of characters to compare.
+ * @param __svt An object convertible to string_view to compare
+ * against.
+ * @param __pos2 A position in the string_view to start comparing from.
+ * @param __n2 The number of characters to compare.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(size_type __pos1, size_type __n1, const _Tp& __svt,
+ size_type __pos2, size_type __n2 = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return __sv_type(*this)
+ .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
+ }
+#endif // C++17
+
/**
* @brief Compare substring to a string.
* @param __pos Index of first character of substring.
*/
int
compare(size_type __pos1, size_type __n1, const basic_string& __str,
- size_type __pos2, size_type __n2) const;
+ size_type __pos2, size_type __n2 = npos) const;
/**
* @brief Compare to a C string.
* ordered first.
*/
int
- compare(const _CharT* __s) const;
+ compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 5 String::compare specification questionable
int
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const;
- };
+
+#if __cplusplus > 201703L
+ bool
+ starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ starts_with(_CharT __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ starts_with(const _CharT* __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+
+ bool
+ ends_with(_CharT __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+
+ bool
+ ends_with(const _CharT* __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+#endif // C++20
+
+ // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
+ template<typename, typename, typename> friend class basic_stringbuf;
+ };
_GLIBCXX_END_NAMESPACE_CXX11
#else // !_GLIBCXX_USE_CXX11_ABI
// Reference-counted COW string implentation
template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string
{
- typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
+ rebind<_CharT>::other _CharT_alloc_type;
+ typedef __gnu_cxx::__alloc_traits<_CharT_alloc_type> _CharT_alloc_traits;
// Types:
public:
typedef _Alloc allocator_type;
typedef typename _CharT_alloc_type::size_type size_type;
typedef typename _CharT_alloc_type::difference_type difference_type;
+#if __cplusplus < 201103L
typedef typename _CharT_alloc_type::reference reference;
typedef typename _CharT_alloc_type::const_reference const_reference;
- typedef typename _CharT_alloc_type::pointer pointer;
- typedef typename _CharT_alloc_type::const_pointer const_pointer;
+#else
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+#endif
+ typedef typename _CharT_alloc_traits::pointer pointer;
+ typedef typename _CharT_alloc_traits::const_pointer const_pointer;
typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
+ protected:
+ // type used for positions in insert, erase etc.
+ typedef iterator __const_iterator;
+
private:
// _Rep: string representation
// Invariants:
struct _Rep : _Rep_base
{
// Types:
- typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc;
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
+ rebind<char>::other _Raw_bytes_alloc;
// (Public) Data members:
_S_empty_rep() _GLIBCXX_NOEXCEPT
{ return _Rep::_S_empty_rep(); }
+#if __cplusplus >= 201703L
+ // A helper type for avoiding boiler-plate.
+ typedef basic_string_view<_CharT, _Traits> __sv_type;
+
+ template<typename _Tp, typename _Res>
+ using _If_sv = enable_if_t<
+ __and_<is_convertible<const _Tp&, __sv_type>,
+ __not_<is_convertible<const _Tp*, const basic_string*>>,
+ __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
+ _Res>;
+
+ // Allows an implicit conversion to __sv_type.
+ static __sv_type
+ _S_to_string_view(__sv_type __svt) noexcept
+ { return __svt; }
+
+ // Wraps a string_view by explicit conversion and thus
+ // allows to add an internal constructor that does not
+ // participate in overload resolution when a string_view
+ // is provided.
+ struct __sv_wrapper
+ {
+ explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
+ __sv_type _M_sv;
+ };
+
+ /**
+ * @brief Only internally used: Construct string from a string view
+ * wrapper.
+ * @param __svw string view wrapper.
+ * @param __a Allocator to use.
+ */
+ explicit
+ basic_string(__sv_wrapper __svw, const _Alloc& __a)
+ : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
+#endif
+
public:
// Construct/copy/destroy:
// NB: We overload ctors in some cases instead of using default
*/
basic_string()
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
- : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
+ _GLIBCXX_NOEXCEPT
+ : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())
#else
- : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()){ }
+ : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())
#endif
+ { }
/**
* @brief Construct an empty string using allocator @a a.
* @param __str Source string.
*/
basic_string(const basic_string& __str);
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2583. no way to supply an allocator for basic_string(str, pos)
+ /**
+ * @brief Construct string as copy of a substring.
+ * @param __str Source string.
+ * @param __pos Index of first character to copy from.
+ * @param __a Allocator to use.
+ */
+ basic_string(const basic_string& __str, size_type __pos,
+ const _Alloc& __a = _Alloc());
+
/**
* @brief Construct string as copy of a substring.
* @param __str Source string.
* @param __pos Index of first character to copy from.
- * @param __n Number of characters to copy (default remainder).
+ * @param __n Number of characters to copy.
*/
basic_string(const basic_string& __str, size_type __pos,
- size_type __n = npos);
+ size_type __n);
/**
* @brief Construct string as copy of a substring.
* @param __str Source string.
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
noexcept // FIXME C++11: should always be noexcept.
#endif
- : _M_dataplus(__str._M_dataplus)
+ : _M_dataplus(std::move(__str._M_dataplus))
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
__str._M_data(_S_empty_rep()._M_refdata());
* @param __a Allocator to use (default is default allocator).
*/
basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc());
+
+ basic_string(const basic_string& __str, const _Alloc& __a)
+ : _M_dataplus(__str._M_rep()->_M_grab(__a, __str.get_allocator()), __a)
+ { }
+
+ basic_string(basic_string&& __str, const _Alloc& __a)
+ : _M_dataplus(__str._M_data(), __a)
+ {
+ if (__a == __str.get_allocator())
+ {
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+ __str._M_data(_S_empty_rep()._M_refdata());
+#else
+ __str._M_data(_S_construct(size_type(), _CharT(), __a));
+#endif
+ }
+ else
+ _M_dataplus._M_p = _S_construct(__str.begin(), __str.end(), __a);
+ }
#endif // C++11
/**
basic_string(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a = _Alloc());
+#if __cplusplus >= 201703L
+ /**
+ * @brief Construct string from a substring of a string_view.
+ * @param __t Source object convertible to string view.
+ * @param __pos The index of the first character to copy from __t.
+ * @param __n The number of characters to copy from __t.
+ * @param __a Allocator to use.
+ */
+ template<typename _Tp, typename = _If_sv<_Tp, void>>
+ basic_string(const _Tp& __t, size_type __pos, size_type __n,
+ const _Alloc& __a = _Alloc())
+ : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
+
+ /**
+ * @brief Construct string from a string_view.
+ * @param __t Source object convertible to string view.
+ * @param __a Allocator to use (default is default allocator).
+ */
+ template<typename _Tp, typename = _If_sv<_Tp, void>>
+ explicit
+ basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
+ : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
+#endif // C++17
+
/**
* @brief Destroy the string instance.
*/
* @param __str Source string.
*/
basic_string&
- operator=(const basic_string& __str)
+ operator=(const basic_string& __str)
{ return this->assign(__str); }
/**
* The contents of @a str are moved into this string (without copying).
* @a str is a valid, but unspecified string.
**/
- // PR 58265, this should be noexcept.
basic_string&
operator=(basic_string&& __str)
+ _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)
{
// NB: DR 1204.
this->swap(__str);
}
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Set value to string constructed from a string_view.
+ * @param __svt An object convertible to string_view.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ operator=(const _Tp& __svt)
+ { return this->assign(__svt); }
+
+ /**
+ * @brief Convert to a string_view.
+ * @return A string_view.
+ */
+ operator __sv_type() const noexcept
+ { return __sv_type(data(), size()); }
+#endif // C++17
+
// Iterators:
/**
* Returns a read/write iterator that points to the first character in
/**
* Erases the string, making it empty.
*/
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+ void
+ clear() _GLIBCXX_NOEXCEPT
+ {
+ if (_M_rep()->_M_is_shared())
+ {
+ _M_rep()->_M_dispose(this->get_allocator());
+ _M_data(_S_empty_rep()._M_refdata());
+ }
+ else
+ _M_rep()->_M_set_length_and_sharable(0);
+ }
+#else
// PR 56166: this should not throw.
void
clear()
{ _M_mutate(0, this->size(), 0); }
+#endif
/**
* Returns true if the %string is empty. Equivalent to
* <code>*this == ""</code>.
*/
- bool
+ _GLIBCXX_NODISCARD bool
empty() const _GLIBCXX_NOEXCEPT
{ return this->size() == 0; }
{ return this->append(__l.begin(), __l.size()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Append a string_view.
+ * @param __svt The object convertible to string_view to be appended.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ operator+=(const _Tp& __svt)
+ { return this->append(__svt); }
+#endif // C++17
+
/**
* @brief Append a string to this string.
* @param __str The string to append.
* remainder of @a __str is appended.
*/
basic_string&
- append(const basic_string& __str, size_type __pos, size_type __n);
+ append(const basic_string& __str, size_type __pos, size_type __n = npos);
/**
* @brief Append a C substring.
append(_InputIterator __first, _InputIterator __last)
{ return this->replace(_M_iend(), _M_iend(), __first, __last); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Append a string_view.
+ * @param __svt The object convertible to string_view to be appended.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ append(const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->append(__sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Append a range of characters from a string_view.
+ * @param __svt The object convertible to string_view to be appended
+ * from.
+ * @param __pos The position in the string_view to append from.
+ * @param __n The number of characters to append from the string_view.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ append(const _Tp& __svt, size_type __pos, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return append(__sv.data()
+ + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+ std::__sv_limit(__sv.size(), __pos, __n));
+ }
+#endif // C++17
+
/**
* @brief Append a single character.
* @param __c Character to append.
* This function sets this string to the exact contents of @a __str.
* @a __str is a valid, but unspecified string.
*/
- // PR 58265, this should be noexcept.
basic_string&
assign(basic_string&& __str)
+ noexcept(allocator_traits<_Alloc>::is_always_equal::value)
{
this->swap(__str);
return *this;
* __str, the remainder of @a __str is used.
*/
basic_string&
- assign(const basic_string& __str, size_type __pos, size_type __n)
+ assign(const basic_string& __str, size_type __pos, size_type __n = npos)
{ return this->assign(__str._M_data()
+ __str._M_check(__pos, "basic_string::assign"),
__str._M_limit(__pos, __n)); }
{ return this->assign(__l.begin(), __l.size()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Set value from a string_view.
+ * @param __svt The source object convertible to string_view.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ assign(const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->assign(__sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Set value from a range of characters in a string_view.
+ * @param __svt The source object convertible to string_view.
+ * @param __pos The position in the string_view to assign from.
+ * @param __n The number of characters to assign.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return assign(__sv.data()
+ + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
+ std::__sv_limit(__sv.size(), __pos, __n));
+ }
+#endif // C++17
+
/**
* @brief Insert multiple characters.
* @param __p Iterator referencing location in string to insert at.
/**
* @brief Insert value of a string.
- * @param __pos1 Iterator referencing location in string to insert at.
+ * @param __pos1 Position in string to insert at.
* @param __str The string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
/**
* @brief Insert a substring.
- * @param __pos1 Iterator referencing location in string to insert at.
+ * @param __pos1 Position in string to insert at.
* @param __str The string to insert.
* @param __pos2 Start of characters in str to insert.
* @param __n Number of characters to insert.
*/
basic_string&
insert(size_type __pos1, const basic_string& __str,
- size_type __pos2, size_type __n)
+ size_type __pos2, size_type __n = npos)
{ return this->insert(__pos1, __str._M_data()
+ __str._M_check(__pos2, "basic_string::insert"),
__str._M_limit(__pos2, __n)); }
/**
* @brief Insert a C substring.
- * @param __pos Iterator referencing location in string to insert at.
+ * @param __pos Position in string to insert at.
* @param __s The C string to insert.
* @param __n The number of characters to insert.
* @return Reference to this string.
/**
* @brief Insert a C string.
- * @param __pos Iterator referencing location in string to insert at.
+ * @param __pos Position in string to insert at.
* @param __s The C string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
return iterator(_M_data() + __pos);
}
+#if __cplusplus >= 201703L
+ /**
+ * @brief Insert a string_view.
+ * @param __pos Position in string to insert at.
+ * @param __svt The object convertible to string_view to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ insert(size_type __pos, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->insert(__pos, __sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Insert a string_view.
+ * @param __pos Position in string to insert at.
+ * @param __svt The object convertible to string_view to insert from.
+ * @param __pos Position in string_view to insert
+ * from.
+ * @param __n The number of characters to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ insert(size_type __pos1, const _Tp& __svt,
+ size_type __pos2, size_type __n = npos)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos1, size_type(0), __sv.data()
+ + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
+ std::__sv_limit(__sv.size(), __pos2, __n));
+ }
+#endif // C++17
+
/**
* @brief Remove characters.
* @param __pos Index of first character to remove (default 0).
*/
basic_string&
replace(size_type __pos1, size_type __n1, const basic_string& __str,
- size_type __pos2, size_type __n2)
+ size_type __pos2, size_type __n2 = npos)
{ return this->replace(__pos1, __n1, __str._M_data()
+ __str._M_check(__pos2, "basic_string::replace"),
__str._M_limit(__pos2, __n2)); }
return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
__k1.base(), __k2 - __k1);
}
-
+
#if __cplusplus >= 201103L
/**
* @brief Replace range of characters with initializer_list.
{ return this->replace(__i1, __i2, __l.begin(), __l.end()); }
#endif // C++11
+#if __cplusplus >= 201703L
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __pos The position to replace at.
+ * @param __n The number of characters to replace.
+ * @param __svt The object convertible to string_view to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(size_type __pos, size_type __n, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos, __n, __sv.data(), __sv.size());
+ }
+
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __pos1 The position to replace at.
+ * @param __n1 The number of characters to replace.
+ * @param __svt The object convertible to string_view to insert from.
+ * @param __pos2 The position in the string_view to insert from.
+ * @param __n2 The number of characters to insert.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(size_type __pos1, size_type __n1, const _Tp& __svt,
+ size_type __pos2, size_type __n2 = npos)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__pos1, __n1,
+ __sv.data()
+ + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+ std::__sv_limit(__sv.size(), __pos2, __n2));
+ }
+
+ /**
+ * @brief Replace range of characters with string_view.
+ * @param __i1 An iterator referencing the start position
+ to replace at.
+ * @param __i2 An iterator referencing the end position
+ for the replace.
+ * @param __svt The object convertible to string_view to insert from.
+ * @return Reference to this string.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, basic_string&>
+ replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
+ {
+ __sv_type __sv = __svt;
+ return this->replace(__i1 - begin(), __i2 - __i1, __sv);
+ }
+#endif // C++17
+
private:
template<class _Integer>
basic_string&
* Exchanges the contents of this string with that of @a __s in constant
* time.
*/
- // PR 58265, this should be noexcept.
void
- swap(basic_string& __s);
+ swap(basic_string& __s)
+ _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value);
// String operations:
/**
/**
* @brief Return const pointer to contents.
*
- * This is a handle to internal data. Do not modify or dire things may
- * happen.
+ * This is a pointer to internal data. It is undefined to modify
+ * the contents through the returned pointer. To get a pointer that
+ * allows modifying the contents use @c &str[0] instead,
+ * (or in C++17 the non-const @c str.data() overload).
*/
const _CharT*
data() const _GLIBCXX_NOEXCEPT
{ return _M_data(); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Return non-const pointer to contents.
+ *
+ * This is a pointer to the character sequence held by the string.
+ * Modifying the characters in the sequence is allowed.
+ */
+ _CharT*
+ data() noexcept
+ {
+ _M_leak();
+ return _M_data();
+ }
+#endif
+
/**
* @brief Return copy of allocator used to construct this string.
*/
* npos.
*/
size_type
- find(const _CharT* __s, size_type __pos, size_type __n) const;
+ find(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a string.
*/
size_type
find(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find(__str.data(), __pos, __str.size()); }
/**
* it begins. If not found, returns npos.
*/
size_type
- find(const _CharT* __s, size_type __pos = 0) const
+ find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find(__s, __pos, traits_type::length(__s));
size_type
find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT;
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a string_view.
+ * @param __svt The object convertible to string_view to locate.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of start of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find last position of a string.
* @param __str String to locate.
*/
size_type
rfind(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->rfind(__str.data(), __pos, __str.size()); }
/**
* npos.
*/
size_type
- rfind(const _CharT* __s, size_type __pos, size_type __n) const;
+ rfind(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a C string.
* where it begins. If not found, returns npos.
*/
size_type
- rfind(const _CharT* __s, size_type __pos = npos) const
+ rfind(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->rfind(__s, __pos, traits_type::length(__s));
size_type
rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT;
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a string_view.
+ * @param __svt The object convertible to string_view to locate.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of start of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ rfind(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->rfind(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find position of a character of string.
* @param __str String containing characters to locate.
*/
size_type
find_first_of(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_first_of(__str.data(), __pos, __str.size()); }
/**
* returns npos.
*/
size_type
- find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
+ find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a character of C string.
*/
size_type
find_first_of(const _CharT* __s, size_type __pos = 0) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_first_of(__s, __pos, traits_type::length(__s));
find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT
{ return this->find(__c, __pos); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a character of a string_view.
+ * @param __svt An object convertible to string_view containing
+ * characters to locate.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_first_of(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_first_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find last position of a character of string.
* @param __str String containing characters to locate.
*/
size_type
find_last_of(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_last_of(__str.data(), __pos, __str.size()); }
/**
* returns npos.
*/
size_type
- find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
+ find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
+ _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a character of C string.
*/
size_type
find_last_of(const _CharT* __s, size_type __pos = npos) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_last_of(__s, __pos, traits_type::length(__s));
find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT
{ return this->rfind(__c, __pos); }
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a character of string.
+ * @param __svt An object convertible to string_view containing
+ * characters to locate.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_last_of(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_last_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
+
/**
* @brief Find position of a character not in string.
* @param __str String containing characters to avoid.
*/
size_type
find_first_not_of(const basic_string& __str, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_first_not_of(__str.data(), __pos, __str.size()); }
/**
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos,
- size_type __n) const;
+ size_type __n) const _GLIBCXX_NOEXCEPT;
/**
* @brief Find position of a character not in C string.
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos = 0) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_first_not_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_first_not_of(_CharT __c, size_type __pos = 0) const
- _GLIBCXX_NOEXCEPT;
+ _GLIBCXX_NOEXCEPT;
+
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find position of a character not in a string_view.
+ * @param __svt An object convertible to string_view containing
+ * characters to avoid.
+ * @param __pos Index of character to search from (default 0).
+ * @return Index of first occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_first_not_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
/**
* @brief Find last position of a character not in string.
*/
size_type
find_last_not_of(const basic_string& __str, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT
+ _GLIBCXX_NOEXCEPT
{ return this->find_last_not_of(__str.data(), __pos, __str.size()); }
/**
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos,
- size_type __n) const;
+ size_type __n) const _GLIBCXX_NOEXCEPT;
/**
* @brief Find last position of a character not in C string.
* @param __s C string containing characters to avoid.
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos = npos) const
+ _GLIBCXX_NOEXCEPT
{
__glibcxx_requires_string(__s);
return this->find_last_not_of(__s, __pos, traits_type::length(__s));
*/
size_type
find_last_not_of(_CharT __c, size_type __pos = npos) const
- _GLIBCXX_NOEXCEPT;
+ _GLIBCXX_NOEXCEPT;
+
+#if __cplusplus >= 201703L
+ /**
+ * @brief Find last position of a character not in a string_view.
+ * @param __svt An object convertible to string_view containing
+ * characters to avoid.
+ * @param __pos Index of character to search back from (default end).
+ * @return Index of last occurrence.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, size_type>
+ find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return this->find_last_not_of(__sv.data(), __pos, __sv.size());
+ }
+#endif // C++17
/**
* @brief Get a substring.
return __r;
}
+#if __cplusplus >= 201703L
+ /**
+ * @brief Compare to a string_view.
+ * @param __svt An object convertible to string_view to compare against.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(const _Tp& __svt) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ const size_type __size = this->size();
+ const size_type __osize = __sv.size();
+ const size_type __len = std::min(__size, __osize);
+
+ int __r = traits_type::compare(_M_data(), __sv.data(), __len);
+ if (!__r)
+ __r = _S_compare(__size, __osize);
+ return __r;
+ }
+
+ /**
+ * @brief Compare to a string_view.
+ * @param __pos A position in the string to start comparing from.
+ * @param __n The number of characters to compare.
+ * @param __svt An object convertible to string_view to compare
+ * against.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(size_type __pos, size_type __n, const _Tp& __svt) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return __sv_type(*this).substr(__pos, __n).compare(__sv);
+ }
+
+ /**
+ * @brief Compare to a string_view.
+ * @param __pos1 A position in the string to start comparing from.
+ * @param __n1 The number of characters to compare.
+ * @param __svt An object convertible to string_view to compare
+ * against.
+ * @param __pos2 A position in the string_view to start comparing from.
+ * @param __n2 The number of characters to compare.
+ * @return Integer < 0, 0, or > 0.
+ */
+ template<typename _Tp>
+ _If_sv<_Tp, int>
+ compare(size_type __pos1, size_type __n1, const _Tp& __svt,
+ size_type __pos2, size_type __n2 = npos) const
+ noexcept(is_same<_Tp, __sv_type>::value)
+ {
+ __sv_type __sv = __svt;
+ return __sv_type(*this)
+ .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
+ }
+#endif // C++17
+
/**
* @brief Compare substring to a string.
* @param __pos Index of first character of substring.
*/
int
compare(size_type __pos1, size_type __n1, const basic_string& __str,
- size_type __pos2, size_type __n2) const;
+ size_type __pos2, size_type __n2 = npos) const;
/**
* @brief Compare to a C string.
* ordered first.
*/
int
- compare(const _CharT* __s) const;
+ compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 5 String::compare specification questionable
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const;
+#if __cplusplus > 201703L
+ bool
+ starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ starts_with(_CharT __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ starts_with(const _CharT* __x) const noexcept
+ { return __sv_type(this->data(), this->size()).starts_with(__x); }
+
+ bool
+ ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+
+ bool
+ ends_with(_CharT __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+
+ bool
+ ends_with(const _CharT* __x) const noexcept
+ { return __sv_type(this->data(), this->size()).ends_with(__x); }
+#endif // C++20
+
# ifdef _GLIBCXX_TM_TS_INTERNAL
friend void
::_txnal_cow_string_C1_for_exceptions(void* that, const char* s,
};
#endif // !_GLIBCXX_USE_CXX11_ABI
+#if __cpp_deduction_guides >= 201606
+_GLIBCXX_BEGIN_NAMESPACE_CXX11
+ template<typename _InputIterator, typename _CharT
+ = typename iterator_traits<_InputIterator>::value_type,
+ typename _Allocator = allocator<_CharT>,
+ typename = _RequireInputIter<_InputIterator>,
+ typename = _RequireAllocator<_Allocator>>
+ basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
+ -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3075. basic_string needs deduction guides from basic_string_view
+ template<typename _CharT, typename _Traits,
+ typename _Allocator = allocator<_CharT>,
+ typename = _RequireAllocator<_Allocator>>
+ basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
+ -> basic_string<_CharT, _Traits, _Allocator>;
+
+ template<typename _CharT, typename _Traits,
+ typename _Allocator = allocator<_CharT>,
+ typename = _RequireAllocator<_Allocator>>
+ basic_string(basic_string_view<_CharT, _Traits>,
+ typename basic_string<_CharT, _Traits, _Allocator>::size_type,
+ typename basic_string<_CharT, _Traits, _Allocator>::size_type,
+ const _Allocator& = _Allocator())
+ -> basic_string<_CharT, _Traits, _Allocator>;
+_GLIBCXX_END_NAMESPACE_CXX11
+#endif
+
// operator+
/**
* @brief Concatenate two strings.
operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
basic_string<_CharT, _Traits, _Alloc>&& __rhs)
{
- const auto __size = __lhs.size() + __rhs.size();
- const bool __cond = (__size > __lhs.capacity()
- && __size <= __rhs.capacity());
- return __cond ? std::move(__rhs.insert(0, __lhs))
- : std::move(__lhs.append(__rhs));
+#if _GLIBCXX_USE_CXX11_ABI
+ using _Alloc_traits = allocator_traits<_Alloc>;
+ bool __use_rhs = false;
+ if _GLIBCXX17_CONSTEXPR (typename _Alloc_traits::is_always_equal{})
+ __use_rhs = true;
+ else if (__lhs.get_allocator() == __rhs.get_allocator())
+ __use_rhs = true;
+ if (__use_rhs)
+#endif
+ {
+ const auto __size = __lhs.size() + __rhs.size();
+ if (__size > __lhs.capacity() && __size <= __rhs.capacity())
+ return std::move(__rhs.insert(0, __lhs));
+ }
+ return std::move(__lhs.append(__rhs));
}
template<typename _CharT, typename _Traits, typename _Alloc>
#if __cplusplus >= 201103L
#include <ext/string_conversions.h>
+#include <bits/charconv.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
{ return __gnu_cxx::__stoa(&std::strtold, "stold", __str.c_str(), __idx); }
#endif // _GLIBCXX_USE_C99_STDLIB
-#if _GLIBCXX_USE_C99_STDIO
- // NB: (v)snprintf vs sprintf.
+ // DR 1261. Insufficent overloads for to_string / to_wstring
- // DR 1261.
inline string
to_string(int __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, 4 * sizeof(int),
- "%d", __val); }
+ {
+ const bool __neg = __val < 0;
+ const unsigned __uval = __neg ? (unsigned)~__val + 1u : __val;
+ const auto __len = __detail::__to_chars_len(__uval);
+ string __str(__neg + __len, '-');
+ __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
+ return __str;
+ }
inline string
to_string(unsigned __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf,
- 4 * sizeof(unsigned),
- "%u", __val); }
+ {
+ string __str(__detail::__to_chars_len(__val), '\0');
+ __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
+ return __str;
+ }
inline string
to_string(long __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, 4 * sizeof(long),
- "%ld", __val); }
+ {
+ const bool __neg = __val < 0;
+ const unsigned long __uval = __neg ? (unsigned long)~__val + 1ul : __val;
+ const auto __len = __detail::__to_chars_len(__uval);
+ string __str(__neg + __len, '-');
+ __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
+ return __str;
+ }
inline string
to_string(unsigned long __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf,
- 4 * sizeof(unsigned long),
- "%lu", __val); }
+ {
+ string __str(__detail::__to_chars_len(__val), '\0');
+ __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
+ return __str;
+ }
inline string
to_string(long long __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf,
- 4 * sizeof(long long),
- "%lld", __val); }
+ {
+ const bool __neg = __val < 0;
+ const unsigned long long __uval
+ = __neg ? (unsigned long long)~__val + 1ull : __val;
+ const auto __len = __detail::__to_chars_len(__uval);
+ string __str(__neg + __len, '-');
+ __detail::__to_chars_10_impl(&__str[__neg], __len, __uval);
+ return __str;
+ }
inline string
to_string(unsigned long long __val)
- { return __gnu_cxx::__to_xstring<string>(&std::vsnprintf,
- 4 * sizeof(unsigned long long),
- "%llu", __val); }
+ {
+ string __str(__detail::__to_chars_len(__val), '\0');
+ __detail::__to_chars_10_impl(&__str[0], __str.size(), __val);
+ return __str;
+ }
+
+#if _GLIBCXX_USE_C99_STDIO
+ // NB: (v)snprintf vs sprintf.
inline string
to_string(float __val)
#endif
#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+#ifdef _GLIBCXX_USE_CHAR8_T
+ /// std::hash specialization for u8string.
+ template<>
+ struct hash<u8string>
+ : public __hash_base<size_t, u8string>
+ {
+ size_t
+ operator()(const u8string& __s) const noexcept
+ { return std::_Hash_impl::hash(__s.data(),
+ __s.length() * sizeof(char8_t)); }
+ };
+
+ template<>
+ struct __is_fast_hash<hash<u8string>> : std::false_type
+ { };
+#endif
+
/// std::hash specialization for u16string.
template<>
struct hash<u16string>
template<>
struct __is_fast_hash<hash<u32string>> : std::false_type
{ };
-#endif
-#if __cplusplus > 201103L
+#if __cplusplus >= 201402L
#define __cpp_lib_string_udls 201304
{
inline namespace string_literals
{
-
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
_GLIBCXX_DEFAULT_ABI_TAG
inline basic_string<char>
operator""s(const char* __str, size_t __len)
{ return basic_string<wchar_t>{__str, __len}; }
#endif
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+#ifdef _GLIBCXX_USE_CHAR8_T
+ _GLIBCXX_DEFAULT_ABI_TAG
+ inline basic_string<char8_t>
+ operator""s(const char8_t* __str, size_t __len)
+ { return basic_string<char8_t>{__str, __len}; }
+#endif
+
_GLIBCXX_DEFAULT_ABI_TAG
inline basic_string<char16_t>
operator""s(const char16_t* __str, size_t __len)
inline basic_string<char32_t>
operator""s(const char32_t* __str, size_t __len)
{ return basic_string<char32_t>{__str, __len}; }
-#endif
+#pragma GCC diagnostic pop
} // inline namespace string_literals
} // inline namespace literals
-#endif // __cplusplus > 201103L
+#if __cplusplus >= 201703L
+ namespace __detail::__variant
+ {
+ template<typename> struct _Never_valueless_alt; // see <variant>
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // basic_string into a variant, but only if moving the string cannot throw.
+ template<typename _Tp, typename _Traits, typename _Alloc>
+ struct _Never_valueless_alt<std::basic_string<_Tp, _Traits, _Alloc>>
+ : __and_<
+ is_nothrow_move_constructible<std::basic_string<_Tp, _Traits, _Alloc>>,
+ is_nothrow_move_assignable<std::basic_string<_Tp, _Traits, _Alloc>>
+ >::type
+ { };
+ } // namespace __detail::__variant
+#endif // C++17
+#endif // C++14
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std