Commit fb8b3e29 by Jonathan Wakely Committed by Jonathan Wakely

Fix basic_string_view typedefs and enforce preconditions

The basic_string_view::pointer and basic_string_view::reference typedefs
are supposed to refer to the non-const value type.

In previous standards having traits_type::char_type different to
value_type was simply undefined, but in the C++2a draft it's ill-formed,
as changed by P1148R0. For std::basic_string and iostreams we might
want to only enforce this conditionally for __cplusplus > 201703L but
for std::basic_string_view we don't have backwards compatibility
concerns. Also add assertions to verify the _CharT argument is a
"char-like" type (non-array, trivial, standard layout type).

Also remove the non-standard basic_string_view::_M_check and
basic_string_view::_M_limit member functions, replacing them with
non-member functions that will still exist even if basic_string_view is
specialized by the program.

	* include/experimental/string_view (basic_string_view::pointer)
	(basic_string_view::reference): Fix to refer to non-const value_type.
	* include/bits/basic_string.h (basic_string): Use __sv_check and
	__sv_limit instead of basic_string_view::_M_check and
	basic_string_view::_M_limit.
	* include/std/string_view (__sv_check, __sv_limit): New
	helper functions to replace basic_string_view::_M_check and
	basic_string_view::_M_limit.
	(basic_string_view): Add static assertions to enforce ill-formed
	requirement for traits_type::char_type from P1148R0, and to enforce
	required properties of char-like types.
	(basic_string_view::pointer, basic_string_view::reference): Fix to
	refer to non-const value_type.
	(basic_string_view::operator[], basic_string_view::at)
	(basic_string_view::front, basic_string_view::back)
	(basic_string_view::data): Use const_reference and const_pointer
	typedefs for return types.
	(basic_string_view::_M_check, basic_string_view::_M_limit): Remove.
	(hash<wstring_view>): Fix argument_type typedef.
	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
	char/1.cc: Fix expected return type of basic_string_view::data().
	* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
	wchar_t/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
	char/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
	wchar_t/1.cc: Likewise.
	* testsuite/21_strings/basic_string_view/requirements/traits_neg.cc:
	New test.
	* testsuite/21_strings/basic_string_view/requirements/typedefs.cc:
	Check reference and pointer typedefs.
	* testsuite/experimental/string_view/requirements/typedefs.cc:
	Likewise.
	* testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc:
	Fix expected return type of basic_string_view::data().
	* testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/
	1.cc: Likewise.
	* testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc:
	Likewise.
	* testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/
	1.cc: Likewise.

