From e38bde5423c85db03ac619f2232cbcad41924246 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 12 Sep 2017 17:27:14 +0100 Subject: [PATCH] PR libstdc++/70483 make std::experimental::string_view fully constexpr Backport from mainline 2017-09-12 Jonathan Wakely 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: r252032 --- libstdc++-v3/ChangeLog | 18 +++ .../include/experimental/bits/string_view.tcc | 20 ++-- libstdc++-v3/include/experimental/string_view | 107 +++++++++--------- .../operations/compare/char/70483.cc | 68 +++++++++++ 4 files changed, 150 insertions(+), 63 deletions(-) create mode 100644 libstdc++-v3/testsuite/experimental/string_view/operations/compare/char/70483.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fb3759182e6..29a7731c795 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,23 @@ 2017-09-12 Jonathan Wakely + Backport from mainline + 2017-09-12 Jonathan Wakely + + 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. + Backport from mainline 2017-09-11 Jonathan Wakely diff --git a/libstdc++-v3/include/experimental/bits/string_view.tcc b/libstdc++-v3/include/experimental/bits/string_view.tcc index 03863d0a9df..30968fc6b83 100644 --- a/libstdc++-v3/include/experimental/bits/string_view.tcc +++ b/libstdc++-v3/include/experimental/bits/string_view.tcc @@ -49,7 +49,7 @@ inline namespace fundamentals_v1 _GLIBCXX_BEGIN_NAMESPACE_VERSION template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - 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 bd212ac3719..24c17e8cbe8 100644 --- a/libstdc++-v3/include/experimental/string_view +++ b/libstdc++-v3/include/experimental/string_view @@ -219,7 +219,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [string.view.modifiers], modifiers: - void + constexpr void remove_prefix(size_type __n) { __glibcxx_assert(this->_M_len >= __n); @@ -227,15 +227,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION .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 { @@ -452,109 +453,109 @@ _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION template - 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 - inline bool + constexpr bool operator==(basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template - inline bool + constexpr bool operator==(__detail::__idt> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template - inline bool + constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template - inline bool + constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return !(__x == __y); } template - inline bool + constexpr bool operator!=(__detail::__idt> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template - inline bool + constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template - inline bool + constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return __x.compare(__y) < 0; } template - inline bool + constexpr bool operator< (__detail::__idt> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template - inline bool + constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template - inline bool + constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return __x.compare(__y) > 0; } template - inline bool + constexpr bool operator> (__detail::__idt> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template - inline bool + constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template - inline bool + constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return __x.compare(__y) <= 0; } template - inline bool + constexpr bool operator<=(__detail::__idt> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template - inline bool + constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) >= 0; } template - inline bool + constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, __detail::__idt> __y) noexcept { return __x.compare(__y) >= 0; } template - inline bool + constexpr bool operator>=(__detail::__idt> __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 +// . + +// { dg-do compile { target c++14 } } + +#include + +struct constexpr_char_traits : std::char_traits +{ + 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; + +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() );