Add contains member function to basic_string_view and basic_string. The new method is enabled for -std=gnu++20, gnu++2b and c++2b. This allows users to access the method as a GNU extension to C++20. The conditional test may be reduced to "__cplusplus > 202011L" once GCC has a c++2b switch.
Changes since v1 (13th Jan 2021) * New: Test __cplusplus >= 202011L, rather than __cplusplus > 202011L. * As suggested by Jonathan Wakely: Adjust formatting. Test feature-test macro is defined by <string_view> and <version>. Correct copyright dates on new files. Fix comment typo. libstdc++-v3/ Add contains member function to basic_string_view. Likewise to basic_string_view, both with and without _GLIBCXX_USE_CXX11_ABI. Enabled with -std=gnu++20, gnu++2b and c++2b. * include/bits/basic_string.h (basic_string::contains): New. * libstdc++-v3/include/std/string_view (basic_string_view::contains): New. * testsuite/21_strings/basic_string/operations/contains/char/1.cc: New test. * testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc: New test. * testsuite/21_strings/basic_string_view/operations/contains/char/1.cc: New test. * testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc: New test. --- libstdc++-v3/include/bits/basic_string.h | 30 ++++ libstdc++-v3/include/std/string_view | 16 ++ libstdc++-v3/include/std/version | 9 + libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc | 65 ++++++++++ libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc | 65 ++++++++++ libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc | 2 libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc | 2 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc | 57 ++++++++ libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc | 27 ++++ libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc | 51 +++++++ 10 files changed, 320 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index e272d332934..ec0abca2a5d 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3073,6 +3073,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 +#if __cplusplus >= 202011L \ + || (__cplusplus == 202002L && !defined __STRICT_ANSI__) + bool + contains(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } +#endif // C++23 + // Allow basic_stringbuf::__xfer_bufptrs to call _M_length: template<typename, typename, typename> friend class basic_stringbuf; }; @@ -5998,6 +6013,21 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 +#if __cplusplus >= 202011L \ + || (__cplusplus == 202002L && !defined __STRICT_ANSI__) + bool + contains(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } +#endif // C++23 + # ifdef _GLIBCXX_TM_TS_INTERNAL friend void ::_txnal_cow_string_C1_for_exceptions(void* that, const char* s, diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index e33e1bc4b79..6a6863cf189 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -352,6 +352,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return this->ends_with(basic_string_view(__x)); } #endif // C++20 +#if __cplusplus >= 202011L \ + || (__cplusplus == 202002L && !defined __STRICT_ANSI__) +#define __cpp_lib_string_contains 202011L + constexpr bool + contains(basic_string_view __x) const noexcept + { return this->find(__x) != npos; } + + constexpr bool + contains(_CharT __x) const noexcept + { return this->find(__x) != npos; } + + constexpr bool + contains(const _CharT* __x) const noexcept + { return this->find(__x) != npos; } +#endif // C++23 + // [string.view.find], searching constexpr size_type diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index e3d52b88c21..ace87cf42cf 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -167,7 +167,7 @@ #endif #if __cplusplus > 201703L -// c++2a +// c++20 #define __cpp_lib_atomic_flag_test 201907L #define __cpp_lib_atomic_float 201711L #define __cpp_lib_atomic_ref 201806L @@ -256,7 +256,12 @@ #define __cpp_lib_to_address 201711L #define __cpp_lib_to_array 201907L #endif -#endif // C++2a + +#if __cplusplus > 202002L +// c++2b +#define __cpp_lib_string_contains 202011L +#endif // C++2b +#endif // C++20 #endif // C++17 #endif // C++14 #endif // C++11 diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc new file mode 100644 index 00000000000..54ee1bb6969 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++2b } } + +// Copyright (C) 2021 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/>. + +// basic_string contains + +#include <string> +#include <testsuite_hooks.h> + +void +test01() +{ + const std::string haystack("no place for needles"); + + VERIFY(haystack.contains(std::string(""))); + VERIFY(haystack.contains(std::string("no"))); + VERIFY(haystack.contains(std::string("needles"))); + VERIFY(haystack.contains(std::string(" for "))); + VERIFY(!haystack.contains(std::string("places"))); + + VERIFY(haystack.contains(std::string_view(""))); + VERIFY(haystack.contains(std::string_view("no"))); + VERIFY(haystack.contains(std::string_view("needles"))); + VERIFY(haystack.contains(std::string_view(" for "))); + VERIFY(!haystack.contains(std::string_view("places"))); + + VERIFY(!haystack.contains('\0')); + VERIFY(haystack.contains('n')); + VERIFY(haystack.contains('e')); + VERIFY(haystack.contains('s')); + VERIFY(!haystack.contains('x')); + + VERIFY(haystack.contains("")); + VERIFY(haystack.contains("no")); + VERIFY(haystack.contains("needles")); + VERIFY(haystack.contains(" for ")); + VERIFY(!haystack.contains("places")); + + const std::string nothing; + VERIFY(nothing.contains("")); + VERIFY(!nothing.contains('\0')); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc new file mode 100644 index 00000000000..ee0d14c3382 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++2b } } + +// Copyright (C) 2021 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/>. + +// basic_string contains + +#include <string> +#include <testsuite_hooks.h> + +void +test01() +{ + const std::wstring haystack(L"no place for needles"); + + VERIFY(haystack.contains(std::wstring(L""))); + VERIFY(haystack.contains(std::wstring(L"no"))); + VERIFY(haystack.contains(std::wstring(L"needles"))); + VERIFY(haystack.contains(std::wstring(L" for "))); + VERIFY(!haystack.contains(std::wstring(L"places"))); + + VERIFY(haystack.contains(std::wstring_view(L""))); + VERIFY(haystack.contains(std::wstring_view(L"no"))); + VERIFY(haystack.contains(std::wstring_view(L"needles"))); + VERIFY(haystack.contains(std::wstring_view(L" for "))); + VERIFY(!haystack.contains(std::wstring_view(L"places"))); + + VERIFY(!haystack.contains('\0')); + VERIFY(haystack.contains('n')); + VERIFY(haystack.contains('e')); + VERIFY(haystack.contains('s')); + VERIFY(!haystack.contains('x')); + + VERIFY(haystack.contains(L"")); + VERIFY(haystack.contains(L"no")); + VERIFY(haystack.contains(L"needles")); + VERIFY(haystack.contains(L" for ")); + VERIFY(!haystack.contains(L"places")); + + const std::wstring nothing; + VERIFY(nothing.contains(L"")); + VERIFY(!nothing.contains('\0')); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc index 7445942679b..4f4a8d2c20c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc @@ -50,7 +50,7 @@ test01() int main() -{ +{ test01(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc index 5c4e94aba75..022f128a2a0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc @@ -50,7 +50,7 @@ test01() int main() -{ +{ test01(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc new file mode 100644 index 00000000000..d087314fdf3 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc @@ -0,0 +1,57 @@ +// { dg-options "-std=gnu++2b" } +// { dg-do compile { target c++2b } } + +// Copyright (C) 2021 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/>. + +// basic_string_view contains + +#include <string_view> + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in <string_view>" +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in <string_view>" +#endif + +void +test01() +{ + constexpr std::string_view haystack("no place for needles"); + + static_assert(haystack.contains(std::string_view(""))); + static_assert(haystack.contains(std::string_view("no"))); + static_assert(haystack.contains(std::string_view("needles"))); + static_assert(haystack.contains(std::string_view(" for "))); + static_assert(!haystack.contains(std::string_view("places"))); + + static_assert(!haystack.contains('\0')); + static_assert(haystack.contains('n')); + static_assert(haystack.contains('e')); + static_assert(haystack.contains('s')); + static_assert(!haystack.contains('x')); + + static_assert(haystack.contains("")); + static_assert(haystack.contains("no")); + static_assert(haystack.contains("needles")); + static_assert(haystack.contains(" for ")); + static_assert(!haystack.contains("places")); + + constexpr std::string_view nothing; + static_assert(nothing.contains("")); + static_assert(!nothing.contains('\0')); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc new file mode 100644 index 00000000000..c9be1849382 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc @@ -0,0 +1,27 @@ +// { dg-options "-std=gnu++2b" } +// { dg-do compile { target c++2b } } + +// Copyright (C) 2021 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/>. + +#include <version> + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in <string_view>" +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in <string_view>" +#endif diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc new file mode 100644 index 00000000000..b61fca966cf --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++2b" } +// { dg-do compile { target c++2b } } + +// Copyright (C) 2021 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/>. + +// basic_string_view contains + +#include <string_view> + +void +test01() +{ + constexpr std::wstring_view haystack = L"no place for needles"; + + static_assert(haystack.contains(std::wstring_view(L""))); + static_assert(haystack.contains(std::wstring_view(L"no"))); + static_assert(haystack.contains(std::wstring_view(L"needles"))); + static_assert(haystack.contains(std::wstring_view(L" for "))); + static_assert(!haystack.contains(std::wstring_view(L"places"))); + + static_assert(!haystack.contains('\0')); + static_assert(haystack.contains('n')); + static_assert(haystack.contains('e')); + static_assert(haystack.contains('s')); + static_assert(!haystack.contains('x')); + + static_assert(haystack.contains(L"")); + static_assert(haystack.contains(L"no")); + static_assert(haystack.contains(L"needles")); + static_assert(haystack.contains(L" for ")); + static_assert(!haystack.contains(L"places")); + + constexpr std::wstring_view nothing; + static_assert(nothing.contains(L"")); + static_assert(!nothing.contains('\0')); +}