Fix basic_string_view typedefs and enforce preconditions
authorJonathan Wakely <jwakely@redhat.com>
Wed, 24 Apr 2019 15:17:53 +0000 (16:17 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 24 Apr 2019 15:17:53 +0000 (16:17 +0100)
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

15 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/experimental/string_view
libstdc++-v3/include/std/string_view
libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/char/1.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_prefix/wchar_t/1.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/char/1.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/modifiers/remove_suffix/wchar_t/1.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/typedefs.cc
libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/char/1.cc
libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_prefix/wchar_t/1.cc
libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/char/1.cc
libstdc++-v3/testsuite/experimental/string_view/modifiers/remove_suffix/wchar_t/1.cc
libstdc++-v3/testsuite/experimental/string_view/requirements/typedefs.cc

index 2ab686ba3bb346ae8a7ea2c9659b027f59135aea..5e8a09a66364ba090106bc7f32c1b180ccd47db5 100644 (file)
@@ -1,5 +1,47 @@
 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
        * 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.
index 922536965e34214d480929a652e8f306492a7276..40ef8758a5103d552a6dfbd045fe6b39236c216a 100644 (file)
@@ -1336,8 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        {
          __sv_type __sv = __svt;
          return _M_append(__sv.data()
-                          + __sv._M_check(__pos, "basic_string::append"),
-                          __sv._M_limit(__pos, __n));
+             + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+             std::__sv_limit(__sv.size(), __pos, __n));
        }
 #endif // C++17
 
@@ -1507,9 +1507,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        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()
-                           + __sv._M_check(__pos, "basic_string::assign"),
-                           __sv._M_limit(__pos, __n));
+         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
 
