blob: 03dada0fec753be3d2650eaebf5c2b085012f700 [file] [log] [blame]
// { dg-do run }
#include <algorithm>
#include <cstddef> // std::byte
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
// PR libstdc++/88545 made std::find use memchr as an optimization.
// This test verifies that it didn't change any semantics.
template<typename C>
void
test_char()
{
const C a[] = { (C)'a', (C)'b', (C)'c', (C)'d' };
const C* end = a + sizeof(a);
const C* res = std::find(a, end, a[0]);
VERIFY( res == a );
res = std::find(a, end, a[2]);
VERIFY( res == a+2 );
res = std::find(a, end, a[0] + 256);
VERIFY( res == end );
res = std::find(a, end, a[0] - 256);
VERIFY( res == end );
res = std::find(a, end, 256);
VERIFY( res == end );
#ifdef __cpp_lib_ranges
res = std::ranges::find(a, a[0]);
VERIFY( res == a );
res = std::ranges::find(a, a[2]);
VERIFY( res == a+2 );
res = std::ranges::find(a, a[0] + 256);
VERIFY( res == end );
res = std::ranges::find(a, a[0] - 256);
VERIFY( res == end );
res = std::ranges::find(a, 256);
VERIFY( res == end );
#endif
}
// Trivial type of size 1, with custom equality.
struct S {
bool operator==(const S&) const { return true; };
char c;
};
// Trivial type of size 1, with custom equality.
enum E
#if __cplusplus >= 201103L
: unsigned char
#endif
{ e1 = 1, e255 = 255 };
bool operator==(E l, E r) { return (l % 3) == (r % 3); }
struct X { char c; };
bool operator==(X, char) { return false; }
bool operator==(char, X) { return false; }
bool operator==(E, char) { return false; }
bool operator==(char, E) { return false; }
void
test_non_characters()
{
S s[3] = { {'a'}, {'b'}, {'c'} };
S sx = {'x'};
S* sres = std::find(s, s+3, sx);
VERIFY( sres == s ); // memchr optimization would not find a match
E e[3] = { E(1), E(2), E(3) };
E* eres = std::find(e, e+3, E(4));
VERIFY( eres == e ); // memchr optimization would not find a match
char x[1] = { 'x' };
X xx = { 'x' };
char* xres = std::find(x, x+1, xx);
VERIFY( xres == x+1 ); // memchr optimization would find a match
xres = std::find(x, x+1, E('x'));
VERIFY( xres == x+1 ); // memchr optimization would find a match
#ifdef __cpp_lib_byte
std::byte b[] = { std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3} };
std::byte* bres = std::find(b, b+4, std::byte{4});
VERIFY( bres == b+4 );
bres = std::find(b, b+2, std::byte{3});
VERIFY( bres == b+2 );
bres = std::find(b, b+3, std::byte{3});
VERIFY( bres == b+3 );
#endif
#ifdef __cpp_lib_ranges
sres = std::ranges::find(s, sx);
VERIFY( sres == s );
eres = std::ranges::find(e, e+3, E(4));
VERIFY( eres == e );
// std::equality_comparable_with<X, char> is not satisfied, so can't do
// std::ranges::find(x, xx)
bres = std::ranges::find(b, std::byte{4});
VERIFY( bres == b+4 );
bres = std::ranges::find(b, b+2, std::byte{3});
VERIFY( bres == b+2 );
bres = std::ranges::find(b, std::byte{3});
VERIFY( bres == b+3 );
xres = std::find(x, x+1, xx);
VERIFY( xres == std::ranges::end(x) );
xres = std::find(x, x+1, E('x'));
VERIFY( xres == std::ranges::end(x) );
#endif
}
#if __cpp_lib_ranges
void
test_pr115799c0(__gnu_test::test_contiguous_range<char> r)
{
// Non-common range with integer-class type as difference_type.
(void) std::ranges::find(r, 'a');
}
#endif
void
test_pr115799c2(__gnu_test::input_iterator_wrapper<char> i)
{
// Non-contiguous range of character type.
(void) std::find(i, i, 'a');
}
int main()
{
test_char<char>();
test_char<signed char>();
test_char<unsigned char>();
test_non_characters();
#if __cpp_lib_constexpr_algorithms
static_assert( [] {
char c[] = "abcd";
return std::find(c, c+4, 'b') == c+1;
}() );
#ifdef __cpp_lib_ranges
static_assert( [] {
char c[] = "abcd";
return std::ranges::find(c, 'b') == c+1;
}() );
#endif
#endif
}