Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,20 @@ public:
}
#endif // _HAS_CXX20

#if _HAS_CXX23
_NODISCARD constexpr bool contains(const basic_string_view _Right) const noexcept {
return find(_Right) != npos;
}

_NODISCARD constexpr bool contains(const _Elem _Right) const noexcept {
return find(_Right) != npos;
}

_NODISCARD constexpr bool contains(const _Elem* const _Right) const noexcept /* strengthened */ {
return find(_Right) != npos;
}
#endif // _HAS_CXX23

_NODISCARD constexpr size_type find(const basic_string_view _Right, const size_type _Off = 0) const noexcept {
// look for _Right beginning at or after _Off
return _Traits_find<_Traits>(_Mydata, _Mysize, _Off, _Right._Mydata, _Right._Mysize);
Expand Down Expand Up @@ -3854,7 +3868,7 @@ public:
#if _HAS_CXX17
/* implicit */ _CONSTEXPR20_CONTAINER operator basic_string_view<_Elem, _Traits>() const noexcept {
// return a string_view around *this's character-type sequence
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize};
}
#endif // _HAS_CXX17

Expand Down Expand Up @@ -4454,30 +4468,44 @@ public:

#if _HAS_CXX20
_NODISCARD _CONSTEXPR20_CONTAINER bool starts_with(const basic_string_view<_Elem, _Traits> _Right) const noexcept {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).starts_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.starts_with(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool starts_with(const _Elem _Right) const noexcept {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).starts_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.starts_with(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool starts_with(const _Elem* const _Right) const noexcept /* strengthened */ {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).starts_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.starts_with(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool ends_with(const basic_string_view<_Elem, _Traits> _Right) const noexcept {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).ends_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.ends_with(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool ends_with(const _Elem _Right) const noexcept {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).ends_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.ends_with(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool ends_with(const _Elem* const _Right) const noexcept /* strengthened */ {
return basic_string_view<_Elem, _Traits>(_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize).ends_with(_Right);
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.ends_with(_Right);
}
#endif // _HAS_CXX20

#if _HAS_CXX23
_NODISCARD _CONSTEXPR20_CONTAINER bool contains(const basic_string_view<_Elem, _Traits> _Right) const noexcept {
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.contains(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool contains(const _Elem _Right) const noexcept {
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.contains(_Right);
}

_NODISCARD _CONSTEXPR20_CONTAINER bool contains(const _Elem* const _Right) const noexcept /* strengthened */ {
return basic_string_view<_Elem, _Traits>{_Mypair._Myval2._Myptr(), _Mypair._Myval2._Mysize}.contains(_Right);
}
#endif // _HAS_CXX23

_NODISCARD _CONSTEXPR20_CONTAINER allocator_type get_allocator() const noexcept {
return static_cast<allocator_type>(_Getal());
}
Expand Down
4 changes: 3 additions & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@

// _HAS_CXX23 directly controls:
// P1048R1 is_scoped_enum
// P1679R3 contains() For basic_string/basic_string_view

// Parallel Algorithms Notes
// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms.
Expand Down Expand Up @@ -1340,7 +1341,8 @@

// C++23
#if _HAS_CXX23
#define __cpp_lib_is_scoped_enum 202011L
#define __cpp_lib_is_scoped_enum 202011L
#define __cpp_lib_string_contains 202011L
#endif // _HAS_CXX23

// EXPERIMENTAL
Expand Down
117 changes: 116 additions & 1 deletion tests/std/tests/P0220R1_string_view/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,115 @@ constexpr bool test_case_starts_with_ends_with() {

return true;
}
#endif //_HAS_CXX20
#endif // _HAS_CXX20

// P1679R3 contains() For basic_string/basic_string_view
#if _HAS_CXX23
template <class CharT, class Traits, bool TestBasicString>
constexpr bool test_case_contains() {
const basic_string_view<CharT, Traits> empty_sv(TYPED_LITERAL(CharT, ""));
const CharT null_c = '\0';
const CharT* const empty_cp(TYPED_LITERAL(CharT, ""));

const basic_string_view<CharT, Traits> a(TYPED_LITERAL(CharT, "a"));
const CharT b = 'b';
const CharT* const c(TYPED_LITERAL(CharT, "c"));

if constexpr (TestBasicString) {
basic_string<CharT, Traits> text(TYPED_LITERAL(CharT, "text"));
basic_string<CharT, Traits> empty_text(TYPED_LITERAL(CharT, ""));

const basic_string_view<CharT, Traits> te(TYPED_LITERAL(CharT, "te"));
const CharT x = 'x';
const CharT* const ext(TYPED_LITERAL(CharT, "ext"));
const basic_string_view<CharT, Traits> text_sv(TYPED_LITERAL(CharT, "text"));
const CharT* const text_cp(TYPED_LITERAL(CharT, "text"));
const basic_string_view<CharT, Traits> next_sv(TYPED_LITERAL(CharT, "next"));
const CharT* const next_cp(TYPED_LITERAL(CharT, "next"));
const basic_string_view<CharT, Traits> texture_sv(TYPED_LITERAL(CharT, "texture"));
const CharT* const texture_cp(TYPED_LITERAL(CharT, "texture"));

assert(text.contains(te));
assert(text.contains(x));
assert(text.contains(ext));
assert(text.contains(text));
assert(text.contains(text_sv));
assert(text.contains(text_cp));
assert(!text.contains(next_sv));
assert(!text.contains(next_cp));
assert(!text.contains(texture_sv));
assert(!text.contains(texture_cp));
assert(text.contains(empty_sv));
assert(!text.contains(null_c));
assert(text.contains(empty_cp));
assert(!text.contains(a));
assert(!text.contains(b));
assert(!text.contains(c));

assert(!empty_text.contains(te));
assert(!empty_text.contains(x));
assert(!empty_text.contains(ext));
assert(empty_text.contains(empty_text));
assert(empty_text.contains(empty_sv));
assert(!empty_text.contains(null_c));
assert(empty_text.contains(empty_cp));

basic_string<CharT, Traits> rocking(TYPED_LITERAL(CharT, "rocking"));

const basic_string_view<CharT, Traits> rocket_sv(TYPED_LITERAL(CharT, "rocket"));
const CharT* const rocket_cp(TYPED_LITERAL(CharT, "rocket"));

assert(!rocking.contains(rocket_sv));
assert(!rocking.contains(rocket_cp));
}

const basic_string_view<CharT, Traits> hello(TYPED_LITERAL(CharT, "hello"));

const basic_string_view<CharT, Traits> he(TYPED_LITERAL(CharT, "he"));
const CharT e = 'e';
const CharT* const llo(TYPED_LITERAL(CharT, "llo"));
const basic_string_view<CharT, Traits> hello_sv(TYPED_LITERAL(CharT, "hello"));
const CharT* const hello_cp(TYPED_LITERAL(CharT, "hello"));
const basic_string_view<CharT, Traits> cello_sv(TYPED_LITERAL(CharT, "cello"));
const CharT* const cello_cp(TYPED_LITERAL(CharT, "cello"));
const basic_string_view<CharT, Traits> helloworld_sv(TYPED_LITERAL(CharT, "helloworld"));
const CharT* const helloworld_cp(TYPED_LITERAL(CharT, "helloworld"));

assert(hello.contains(he));
assert(hello.contains(e));
assert(hello.contains(llo));
assert(hello.contains(hello));
assert(hello.contains(hello_sv));
assert(hello.contains(hello_cp));
assert(!hello.contains(cello_sv));
assert(!hello.contains(cello_cp));
assert(!hello.contains(helloworld_sv));
assert(!hello.contains(helloworld_cp));
assert(hello.contains(empty_sv));
assert(!hello.contains(null_c));
assert(hello.contains(empty_cp));
assert(!hello.contains(a));
assert(!hello.contains(b));
assert(!hello.contains(c));

assert(!empty_sv.contains(he));
assert(!empty_sv.contains(e));
assert(!empty_sv.contains(llo));
assert(empty_sv.contains(empty_sv));
assert(!empty_sv.contains(null_c));
assert(empty_sv.contains(empty_cp));

const basic_string_view<CharT, Traits> playing(TYPED_LITERAL(CharT, "playing"));

const basic_string_view<CharT, Traits> player_sv(TYPED_LITERAL(CharT, "player"));
const CharT* const player_cp(TYPED_LITERAL(CharT, "player"));

assert(!playing.contains(player_sv));
assert(!playing.contains(player_cp));

return true;
}
#endif // _HAS_CXX23

template <typename CharT, typename Traits>
constexpr bool test_case_find() {
Expand Down Expand Up @@ -1062,6 +1170,9 @@ static_assert(test_case_copy<constexpr_char_traits>());
static_assert(test_case_Copy_s<constexpr_char_traits>());
static_assert(test_case_starts_with_ends_with<char, constexpr_char_traits, false>());
#endif // _HAS_CXX20
#if _HAS_CXX23
static_assert(test_case_contains<char, constexpr_char_traits, false>());
#endif // _HAS_CXX23
static_assert(test_case_operators<char, constexpr_char_traits>());
static_assert(test_case_find<char, constexpr_char_traits>());

Expand Down Expand Up @@ -1115,6 +1226,10 @@ int main() {
test_case_starts_with_ends_with<char, char_traits<char>, true>();
test_case_starts_with_ends_with<wchar_t, char_traits<wchar_t>, true>();
#endif // _HAS_CXX20
#if _HAS_CXX23
test_case_contains<char, char_traits<char>, true>();
test_case_contains<wchar_t, char_traits<wchar_t>, true>();
#endif // _HAS_CXX23
test_case_find<char, char_traits<char>>();
test_case_find<wchar_t, char_traits<wchar_t>>();
test_case_operators<char, char_traits<char>>();
Expand Down
16 changes: 16 additions & 0 deletions tests/std/tests/P0980R1_constexpr_strings/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,22 @@ _CONSTEXPR20_CONTAINER bool test_interface() {
assert(!input_string_false.ends_with(get_literal_input<CharType>()));
}

#if _HAS_CXX23
{ // contains
const str hello_fluffy_kittens = get_literal_input<CharType>(); // "Hello fluffy kittens"
constexpr auto kitten_ptr = get_cat<CharType>(); // "kitten"
constexpr auto dog_ptr = get_dog<CharType>(); // "dog"

assert(hello_fluffy_kittens.contains(kitten_ptr));
assert(hello_fluffy_kittens.contains(basic_string_view{kitten_ptr}));
assert(hello_fluffy_kittens.contains(CharType{'e'}));

assert(!hello_fluffy_kittens.contains(dog_ptr));
assert(!hello_fluffy_kittens.contains(basic_string_view{dog_ptr}));
assert(!hello_fluffy_kittens.contains(CharType{'z'}));
}
#endif // _HAS_CXX23

{ // replace
const str input = get_dog<CharType>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,20 @@ STATIC_ASSERT(__cpp_lib_starts_ends_with == 201711L);
#endif
#endif

#if _HAS_CXX23
#ifndef __cpp_lib_string_contains
#error __cpp_lib_string_contains is not defined
#elif __cpp_lib_string_contains != 202011L
#error __cpp_lib_string_contains is not 202011L
#else
STATIC_ASSERT(__cpp_lib_string_contains == 202011L);
#endif
#else
#ifdef __cpp_lib_string_contains
#error __cpp_lib_string_contains is defined
#endif
#endif

#ifndef __cpp_lib_string_udls
#error __cpp_lib_string_udls is not defined
#elif __cpp_lib_string_udls != 201304L
Expand Down