Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce memory consumption of two ranges tests #2657

Merged
merged 3 commits into from Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 37 additions & 10 deletions tests/std/tests/P0896R4_ranges_alg_remove_copy/test.cpp
Expand Up @@ -20,6 +20,15 @@ STATIC_ASSERT(same_as<decltype(ranges::remove_copy(borrowed<false>{}, static_cas
STATIC_ASSERT(same_as<decltype(ranges::remove_copy(borrowed<true>{}, static_cast<int*>(nullptr), 42)),
ranges::remove_copy_result<int*, int*>>);

struct counted_projection {
size_t& counter;

constexpr auto operator()(const P& val) const noexcept(is_nothrow_copy_constructible_v<decltype(P::second)>) {
++counter;
return val.second;
}
};

struct instantiator {
static constexpr P input[5] = {{0, 99}, {1, 47}, {2, 99}, {3, 47}, {4, 99}};
static constexpr P expected[3] = {{0, 99}, {2, 99}, {4, 99}};
Expand All @@ -33,11 +42,8 @@ struct instantiator {
if constexpr (non_proxy || !is_permissive) {
using ranges::remove_copy, ranges::remove_copy_result, ranges::equal, ranges::iterator_t;

size_t projectionCounter = 0;
auto projection = [&projectionCounter](const P& val) {
++projectionCounter;
return val.second;
};
size_t counter = 0;
counted_projection projection{counter};

{ // Validate iterator + sentinel overload
P output[3] = {{-1, -1}, {-1, -1}, {-1, -1}};
Expand All @@ -48,10 +54,10 @@ struct instantiator {
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected));
assert(projectionCounter == ranges::size(input));
assert(counter == ranges::size(input));
}

projectionCounter = 0;
counter = 0;

{ // Validate range overload
P output[3] = {{-1, -1}, {-1, -1}, {-1, -1}};
Expand All @@ -62,15 +68,36 @@ struct instantiator {
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected));
assert(projectionCounter == ranges::size(input));
assert(counter == ranges::size(input));
}
}
}
};

using test::Common, test::Sized;

template <class Category, Sized IsSized, Common IsCommon>
using test_range =
test::range<Category, const P, IsSized, test::CanDifference{derived_from<Category, random_access_iterator_tag>},
IsCommon, test::CanCompare{derived_from<Category, forward_iterator_tag> || IsCommon == test::Common::yes},
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
test::ProxyRef::no>;

int main() {
#ifndef _PREFAST_ // TRANSITION, GH-1030
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
#ifdef TEST_EVERYTHING
STATIC_ASSERT((test_in_write<instantiator, const P, P>(), true));
#endif // TRANSITION, GH-1030
test_in_write<instantiator, const P, P>();
#else // ^^^ test all input range permutations / test only "interesting" permutations vvv
// The algorithm is insensitive to _every_ range property; it's simply a conditional copy.
// Let's test a range of each category for basic coverage, and a contiguous+sized range just in
// case some ambitious contributor tries to vectorize some day.

using out =
test::iterator<output_iterator_tag, P, test::CanDifference::no, test::CanCompare::no, test::ProxyRef::no>;

instantiator::call<test_range<input_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<forward_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<bidirectional_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<random_access_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<contiguous_iterator_tag, Sized::yes, Common::yes>, out>();
#endif // TEST_EVERYTHING
}
47 changes: 37 additions & 10 deletions tests/std/tests/P0896R4_ranges_alg_remove_copy_if/test.cpp
Expand Up @@ -22,6 +22,15 @@ STATIC_ASSERT(same_as<decltype(ranges::remove_copy_if(borrowed<false>{}, static_
STATIC_ASSERT(same_as<decltype(ranges::remove_copy_if(borrowed<true>{}, static_cast<int*>(nullptr), matches)),
ranges::remove_copy_if_result<int*, int*>>);

struct counted_projection {
size_t& counter;

constexpr auto operator()(const P& val) const noexcept(is_nothrow_copy_constructible_v<decltype(P::second)>) {
++counter;
return val.second;
}
};

struct instantiator {
static constexpr P input[5] = {{0, 99}, {1, 47}, {2, 99}, {3, 47}, {4, 99}};
static constexpr P expected[3] = {{0, 99}, {2, 99}, {4, 99}};
Expand All @@ -35,11 +44,8 @@ struct instantiator {
if constexpr (non_proxy || !is_permissive) {
using ranges::remove_copy_if, ranges::remove_copy_if_result, ranges::equal, ranges::iterator_t;

size_t projectionCounter = 0;
auto projection = [&projectionCounter](const P& val) {
++projectionCounter;
return val.second;
};
size_t counter = 0;
counted_projection projection{counter};

{ // Validate iterator + sentinel overload
P output[3] = {{-1, -1}, {-1, -1}, {-1, -1}};
Expand All @@ -50,10 +56,10 @@ struct instantiator {
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected));
assert(projectionCounter == ranges::size(input));
assert(counter == ranges::size(input));
}

projectionCounter = 0;
counter = 0;

{ // Validate range overload
P output[3] = {{-1, -1}, {-1, -1}, {-1, -1}};
Expand All @@ -63,15 +69,36 @@ struct instantiator {
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected));
assert(projectionCounter == ranges::size(input));
assert(counter == ranges::size(input));
}
}
}
};

using test::Common, test::Sized;

template <class Category, Sized IsSized, Common IsCommon>
using test_range =
test::range<Category, const P, IsSized, test::CanDifference{derived_from<Category, random_access_iterator_tag>},
IsCommon, test::CanCompare{derived_from<Category, forward_iterator_tag> || IsCommon == test::Common::yes},
test::ProxyRef::no>;

int main() {
#ifndef _PREFAST_ // TRANSITION, GH-1030
#ifdef TEST_EVERYTHING
STATIC_ASSERT((test_in_write<instantiator, const P, P>(), true));
#endif // TRANSITION, GH-1030
test_in_write<instantiator, const P, P>();
#else // ^^^ test all input range permutations / test only "interesting" permutations vvv
// The algorithm is insensitive to _every_ range property; it's simply a conditional copy.
// Let's test a range of each category for basic coverage, and a contiguous+sized range just in
// case some ambitious contributor tries to vectorize some day.

using out =
test::iterator<output_iterator_tag, P, test::CanDifference::no, test::CanCompare::no, test::ProxyRef::no>;

instantiator::call<test_range<input_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<forward_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<bidirectional_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<random_access_iterator_tag, Sized::no, Common::no>, out>();
instantiator::call<test_range<contiguous_iterator_tag, Sized::yes, Common::yes>, out>();
#endif // TEST_EVERYTHING
}