Index: libcxx/include/string =================================================================== --- libcxx/include/string +++ libcxx/include/string @@ -324,6 +324,10 @@ bool ends_with(charT c) const noexcept; // C++20 bool ends_with(const charT* s) const; // C++20 + constexpr bool contains(basic_string_view sv) const noexcept; // C++23 + constexpr bool contains(charT c) const noexcept; // C++23 + constexpr bool contains(const charT* s) const; // C++23 + bool __invariants() const; }; @@ -1433,6 +1437,20 @@ { return ends_with(__self_view(__s)); } #endif +#if _LIBCPP_STD_VER > 20 + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(__self_view __sv) const _NOEXCEPT + { return __self_view(data(), size()).contains( __sv); } + + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(_CharT __c) const _NOEXCEPT + { return __self_view(data(), size()).contains( __c); } + + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(const _CharT* __s) const _NOEXCEPT + { return contains(__self_view(__s)); } +#endif + _LIBCPP_INLINE_VISIBILITY bool __invariants() const; _LIBCPP_INLINE_VISIBILITY void __clear_and_shrink() _NOEXCEPT; Index: libcxx/include/string_view =================================================================== --- libcxx/include/string_view +++ libcxx/include/string_view @@ -149,6 +149,10 @@ constexpr bool ends_with(charT c) const noexcept; // C++20 constexpr bool ends_with(const charT* s) const; // C++20 + constexpr bool contains(basic_string_view s) const noexcept; // C++23 + constexpr bool contains(charT c) const noexcept; // C++23 + constexpr bool contains(const charT* s) const; // C++23 + private: const_pointer data_; // exposition only size_type size_; // exposition only @@ -622,6 +626,21 @@ { return ends_with(basic_string_view(__s)); } #endif +#if _LIBCPP_STD_VER > 20 + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(basic_string_view __s) const _NOEXCEPT + { return find(__s) != npos; } + + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(_CharT __c) const _NOEXCEPT + { return find(__c) != npos; } + + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool contains(const _CharT* __s) const _NOEXCEPT + { return contains(basic_string_view(__s)); } +#endif + + private: const value_type* __data; size_type __size; Index: libcxx/include/version =================================================================== --- libcxx/include/version +++ libcxx/include/version @@ -278,4 +278,8 @@ # define __cpp_lib_to_array 201907L #endif +#if _LIBCPP_STD_VER > 20 +# define __cpp_lib_string_contains 202101L +#endif + #endif // _LIBCPP_VERSIONH Index: libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++2a + +// + +// bool contains(charT x) const noexcept; + +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + typedef std::string S; + S s1{}; + S s2{"abcde", 5}; + + ASSERT_NOEXCEPT(s1.contains('e')); + + assert(!s1.contains('a')); + assert(!s1.contains('x')); + + assert( s2.contains('a')); + assert( s2.contains('c')); + assert( s2.contains('e')); + assert(!s2.contains('x')); + } + + return 0; +} Index: libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++2a + +// + +// bool contains(const CharT *x) const; + +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + typedef std::string S; + const char* s = "abcde"; + S s0{}; + S s1{s, 1}; + S s2{s, 2}; + // S s3 { s, 3 }; + // S s4 { s, 4 }; + S s5{s, 5}; + S sNot{"def", 3}; + + LIBCPP_ASSERT_NOEXCEPT(s0.contains("")); + + assert( s0.contains("")); + assert(!s0.contains("a")); + + assert( s1.contains("")); + assert( s1.contains("a")); + assert(!s1.contains("ab")); + assert(!s1.contains("abc")); + assert(!s1.contains("abcd")); + assert(!s1.contains("abcde")); + assert(!s1.contains("def")); + + assert( s2.contains("")); + assert( s2.contains("a")); + assert( s2.contains("b")); + assert( s2.contains("ab")); + assert(!s2.contains("abc")); + assert(!s2.contains("abcd")); + assert(!s2.contains("abcde")); + assert(!s2.contains("def")); + + assert( s5.contains("")); + assert( s5.contains("a")); + assert( s5.contains("b")); + assert( s5.contains("ab")); + assert( s5.contains("bc")); + assert( s5.contains("abc")); + assert( s5.contains("bcd")); + assert( s5.contains("cde")); + assert( s5.contains("abcd")); + assert( s5.contains("bcde")); + assert( s5.contains("abcde")); + assert(!s5.contains("def")); + + assert( sNot.contains("")); + assert(!sNot.contains("a")); + assert(!sNot.contains("ab")); + assert(!sNot.contains("abc")); + assert(!sNot.contains("abcd")); + assert(!sNot.contains("abcde")); + assert( sNot.contains("def")); + } + + return 0; +} Index: libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++2a + +// + +// bool contains(string_view x) const noexcept; + +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + typedef std::string S; + typedef std::string_view SV; + const char* s = "abcde"; + + S s0; + S s1{s, 1}; + S s2{s, 2}; + // S s3 { s, 3 }; + // S s4 { s, 4 }; + S s5{s, 5}; + S sNot{"def", 3}; + + SV sv0; + SV sv1{s, 1}; + SV sv2{s, 2}; + SV sv3{s, 3}; + SV sv4{s, 4}; + SV sv5{s, 5}; + + SV sv3_s0 = sv5.substr(0, 3); + SV sv3_s1 = sv5.substr(1, 3); + SV sv3_s2 = sv5.substr(2, 3); + + SV svNot{"def", 3}; + + ASSERT_NOEXCEPT(s0.contains(sv0)); + + assert( s0.contains(sv0)); + assert(!s0.contains(sv1)); + + assert( s1.contains(sv0)); + assert( s1.contains(sv1)); + assert(!s1.contains(sv2)); + assert(!s1.contains(sv3)); + assert(!s1.contains(sv4)); + assert(!s1.contains(sv5)); + assert(!s1.contains(svNot)); + + assert( s2.contains(sv0)); + assert( s2.contains(sv1)); + assert( s2.contains(sv2)); + assert(!s2.contains(sv3)); + assert(!s2.contains(sv4)); + assert(!s2.contains(sv5)); + assert(!s2.contains(svNot)); + + assert( s5.contains(sv3_s0)); + assert( s5.contains(sv3_s1)); + assert( s5.contains(sv3_s2)); + + assert( sNot.contains(sv0)); + assert(!sNot.contains(sv1)); + assert(!sNot.contains(sv2)); + assert(!sNot.contains(sv3)); + assert(!sNot.contains(sv4)); + assert(!sNot.contains(sv5)); + assert( sNot.contains(svNot)); + } + + return 0; +} Index: libcxx/test/std/strings/string.view/string_view.contains/contains.ptr.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/strings/string.view/string_view.contains/contains.ptr.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++2a + +// + +// bool contains(const CharT *x) const; + +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + typedef std::string_view SV; + const char* s = "abcde"; + SV s0{}; + SV s1{s, 1}; + SV s2{s, 2}; + SV s5{s, 5}; + SV sNot{"def", 3}; + + LIBCPP_ASSERT_NOEXCEPT(s0.contains("")); + + assert(s0.contains("")); + assert(!s0.contains("a")); + + assert( s1.contains("")); + assert( s1.contains("a")); + assert(!s1.contains("ab")); + assert(!s1.contains("abc")); + assert(!s1.contains("abcd")); + assert(!s1.contains("abcde")); + assert(!s1.contains("def")); + + assert( s2.contains("")); + assert( s2.contains("a")); + assert( s2.contains("b")); + assert( s2.contains("ab")); + assert(!s2.contains("abc")); + assert(!s2.contains("abcd")); + assert(!s2.contains("abcde")); + assert(!s2.contains("def")); + + assert( s5.contains("")); + assert( s5.contains("a")); + assert( s5.contains("b")); + assert( s5.contains("ab")); + assert( s5.contains("bc")); + assert( s5.contains("abc")); + assert( s5.contains("bcd")); + assert( s5.contains("cde")); + assert( s5.contains("abcd")); + assert( s5.contains("bcde")); + assert( s5.contains("abcde")); + assert(!s5.contains("def")); + + assert( sNot.contains("")); + assert(!sNot.contains("a")); + assert(!sNot.contains("ab")); + assert(!sNot.contains("abc")); + assert(!sNot.contains("abcd")); + assert(!sNot.contains("abcde")); + assert( sNot.contains("def")); + } + + return 0; +} Index: libcxx/utils/generate_feature_test_macro_components.py =================================================================== --- libcxx/utils/generate_feature_test_macro_components.py +++ libcxx/utils/generate_feature_test_macro_components.py @@ -419,6 +419,10 @@ "name": "__cpp_lib_string_view", "values": { "c++17": 201606 }, "headers": ["string", "string_view"], + }, { + "name": "__cpp_lib_string_contains", + "values": { "c++23": 202101 }, + "headers": ["string", "string_view"], }, { "name": "__cpp_lib_three_way_comparison", "values": { "c++20": 201711 }, Index: libcxx/utils/libcxx/test/params.py =================================================================== --- libcxx/utils/libcxx/test/params.py +++ libcxx/utils/libcxx/test/params.py @@ -8,7 +8,7 @@ from libcxx.test.dsl import * -_allStandards = ['c++03', 'c++11', 'c++14', 'c++17', 'c++2a'] +_allStandards = ['c++03', 'c++11', 'c++14', 'c++17', 'c++2a', 'c++2b'] _warningFlags = [ '-Werror', '-Wall',