#include #include "helpers.hpp" #include #include #include #include "catch.hpp" using iter::dropwhile; using Vec = const std::vector; TEST_CASE("dropwhile: skips initial elements", "[dropwhile]") { Vec ns{1, 2, 3, 4, 5, 6, 7, 8}; auto d = dropwhile([](int i) { return i < 5; }, ns); Vec v(std::begin(d), std::end(d)); Vec vc = {5, 6, 7, 8}; REQUIRE(v == vc); } TEST_CASE("dropwhile: doesn't skip anything if it shouldn't", "[dropwhile]") { Vec ns{3, 4, 5, 6}; auto d = dropwhile([](int i) { return i < 3; }, ns); Vec v(std::begin(d), std::end(d)); Vec vc = {3, 4, 5, 6}; REQUIRE(v == vc); } TEST_CASE("dropwhile: skips all elements when all are true under predicate", "[dropwhile]") { Vec ns{3, 4, 5, 6}; auto d = dropwhile([](int i) { return i != 0; }, ns); REQUIRE(std::begin(d) == std::end(d)); } TEST_CASE("dropwhile: empty case is empty", "[dropwhile]") { Vec ns{}; auto d = dropwhile([](int i) { return i != 0; }, ns); REQUIRE(std::begin(d) == std::end(d)); } TEST_CASE("dropwhile: only drops from beginning", "[dropwhile]") { Vec ns{1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1}; auto d = dropwhile([](int i) { return i < 5; }, ns); Vec v(std::begin(d), std::end(d)); Vec vc = {5, 6, 5, 4, 3, 2, 1}; REQUIRE(v == vc); } TEST_CASE("dropwhile: operator->", "[dropwhile]") { std::vector vs = {"a", "ab", "abcdef", "abcdefghi"}; auto d = dropwhile([](const std::string& str) { return str.size() < 3; }, vs); auto it = std::begin(d); REQUIRE(it->size() == 6); } namespace { int less_than_five(int i) { return i < 5; } } TEST_CASE("dropwhile: works with function pointer", "[dropwhile]") { Vec ns{1, 2, 3, 4, 5, 6, 7, 8}; auto d = dropwhile(less_than_five, ns); Vec v(std::begin(d), std::end(d)); Vec vc = {5, 6, 7, 8}; REQUIRE(v == vc); } TEST_CASE("dropwhile: binds to lvalues, moves rvalues", "[dropwhile]") { itertest::BasicIterable bi{1, 2, 3, 4}; SECTION("binds to lvalues") { dropwhile(less_than_five, bi); REQUIRE_FALSE(bi.was_moved_from()); } SECTION("moves rvalues") { dropwhile(less_than_five, std::move(bi)); REQUIRE(bi.was_moved_from()); } } TEST_CASE( "dropwhile: doesn't move or copy elements of iterable", "[dropwhile]") { constexpr itertest::SolidInt arr[] = {{6}, {7}, {8}}; for (auto&& i : dropwhile([](const itertest::SolidInt&) { return false; }, arr)) { (void)i; } } TEST_CASE("dropwhile: iterator meets requirements", "[dropwhile]") { std::string s{}; auto c = dropwhile([] { return true; }, s); REQUIRE(itertest::IsIterator::value); } template using ImpT = decltype(dropwhile(std::declval(), std::declval())); TEST_CASE("dropwhile: has correct ctor and assign ops", "[dropwhile]") { using T1 = ImpT; auto lam = [](char) { return false; }; using T2 = ImpT; REQUIRE(itertest::IsMoveConstructibleOnly::value); REQUIRE(itertest::IsMoveConstructibleOnly::value); }