PR libstdc++/70483 make std::experimental::string_view fully constexpr
authorJonathan Wakely <jwakely@redhat.com>
Tue, 12 Sep 2017 13:31:20 +0000 (14:31 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 12 Sep 2017 13:31:20 +0000 (14:31 +0100)
PR libstdc++/70483
* include/experimental/bits/string_view.tcc (basic_string_view::find)
(basic_string_view::rfind, basic_string_view::find_first_of)
(basic_string_view::find_last_of, basic_string_view::find_first_not_of)
(basic_string_view::find_last_not_of): Add constexpr specifier.
* include/experimental/string_view (basic_string_view::remove_prefix)
(basic_string_view::remove_suffix, basic_string_view::swap)
(basic_string_view::compare, basic_string_view::find)
(basic_string_view::rfind, basic_string_view::find_first_of)
(basic_string_view::find_last_of, basic_string_view::find_first_not_of)
(basic_string_view::find_last_not_of, operator==, operator!=)
(operator<, operator>, operator<=, operator>=): Likewise.
* testsuite/experimental/string_view/operations/compare/char/70483.cc:
New.

From-SVN: r252017

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/bits/string_view.tcc
libstdc++-v3/include/experimental/string_view
libstdc++-v3/testsuite/experimental/string_view/operations/compare/char/70483.cc [new file with mode: 0644]

index 8b285bf93d3bc17982583e3c5b4a67448c461cc4..5bae0dc7c91dd022430dd37b0ea721d01c4afdef 100644 (file)
@@ -1,3 +1,20 @@
+2017-09-12  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/70483
+       * include/experimental/bits/string_view.tcc (basic_string_view::find)
+       (basic_string_view::rfind, basic_string_view::find_first_of)
+       (basic_string_view::find_last_of, basic_string_view::find_first_not_of)
+       (basic_string_view::find_last_not_of): Add constexpr specifier.
+       * include/experimental/string_view (basic_string_view::remove_prefix)
+       (basic_string_view::remove_suffix, basic_string_view::swap)
+       (basic_string_view::compare, basic_string_view::find)
+       (basic_string_view::rfind, basic_string_view::find_first_of)
+       (basic_string_view::find_last_of, basic_string_view::find_first_not_of)
+       (basic_string_view::find_last_not_of, operator==, operator!=)
+       (operator<, operator>, operator<=, operator>=): Likewise.
+       * testsuite/experimental/string_view/operations/compare/char/70483.cc:
+       New.
+
 2017-09-11  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/70483
index e66932d1ac0e2e3f0b5eb6573cc978d60768cd5c..450a43c7876ef790dfc6171f5c379b5b0de7fd13 100644 (file)
@@ -49,7 +49,7 @@ namespace experimental
 inline namespace fundamentals_v1
 {
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find(const _CharT* __str, size_type __pos, size_type __n) const noexcept
     {
@@ -70,7 +70,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find(_CharT __c, size_type __pos) const noexcept
     {
@@ -86,7 +86,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept
     {
@@ -106,7 +106,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     rfind(_CharT __c, size_type __pos) const noexcept
     {
@@ -123,7 +123,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_of(const _CharT* __str, size_type __pos, size_type __n) const
     {
@@ -139,7 +139,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_of(const _CharT* __str, size_type __pos, size_type __n) const
     {
@@ -160,7 +160,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const
     {
@@ -172,7 +172,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_first_not_of(_CharT __c, size_type __pos) const noexcept
     {
@@ -183,7 +183,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const
     {
@@ -204,7 +204,7 @@ inline namespace fundamentals_v1
     }
 
   template<typename _CharT, typename _Traits>
-    typename basic_string_view<_CharT, _Traits>::size_type
+    constexpr typename basic_string_view<_CharT, _Traits>::size_type
     basic_string_view<_CharT, _Traits>::
     find_last_not_of(_CharT __c, size_type __pos) const noexcept
     {
index 5cec5597744ffef6c78a7505f29683f272085575..2e8e7cda62da67d97a6639df5727ff99b4682dae 100644 (file)
@@ -219,7 +219,7 @@ inline namespace fundamentals_v1
 
       // [string.view.modifiers], modifiers:
 
-      void
+      constexpr void
       remove_prefix(size_type __n)
       {
        __glibcxx_assert(this->_M_len >= __n);
@@ -227,15 +227,16 @@ inline namespace fundamentals_v1
        this->_M_len -= __n;
       }
 
-      void
+      constexpr void
       remove_suffix(size_type __n)
       { this->_M_len -= __n; }
 
-      void
+      constexpr void
       swap(basic_string_view& __sv) noexcept
       {
-       std::swap(this->_M_len, __sv._M_len);
-       std::swap(this->_M_str, __sv._M_str);
+       auto __tmp = *this;
+       *this = __sv;
+       __sv = __tmp;
       }
 
 
@@ -285,7 +286,7 @@ inline namespace fundamentals_v1
                                     __pos, this->size()), basic_string_view{});
       }
 
-      int
+      constexpr int
       compare(basic_string_view __str) const noexcept
       {
        int __ret = traits_type::compare(this->_M_str, __str._M_str,
@@ -295,24 +296,24 @@ inline namespace fundamentals_v1
        return __ret;
       }
 
-      int
+      constexpr int
       compare(size_type __pos1, size_type __n1, basic_string_view __str) const
       { return this->substr(__pos1, __n1).compare(__str); }
 
-      int
+      constexpr int
       compare(size_type __pos1, size_type __n1,
              basic_string_view __str, size_type __pos2, size_type __n2) const
       { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); }
 
-      int
+      constexpr int
       compare(const _CharT* __str) const noexcept
       { return this->compare(basic_string_view{__str}); }
 
-      int
+      constexpr int
       compare(size_type __pos1, size_type __n1, const _CharT* __str) const
       { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
 
-      int
+      constexpr int
       compare(size_type __pos1, size_type __n1,
              const _CharT* __str, size_type __n2) const
       {
@@ -320,97 +321,97 @@ inline namespace fundamentals_v1
                   .compare(basic_string_view(__str, __n2));
       }
 
-      size_type
+      constexpr size_type
       find(basic_string_view __str, size_type __pos = 0) const noexcept
       { return this->find(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       find(_CharT __c, size_type __pos=0) const noexcept;
 
-      size_type
+      constexpr size_type
       find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
-      size_type
+      constexpr size_type
       find(const _CharT* __str, size_type __pos=0) const noexcept
       { return this->find(__str, __pos, traits_type::length(__str)); }
 
-      size_type
+      constexpr size_type
       rfind(basic_string_view __str, size_type __pos = npos) const noexcept
       { return this->rfind(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       rfind(_CharT __c, size_type __pos = npos) const noexcept;
 
-      size_type
+      constexpr size_type
       rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
 
-      size_type
+      constexpr size_type
       rfind(const _CharT* __str, size_type __pos = npos) const noexcept
       { return this->rfind(__str, __pos, traits_type::length(__str)); }
 
-      size_type
+      constexpr size_type
       find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
       { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       find_first_of(_CharT __c, size_type __pos = 0) const noexcept
       { return this->find(__c, __pos); }
 
-      size_type
+      constexpr size_type
       find_first_of(const _CharT* __str, size_type __pos, size_type __n) const;
 
-      size_type
+      constexpr size_type
       find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
       { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
 
-      size_type
+      constexpr size_type
       find_last_of(basic_string_view __str,
                   size_type __pos = npos) const noexcept
       { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       find_last_of(_CharT __c, size_type __pos=npos) const noexcept
       { return this->rfind(__c, __pos); }
 
-      size_type
+      constexpr size_type
       find_last_of(const _CharT* __str, size_type __pos, size_type __n) const;
 
-      size_type
+      constexpr size_type
       find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
       { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
 
-      size_type
+      constexpr size_type
       find_first_not_of(basic_string_view __str,
                        size_type __pos = 0) const noexcept
       { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
 
-      size_type
+      constexpr size_type
       find_first_not_of(const _CharT* __str,
                        size_type __pos, size_type __n) const;
 
-      size_type
+      constexpr size_type
       find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
       {
        return this->find_first_not_of(__str, __pos,
                                       traits_type::length(__str));
       }
 
-      size_type
+      constexpr size_type
       find_last_not_of(basic_string_view __str,
                       size_type __pos = npos) const noexcept
       { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
 
-      size_type
+      constexpr size_type
       find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
 
-      size_type
+      constexpr size_type
       find_last_not_of(const _CharT* __str,
                       size_type __pos, size_type __n) const;
 
-      size_type
+      constexpr size_type
       find_last_not_of(const _CharT* __str,
                       size_type __pos = npos) const noexcept
       {
@@ -446,109 +447,109 @@ inline namespace fundamentals_v1
   }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator==(basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator==(basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator!=(basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return !(__x == __y); }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator!=(basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return !(__x == __y); }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return !(__x == __y); }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator< (basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) < 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator< (basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return __x.compare(__y) < 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) < 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator> (basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) > 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator> (basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return __x.compare(__y) > 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) > 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator<=(basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) <= 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator<=(basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return __x.compare(__y) <= 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) <= 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator>=(basic_string_view<_CharT, _Traits> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) >= 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator>=(basic_string_view<_CharT, _Traits> __x,
                __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
     { return __x.compare(__y) >= 0; }
 
   template<typename _CharT, typename _Traits>
-    inline bool
+    constexpr bool
     operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
                basic_string_view<_CharT, _Traits> __y) noexcept
     { return __x.compare(__y) >= 0; }
diff --git a/libstdc++-v3/testsuite/experimental/string_view/operations/compare/char/70483.cc b/libstdc++-v3/testsuite/experimental/string_view/operations/compare/char/70483.cc
new file mode 100644 (file)
index 0000000..3bfb59c
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (C) 2017 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-do compile { target c++14 } }
+
+#include <experimental/string_view>
+
+struct constexpr_char_traits : std::char_traits<char>
+{
+  static constexpr size_t
+  length(const char* val)
+  {
+    size_t res = 0;
+    for (; val[res] != '\0'; ++res)
+      ;
+    return res;
+  }
+
+  static constexpr int
+  compare(const char* lhs, const char* rhs, std::size_t count)
+  {
+    for (size_t pos = 0; pos < count; ++pos)
+    {
+      if (lhs[pos] != rhs[pos])
+        return lhs[pos] - rhs[pos];
+    }
+    return 0;
+  }
+
+  static constexpr const char*
+  find(const char* p, std::size_t n, char c)
+  {
+    for (size_t pos = 0; pos < n; ++pos)
+      if (p[pos] == c)
+       return p + pos;
+    return nullptr;
+  }
+};
+
+using string_view
+  = std::experimental::basic_string_view<char, constexpr_char_traits>;
+
+constexpr
+string_view get()
+{
+    string_view res = "x::";
+    string_view start_pattern = "x";
+    res = res.substr(res.find(start_pattern) + start_pattern.size());
+    res = res.substr(0, res.find_first_of(";]"));
+    res = res.substr(res.rfind("::"));
+    return res;
+}
+
+static_assert( get() == get() );