@@ -1780,9 +1781,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
               size_type __pos2, size_type __n = npos)
        {
          __sv_type __sv = __svt;
-         return this->replace(__pos1, size_type(0), __sv.data()
-                              + __sv._M_check(__pos2, "basic_string::insert"),
-                              __sv._M_limit(__pos2, __n));
+         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
 
@@ -2212,9 +2214,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
                size_type __pos2, size_type __n2 = npos)
        {
          __sv_type __sv = __svt;
-         return this->replace(__pos1, __n1, __sv.data()
-                              + __sv._M_check(__pos2, "basic_string::replace"),
-                              __sv._M_limit(__pos2, __n2));
+         return this->replace(__pos1, __n1,
+             __sv.data()
+             + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+             std::__sv_limit(__sv.size(), __pos2, __n2));
        }
 
       /**
@@ -4303,8 +4306,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
        {
          __sv_type __sv = __svt;
          return append(__sv.data()
-                       + __sv._M_check(__pos, "basic_string::append"),
-                       __sv._M_limit(__pos, __n));
+             + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
+             std::__sv_limit(__sv.size(), __pos, __n));
        }
 #endif // C++17
 
@@ -4460,8 +4463,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
        {
          __sv_type __sv = __svt;
          return assign(__sv.data()
-                       + __sv._M_check(__pos, "basic_string::assign"),
-                       __sv._M_limit(__pos, __n));
+             + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
+             std::__sv_limit(__sv.size(), __pos, __n));
        }
 #endif // C++17
 
@@ -4671,8 +4674,8 @@ _GLIBCXX_END_NAMESPACE_CXX11
        {
          __sv_type __sv = __svt;
          return this->replace(__pos1, size_type(0), __sv.data()
-                              + __sv._M_check(__pos2, "basic_string::insert"),
-                              __sv._M_limit(__pos2, __n));
+             + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
+             std::__sv_limit(__sv.size(), __pos2, __n));
        }
 #endif // C++17
 
@@ -5062,8 +5065,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
        {
          __sv_type __sv = __svt;
          return this->replace(__pos1, __n1,
-             __sv.data() + __sv._M_check(__pos2, "basic_string::replace"),
-             __sv._M_limit(__pos2, __n2));
+             __sv.data()
+             + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
+             std::__sv_limit(__sv.size(), __pos2, __n2));
        }
 
       /**
index ce2c14cfe361fb6b95c0c4f688fda74b64b5f3e6..9e810dec8445c32c31df23df797594201343090e 100644 (file)
@@ -78,9 +78,9 @@ inline namespace fundamentals_v1
       // types
       using traits_type = _Traits;
       using value_type = _CharT;
-      using pointer = const _CharT*;
+      using pointer = _CharT*;
       using const_pointer = const _CharT*;
-      using reference = const _CharT&;
+      using reference = _CharT&;
       using const_reference = const _CharT&;
       using const_iterator = const _CharT*;
       using iterator = const_iterator;
index 844cfb148ad60a670b9cecdf2d39b4c49d958273..42822cc41abbd1c7fc54b3bd47bba46703aba796 100644 (file)
@@ -49,6 +49,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #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>
    *  @brief  A non-owning reference to a string.
@@ -70,24 +89,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
     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:
 
       // types
-      using traits_type = _Traits;
-      using value_type = _CharT;
-      using pointer = const _CharT*;
-      using const_pointer = const _CharT*;
-      using reference = const _CharT&;
-      using const_reference = const _CharT&;
-      using const_iterator = const _CharT*;
-      using iterator = const_iterator;
+      using traits_type                = _Traits;
+      using value_type         = _CharT;
+      using pointer            = value_type*;
+      using const_pointer      = const value_type*;
+      using reference          = value_type&;
+      using const_reference    = const value_type&;
+      using const_iterator     = const value_type*;
+      using iterator           = const_iterator;
       using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-      using reverse_iterator = const_reverse_iterator;
-      using size_type = size_t;
-      using difference_type = ptrdiff_t;
+      using reverse_iterator   = const_reverse_iterator;
+      using size_type          = size_t;
+      using difference_type    = ptrdiff_t;
       static constexpr size_type npos = size_type(-1);
 
-      // [string.view.cons], construct/copy
+      // [string.view.cons], construction and assignment
 
       constexpr
       basic_string_view() noexcept
@@ -110,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr basic_string_view&
       operator=(const basic_string_view&) noexcept = default;
 
-      // [string.view.iterators], iterators
+      // [string.view.iterators], iterator support
 
       constexpr const_iterator
       begin() const noexcept
@@ -167,7 +190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // [string.view.access], element access
 
-      constexpr const _CharT&
+      constexpr const_reference
       operator[](size_type __pos) const noexcept
       {
        // TODO: Assert to restore in a way compatible with the constexpr.
@@ -175,7 +198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *(this->_M_str + __pos);
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       at(size_type __pos) const
       {
        if (__pos >= _M_len)
@@ -185,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *(this->_M_str + __pos);
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       front() const noexcept
       {
        // TODO: Assert to restore in a way compatible with the constexpr.
@@ -193,7 +216,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *this->_M_str;
       }
 
-      constexpr const _CharT&
+      constexpr const_reference
       back() const noexcept
       {
        // TODO: Assert to restore in a way compatible with the constexpr.
@@ -201,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *(this->_M_str + this->_M_len - 1);
       }
 
-      constexpr const _CharT*
+      constexpr const_pointer
       data() const noexcept
       { return this->_M_str; }
 
@@ -233,7 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
       {
        __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);
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // 2777. basic_string_view::copy should use char_traits::copy
@@ -244,7 +267,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr basic_string_view
       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);
        return basic_string_view{_M_str + __pos, __rlen};
       }
@@ -286,6 +309,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                   .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
       find(basic_string_view __str, size_type __pos = 0) const noexcept
       { return this->find(__str._M_str, __pos, __str._M_len); }
@@ -386,53 +440,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                      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:
 
       static constexpr int
@@ -610,7 +617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #ifdef _GLIBCXX_USE_WCHAR_T
   template<>
     struct hash<wstring_view>
-    : public __hash_base<size_t, wstring>
+    : public __hash_base<size_t, wstring_view>
     {
       size_t
       operator()(const wstring_view& __s) const noexcept
index eedc6b99f7082e2cfb38cd6c5c8c805d51f33318..944260652bf11f5415cd6b139d9e930a469a98e2 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
@@ -39,7 +39,7 @@ test02()
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   if ( str0.data() != p + 4)
     return false;
index e0177511f4f741f5a1975621e857eae66c601590..c8ad5528b31d5fe79ab76f89eb69311cc22cd462 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
@@ -39,7 +39,7 @@ test02()
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   if ( str0.data() != p + 4)
     return false;
index 67a8a589c5fc1b9cefc3bf8981b154d224d0128c..d4d5d7dd06d75cacaed612118dc1b13c86c46f19 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
@@ -39,7 +39,7 @@ test02()
   using std::string_view;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   if ( str0.data() != p)
     return false;
index 81ccb91b5043af1457d9a0ad7897f4da78c468d0..deccc25284062539b6c815cf465775639d9d680a 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
@@ -39,7 +39,7 @@ test02()
   using std::wstring_view;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   if ( str0.data() != p)
     return false;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/traits_neg.cc
new file mode 100644 (file)
index 0000000..93ea808
--- /dev/null
@@ -0,0 +1,37 @@
+// 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" }
index 41b8f566a9056250899bd0fd5a70b9fc2c638502..b11ef57280096ef1a145da23b9d300d111b6171f 100644 (file)
@@ -45,3 +45,12 @@ __gnu_test::basic_types<std::wstring_view> t2b;
 __gnu_test::reversible_types<std::wstring_view> t2r;
 typedef typename std::wstring_view::traits_type traits_type2;
 #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&");
index 12a407889a48a9db36412b68f41c65eb1ac21ac4..8a7b6b8767902f3f11988d3b919b6d9674c7aa3e 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using namespace std::experimental;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
index e92d6d9c70a09c25a90bdfb44f656943e6c2137b..153349f2a9f3b47fb159c464accc58d085ecb197 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using namespace std::experimental;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_prefix(4);
   VERIFY( str0.data() == p + 4);
   VERIFY( str0.length() == 8 );
index ab990cb296dcdea8a6a45881071e1c9ca815af8b..612a62c045b507a357a556f8fa6d8a128160b57a 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using namespace std::experimental;
 
   string_view str0{"olympus mons"};
-  string_view::pointer p = str0.data();
+  string_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
index 7c7c63ee8510f3da1280c7cc8793ad7b6cc7de89..b1114d1799bc0f3d9a0a2f91eb8e47fe1bda5ee3 100644 (file)
@@ -26,7 +26,7 @@ test01()
   using namespace std::experimental;
 
   wstring_view str0{L"olympus mons"};
-  wstring_view::pointer p = str0.data();
+  wstring_view::const_pointer p = str0.data();
   str0.remove_suffix(2);
   VERIFY( str0.data() == p);
   VERIFY( str0.length() == 10 );
index 269633bdf7e06124bdbe7b18288088e5ae7f5865..38e20e1625c25fb1880ac7a0e89f258176dadd39 100644 (file)
@@ -43,3 +43,16 @@ __gnu_test::basic_types<std::experimental::wstring_view> t2b;
 __gnu_test::reversible_types<std::experimental::wstring_view> t2r;
 typedef typename std::experimental::wstring_view::traits_type traits_type2;
 #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&");