This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [PATCH] PR libstdc++/70483 make std::string_view fully constexpr
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Tue, 12 Sep 2017 14:31:15 +0100
- Subject: Re: [PATCH] PR libstdc++/70483 make std::string_view fully constexpr
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=jwakely at redhat dot com
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D5A9AC0587EE
- References: <20170911214846.GA8159@redhat.com>
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 <jwakely@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() );