Skip to content

Commit

Permalink
Reduce memory consumption of two ranges tests (#2657)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
  • Loading branch information
CaseyCarter and StephanTLavavej committed Apr 27, 2022
1 parent 9d1421d commit 314f65f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 20 deletions.
46 changes: 36 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,35 @@ 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 == 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
}
46 changes: 36 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,35 @@ 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 == 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
}

0 comments on commit 314f65f

Please sign in to comment.