On 11/09/17 22:48 +0100, Jonathan Wakely wrote:
This adds 'constexpr' everywhere it's missing from
std::basic_string_view.

And this does it for std::experimental::basic_string_view, fixing the
bug as reported.

Tested powerpc64le-linux, committed to trunk.



commit d1cb3e5ac0bf7b07a06d4b8bbdd4f6752be112ae
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Tue Sep 12 10:44:38 2017 +0100

    PR libstdc++/70483 make std::experimental::string_view fully constexpr
    
            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.

diff --git a/libstdc++-v3/include/experimental/bits/string_view.tcc b/libstdc++-v3/include/experimental/bits/string_view.tcc
index e66932d1ac0..450a43c7876 100644
--- a/libstdc++-v3/include/experimental/bits/string_view.tcc
+++ b/libstdc++-v3/include/experimental/bits/string_view.tcc
@@ -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
     {
diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view
index 5cec5597744..2e8e7cda62d 100644
--- a/libstdc++-v3/include/experimental/string_view
+++ b/libstdc++-v3/include/experimental/string_view
@@ -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
index 00000000000..3bfb59c046b
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/string_view/operations/compare/char/70483.cc
@@ -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() );

Reply via email to