From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by sourceware.org (Postfix) with ESMTPS id 6CAF4387090C; Fri, 15 Jan 2021 01:23:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 6CAF4387090C Received: by mail-lf1-x12b.google.com with SMTP id u25so10870303lfc.2; Thu, 14 Jan 2021 17:23:42 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=dgqCEhWJ1ObNgNNzTRnCBntpDNeZZEZzgSbS/XUivjE=; b=QDOkrAfPaY0hoQHnwL1NktKz4d5mzzJJ6gYm+vH/5j89hHF6hZLjiwOq9cM8qjyoLb jVDlsh0ZJ5GydK+7Enrjp2zwTLPtgnnX1E6pN99eTn6RztuN17sN3qcs8KyOMd/O/O91 l2Tf50FgmK3gi5iwXiG8yGnXgbPuBsd+c4UGhFKtM6FQD2AE0hUkqtYV4DaKYGzLDU4n 7of3raef65CGFeja9asLVY2J0XLZBTboQQMWO9WUobjhkQKRXZy1Ec3K6GvpDK0JfywE HbWMrwbG1jztc5ypUw9PMkCw39V6pd+EM+aj8yBZvIOa31Ym5fXJtAtdF/QBLJAxBPvA DoBA== X-Gm-Message-State: AOAM533NpcBqujDJ/HLczOsz12sVoTTX3b9rNiBj/EuZiEe4wWQ91BhZ a5nFaHtqm5CuUP7ioNMcNPT+a5qRg8++G8dUvVJy4Ewk/nk78g== X-Google-Smtp-Source: ABdhPJxAxvYQNAeauIwRmHurQnhSI5SqIqE1grWfjf9iDjWrYaK0MvYocx8ISpOEaXIm/k46U+T0El7JrnWGlOakW84= X-Received: by 2002:a19:48e:: with SMTP id 136mr4395385lfe.357.1610673820479; Thu, 14 Jan 2021 17:23:40 -0800 (PST) MIME-Version: 1.0 From: Paul Fee Date: Fri, 15 Jan 2021 01:23:29 +0000 Message-ID: Subject: [PATCH v2] libstdc++: C++23, implement WG21 P1679R3 To: gcc-patches , "libstdc++" Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Jan 2021 01:23:45 -0000 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 and . 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 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 +// . + +// basic_string contains + +#include +#include + +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 +// . + +// basic_string contains + +#include +#include + +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 +// . + +// basic_string_view contains + +#include + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in " +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in " +#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 +// . + +#include + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in " +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in " +#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 +// . + +// basic_string_view contains + +#include + +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')); +}