From-SVN: r270548
parent 92750002
2019-04-24 Jonathan Wakely <jwakely@redhat.com> 2019-04-24 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/string_view (basic_string_view::pointer)
(basic_string_view::reference): Fix to refer to non-const value_type.
* include/bits/basic_string.h (basic_string): Use __sv_check and
__sv_limit instead of basic_string_view::_M_check and
basic_string_view::_M_limit.
* include/std/string_view (__sv_check, __sv_limit): New
helper functions to replace basic_string_view::_M_check and
basic_string_view::_M_limit.
(basic_string_view): Add static assertions to enforce ill-formed
requirement for traits_type::char_type from P1148R0, and to enforce
required properties of char-like types.
(basic_string_view::pointer, basic_string_view::reference): Fix to
refer to non-const value_type.
(basic_string_view::operator[], basic_string_view::at)
(basic_string_view::front, basic_string_view::back)
(basic_string_view::data): Use const_reference and const_pointer
typedefs for return types.
(basic_string_view::_M_check, basic_string_view::_M_limit): Remove.
(hash<wstring_view>): Fix argument_type typedef.
* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
char/1.cc: Fix expected return type of basic_string_view::data().
* testsuite/21_strings/basic_string_view/modifiers/remove_prefix/
wchar_t/1.cc: Likewise.
* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
char/1.cc: Likewise.
* testsuite/21_strings/basic_string_view/modifiers/remove_suffix/
wchar_t/1.cc: Likewise.
* testsuite/21_strings/basic_string_view/requirements/traits_neg.cc:
New test.
* testsuite/21_strings/basic_string_view/requirements/typedefs.cc:
Check reference and pointer typedefs.
* testsuite/experimental/string_view/requirements/typedefs.cc:
Likewise.
* testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc:
Fix expected return type of basic_string_view::data().
* testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/
1.cc: Likewise.
* testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc:
Likewise.
* testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/
1.cc: Likewise.
PR libstdc++/90220 PR libstdc++/90220
* include/std/any (__any_caster): Use remove_cv_t instead of decay_t. * include/std/any (__any_caster): Use remove_cv_t instead of decay_t.
Avoid a runtime check for types that can never be stored in std::any. Avoid a runtime check for types that can never be stored in std::any.
......
...@@ -1336,8 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1336,8 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return _M_append(__sv.data() return _M_append(__sv.data()
+ __sv._M_check(__pos, "basic_string::append"), + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
__sv._M_limit(__pos, __n)); std::__sv_limit(__sv.size(), __pos, __n));
} }
#endif // C++17 #endif // C++17
...@@ -1507,9 +1507,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1507,9 +1507,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
assign(const _Tp& __svt, size_type __pos, size_type __n = npos) assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return _M_replace(size_type(0), this->size(), __sv.data() return _M_replace(size_type(0), this->size(),
+ __sv._M_check(__pos, "basic_string::assign"), __sv.data()
__sv._M_limit(__pos, __n)); + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
std::__sv_limit(__sv.size(), __pos, __n));
} }
#endif // C++17 #endif // C++17
...@@ -1780,9 +1781,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1780,9 +1781,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_type __pos2, size_type __n = npos) size_type __pos2, size_type __n = npos)
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return this->replace(__pos1, size_type(0), __sv.data() return this->replace(__pos1, size_type(0),
+ __sv._M_check(__pos2, "basic_string::insert"), __sv.data()
__sv._M_limit(__pos2, __n)); + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
std::__sv_limit(__sv.size(), __pos2, __n));
} }
#endif // C++17 #endif // C++17
...@@ -2212,9 +2214,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -2212,9 +2214,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_type __pos2, size_type __n2 = npos) size_type __pos2, size_type __n2 = npos)
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return this->replace(__pos1, __n1, __sv.data() return this->replace(__pos1, __n1,
+ __sv._M_check(__pos2, "basic_string::replace"), __sv.data()
__sv._M_limit(__pos2, __n2)); + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
std::__sv_limit(__sv.size(), __pos2, __n2));
} }
/** /**
...@@ -4303,8 +4306,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 ...@@ -4303,8 +4306,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return append(__sv.data() return append(__sv.data()
+ __sv._M_check(__pos, "basic_string::append"), + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
__sv._M_limit(__pos, __n)); std::__sv_limit(__sv.size(), __pos, __n));
} }
#endif // C++17 #endif // C++17
...@@ -4460,8 +4463,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 ...@@ -4460,8 +4463,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return assign(__sv.data() return assign(__sv.data()
+ __sv._M_check(__pos, "basic_string::assign"), + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
__sv._M_limit(__pos, __n)); std::__sv_limit(__sv.size(), __pos, __n));
} }
#endif // C++17 #endif // C++17
...@@ -4671,8 +4674,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 ...@@ -4671,8 +4674,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return this->replace(__pos1, size_type(0), __sv.data() return this->replace(__pos1, size_type(0), __sv.data()
+ __sv._M_check(__pos2, "basic_string::insert"), + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
__sv._M_limit(__pos2, __n)); std::__sv_limit(__sv.size(), __pos2, __n));
} }
#endif // C++17 #endif // C++17
...@@ -5062,8 +5065,9 @@ _GLIBCXX_END_NAMESPACE_CXX11 ...@@ -5062,8 +5065,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
{ {
__sv_type __sv = __svt; __sv_type __sv = __svt;
return this->replace(__pos1, __n1, return this->replace(__pos1, __n1,
__sv.data() + __sv._M_check(__pos2, "basic_string::replace"), __sv.data()
__sv._M_limit(__pos2, __n2)); + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
std::__sv_limit(__sv.size(), __pos2, __n2));
} }
/** /**
......
...@@ -78,9 +78,9 @@ inline namespace fundamentals_v1 ...@@ -78,9 +78,9 @@ inline namespace fundamentals_v1
// types // types
using traits_type = _Traits; using traits_type = _Traits;
using value_type = _CharT; using value_type = _CharT;
using pointer = const _CharT*; using pointer = _CharT*;
using const_pointer = const _CharT*; using const_pointer = const _CharT*;
using reference = const _CharT&; using reference = _CharT&;
using const_reference = const _CharT&; using const_reference = const _CharT&;
using const_iterator = const _CharT*; using const_iterator = const _CharT*;
using iterator = const_iterator; using iterator = const_iterator;
......
...@@ -49,6 +49,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -49,6 +49,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#define __cpp_lib_string_view 201603 #define __cpp_lib_string_view 201603
// Helper for basic_string and basic_string_view members.
constexpr size_t
__sv_check(size_t __size, size_t __pos, const char* __s)
{
if (__pos > __size)
__throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size "
"(which is %zu)"), __s, __pos, __size);
return __pos;
}
// Helper for basic_string members.
// NB: __sv_limit doesn't check for a bad __pos value.
constexpr size_t
__sv_limit(size_t __size, size_t __pos, size_t __off) noexcept
{
const bool __testoff = __off < __size - __pos;
return __testoff ? __off : __size - __pos;
}
/** /**
* @class basic_string_view <string_view> * @class basic_string_view <string_view>
* @brief A non-owning reference to a string. * @brief A non-owning reference to a string.
...@@ -70,24 +89,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -70,24 +89,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits = std::char_traits<_CharT>> template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
class basic_string_view class basic_string_view
{ {
static_assert(!is_array_v<_CharT>);
static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);
static_assert(is_same_v<_CharT, typename _Traits::char_type>);
public: public:
// types // types
using traits_type = _Traits; using traits_type = _Traits;
using value_type = _CharT; using value_type = _CharT;
using pointer = const _CharT*; using pointer = value_type*;
using const_pointer = const _CharT*; using const_pointer = const value_type*;
using reference = const _CharT&; using reference = value_type&;
using const_reference = const _CharT&; using const_reference = const value_type&;
using const_iterator = const _CharT*; using const_iterator = const value_type*;
using iterator = const_iterator; using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator; using reverse_iterator = const_reverse_iterator;
using size_type = size_t; using size_type = size_t;
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
static constexpr size_type npos = size_type(-1); static constexpr size_type npos = size_type(-1);
// [string.view.cons], construct/copy // [string.view.cons], construction and assignment
constexpr constexpr
basic_string_view() noexcept basic_string_view() noexcept
...@@ -110,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -110,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr basic_string_view& constexpr basic_string_view&
operator=(const basic_string_view&) noexcept = default; operator=(const basic_string_view&) noexcept = default;
// [string.view.iterators], iterators // [string.view.iterators], iterator support
constexpr const_iterator constexpr const_iterator
begin() const noexcept begin() const noexcept
...@@ -167,7 +190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -167,7 +190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// [string.view.access], element access // [string.view.access], element access
constexpr const _CharT& constexpr const_reference
operator[](size_type __pos) const noexcept operator[](size_type __pos) const noexcept
{ {
// TODO: Assert to restore in a way compatible with the constexpr. // TODO: Assert to restore in a way compatible with the constexpr.
...@@ -175,7 +198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -175,7 +198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *(this->_M_str + __pos); return *(this->_M_str + __pos);
} }
constexpr const _CharT& constexpr const_reference
at(size_type __pos) const at(size_type __pos) const
{ {
if (__pos >= _M_len) if (__pos >= _M_len)
...@@ -185,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -185,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *(this->_M_str + __pos); return *(this->_M_str + __pos);
} }
constexpr const _CharT& constexpr const_reference
front() const noexcept front() const noexcept
{ {
// TODO: Assert to restore in a way compatible with the constexpr. // TODO: Assert to restore in a way compatible with the constexpr.
...@@ -193,7 +216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -193,7 +216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this->_M_str; return *this->_M_str;
} }
constexpr const _CharT& constexpr const_reference
back() const noexcept back() const noexcept
{ {
// TODO: Assert to restore in a way compatible with the constexpr. // TODO: Assert to restore in a way compatible with the constexpr.
...@@ -201,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -201,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *(this->_M_str + this->_M_len - 1); return *(this->_M_str + this->_M_len - 1);
} }
constexpr const _CharT* constexpr const_pointer
data() const noexcept data() const noexcept
{ return this->_M_str; } { return this->_M_str; }
...@@ -233,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -233,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
copy(_CharT* __str, size_type __n, size_type __pos = 0) const copy(_CharT* __str, size_type __n, size_type __pos = 0) const
{ {
__glibcxx_requires_string_len(__str, __n); __glibcxx_requires_string_len(__str, __n);
__pos = _M_check(__pos, "basic_string_view::copy"); __pos = std::__sv_check(size(), __pos, "basic_string_view::copy");
const size_type __rlen = std::min(__n, _M_len - __pos); const size_type __rlen = std::min(__n, _M_len - __pos);
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2777. basic_string_view::copy should use char_traits::copy // 2777. basic_string_view::copy should use char_traits::copy
...@@ -244,7 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -244,7 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr basic_string_view constexpr basic_string_view
substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) substr(size_type __pos = 0, size_type __n = npos) const noexcept(false)
{ {
__pos = _M_check(__pos, "basic_string_view::substr"); __pos = std::__sv_check(size(), __pos, "basic_string_view::substr");
const size_type __rlen = std::min(__n, _M_len - __pos); const size_type __rlen = std::min(__n, _M_len - __pos);
return basic_string_view{_M_str + __pos, __rlen}; return basic_string_view{_M_str + __pos, __rlen};
} }
...@@ -286,6 +309,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -286,6 +309,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
.compare(basic_string_view(__str, __n2)); .compare(basic_string_view(__str, __n2));
} }
#if __cplusplus > 201703L
constexpr bool
starts_with(basic_string_view __x) const noexcept
{ return this->substr(0, __x.size()) == __x; }
constexpr bool
starts_with(_CharT __x) const noexcept
{ return !this->empty() && traits_type::eq(this->front(), __x); }
constexpr bool
starts_with(const _CharT* __x) const noexcept
{ return this->starts_with(basic_string_view(__x)); }
constexpr bool
ends_with(basic_string_view __x) const noexcept
{
return this->size() >= __x.size()
&& this->compare(this->size() - __x.size(), npos, __x) == 0;
}
constexpr bool
ends_with(_CharT __x) const noexcept
{ return !this->empty() && traits_type::eq(this->back(), __x); }
constexpr bool
ends_with(const _CharT* __x) const noexcept
{ return this->ends_with(basic_string_view(__x)); }
#endif // C++20
// [string.view.find], searching
constexpr size_type constexpr size_type
find(basic_string_view __str, size_type __pos = 0) const noexcept find(basic_string_view __str, size_type __pos = 0) const noexcept
{ return this->find(__str._M_str, __pos, __str._M_len); } { return this->find(__str._M_str, __pos, __str._M_len); }
...@@ -386,53 +440,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -386,53 +440,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
traits_type::length(__str)); traits_type::length(__str));
} }
#if __cplusplus > 201703L
constexpr bool
starts_with(basic_string_view __x) const noexcept
{ return this->substr(0, __x.size()) == __x; }
constexpr bool
starts_with(_CharT __x) const noexcept
{ return !this->empty() && traits_type::eq(this->front(), __x); }
constexpr bool
starts_with(const _CharT* __x) const noexcept
{ return this->starts_with(basic_string_view(__x)); }
constexpr bool
ends_with(basic_string_view __x) const noexcept
{
return this->size() >= __x.size()
&& this->compare(this->size() - __x.size(), npos, __x) == 0;
}
constexpr bool
ends_with(_CharT __x) const noexcept
{ return !this->empty() && traits_type::eq(this->back(), __x); }
constexpr bool
ends_with(const _CharT* __x) const noexcept
{ return this->ends_with(basic_string_view(__x)); }
#endif // C++20
constexpr size_type
_M_check(size_type __pos, const char* __s) const noexcept(false)
{
if (__pos > this->size())
__throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
"this->size() (which is %zu)"),
__s, __pos, this->size());
return __pos;
}
// NB: _M_limit doesn't check for a bad __pos value.
constexpr size_type
_M_limit(size_type __pos, size_type __off) const noexcept
{
const bool __testoff = __off < this->size() - __pos;
return __testoff ? __off : this->size() - __pos;
}
private: private:
static constexpr int static constexpr int
...@@ -610,7 +617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -610,7 +617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_USE_WCHAR_T #ifdef _GLIBCXX_USE_WCHAR_T
template<> template<>
struct hash<wstring_view> struct hash<wstring_view>
: public __hash_base<size_t, wstring> : public __hash_base<size_t, wstring_view>
{ {
size_t size_t
operator()(const wstring_view& __s) const noexcept operator()(const wstring_view& __s) const noexcept
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using std::string_view; using std::string_view;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
VERIFY( str0.data() == p + 4); VERIFY( str0.data() == p + 4);
VERIFY( str0.length() == 8 ); VERIFY( str0.length() == 8 );
...@@ -39,7 +39,7 @@ test02() ...@@ -39,7 +39,7 @@ test02()
using std::string_view; using std::string_view;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
if ( str0.data() != p + 4) if ( str0.data() != p + 4)
return false; return false;
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using std::wstring_view; using std::wstring_view;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
VERIFY( str0.data() == p + 4); VERIFY( str0.data() == p + 4);
VERIFY( str0.length() == 8 ); VERIFY( str0.length() == 8 );
...@@ -39,7 +39,7 @@ test02() ...@@ -39,7 +39,7 @@ test02()
using std::wstring_view; using std::wstring_view;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
if ( str0.data() != p + 4) if ( str0.data() != p + 4)
return false; return false;
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using std::string_view; using std::string_view;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
VERIFY( str0.data() == p); VERIFY( str0.data() == p);
VERIFY( str0.length() == 10 ); VERIFY( str0.length() == 10 );
...@@ -39,7 +39,7 @@ test02() ...@@ -39,7 +39,7 @@ test02()
using std::string_view; using std::string_view;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
if ( str0.data() != p) if ( str0.data() != p)
return false; return false;
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using std::wstring_view; using std::wstring_view;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
VERIFY( str0.data() == p); VERIFY( str0.data() == p);
VERIFY( str0.length() == 10 ); VERIFY( str0.length() == 10 );
...@@ -39,7 +39,7 @@ test02() ...@@ -39,7 +39,7 @@ test02()
using std::wstring_view; using std::wstring_view;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
if ( str0.data() != p) if ( str0.data() != p)
return false; return false;
......
// Copyright (C) 2019 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++17" }
// { dg-do compile { target c++17 } }
#include <string_view>
// C++98 21.1 [lib.char.traits] p3
// C++03 21.1 [lib.char.traits] p3
// C++11 21.2 [char.traits] p3
// C++14 21.2 [char.traits] p3
// C++17 24.2 [char.traits] p3
// "Traits::char_type shall be the same as CharT."
// C++17 24.4.2 [string.view.template] p1
// "the type traits::char_type shall name the same type as charT"
// C++2a 21.2 [char.traits] p3 (post-P1148R0)
// "If X::char_type is not the same type as C, the program is ill-formed."
std::basic_string_view<char, std::char_traits<char16_t>> s1; // { dg-error "here" }
std::basic_string_view<char32_t, std::char_traits<char>> s2; // { dg-error "here" }
// { dg-prune-output "static assertion failed" }
...@@ -45,3 +45,12 @@ __gnu_test::basic_types<std::wstring_view> t2b; ...@@ -45,3 +45,12 @@ __gnu_test::basic_types<std::wstring_view> t2b;
__gnu_test::reversible_types<std::wstring_view> t2r; __gnu_test::reversible_types<std::wstring_view> t2r;
typedef typename std::wstring_view::traits_type traits_type2; typedef typename std::wstring_view::traits_type traits_type2;
#endif #endif
static_assert(std::is_same<std::string_view::pointer, char*>(),
"pointer should be value_type*");
static_assert(std::is_same<std::string_view::const_pointer, const char*>(),
"const_pointer should be const value_type*");
static_assert(std::is_same<std::string_view::reference, char&>(),
"reference should be value_type&");
static_assert(std::is_same<std::string_view::const_reference, const char&>(),
"const_reference should be const value_type&");
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using namespace std::experimental; using namespace std::experimental;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
VERIFY( str0.data() == p + 4); VERIFY( str0.data() == p + 4);
VERIFY( str0.length() == 8 ); VERIFY( str0.length() == 8 );
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using namespace std::experimental; using namespace std::experimental;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_prefix(4); str0.remove_prefix(4);
VERIFY( str0.data() == p + 4); VERIFY( str0.data() == p + 4);
VERIFY( str0.length() == 8 ); VERIFY( str0.length() == 8 );
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using namespace std::experimental; using namespace std::experimental;
string_view str0{"olympus mons"}; string_view str0{"olympus mons"};
string_view::pointer p = str0.data(); string_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
VERIFY( str0.data() == p); VERIFY( str0.data() == p);
VERIFY( str0.length() == 10 ); VERIFY( str0.length() == 10 );
......
...@@ -26,7 +26,7 @@ test01() ...@@ -26,7 +26,7 @@ test01()
using namespace std::experimental; using namespace std::experimental;
wstring_view str0{L"olympus mons"}; wstring_view str0{L"olympus mons"};
wstring_view::pointer p = str0.data(); wstring_view::const_pointer p = str0.data();
str0.remove_suffix(2); str0.remove_suffix(2);
VERIFY( str0.data() == p); VERIFY( str0.data() == p);
VERIFY( str0.length() == 10 ); VERIFY( str0.length() == 10 );
......
...@@ -43,3 +43,16 @@ __gnu_test::basic_types<std::experimental::wstring_view> t2b; ...@@ -43,3 +43,16 @@ __gnu_test::basic_types<std::experimental::wstring_view> t2b;
__gnu_test::reversible_types<std::experimental::wstring_view> t2r; __gnu_test::reversible_types<std::experimental::wstring_view> t2r;
typedef typename std::experimental::wstring_view::traits_type traits_type2; typedef typename std::experimental::wstring_view::traits_type traits_type2;
#endif #endif
static_assert(
std::is_same<std::experimental::string_view::pointer, char*>(),
"pointer should be value_type*");
static_assert(
std::is_same<std::experimental::string_view::const_pointer, const char*>(),
"const_pointer should be const value_type*");
static_assert(
std::is_same<std::experimental::string_view::reference, char&>(),
"reference should be value_type&");
static_assert(
std::is_same<std::experimental::string_view::const_reference, const char&>(),
"const_reference should be const value_type&");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment