#include #include "helpers.hpp" #include #include #include #include "catch.hpp" using iter::powerset; using IntPermSet = std::multiset>; TEST_CASE("powerset: basic test, [1, 2, 3]", "[powerset]") { const std::vector ns = {1, 2, 3}; IntPermSet v; for (auto&& st : powerset(ns)) { v.emplace(std::begin(st), std::end(st)); } const IntPermSet vc = {std::multiset{}, {1}, {2}, { 3, }, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}; REQUIRE(v == vc); } TEST_CASE("powerset: empty sequence gives only empty set", "[powerset]") { const std::vector ns = {}; auto ps = powerset(ns); auto it = std::begin(ps); REQUIRE(std::begin(*it) == std::end(*it)); // it's empty ++it; REQUIRE(it == std::end(ps)); } TEST_CASE("powerset: iterators can be compared", "[powerset]") { std::vector ns = {1, 2}; auto p = powerset(ns); { auto it = std::begin(p); REQUIRE(it == std::begin(p)); REQUIRE_FALSE(it != std::begin(p)); REQUIRE(it != std::end(p)); REQUIRE_FALSE(it == std::end(p)); ++it; REQUIRE_FALSE(it == std::begin(p)); REQUIRE(it != std::begin(p)); REQUIRE_FALSE(it == std::end(p)); REQUIRE(it != std::end(p)); ++it; ++it; ++it; REQUIRE(it == std::end(p)); } ns.push_back(3); { auto it = std::begin(p); auto it2 = std::begin(p); std::advance(it, 4); std::advance(it2, 4); REQUIRE(it == it2); ++it2; REQUIRE(it != it2); } } TEST_CASE("powerset: iterator copy ctor is correct", "[powerset]") { // { {}, {1}, {2}, {1, 2} } std::vector ns = {1, 2}; auto p = powerset(ns); auto it = std::begin(p); auto it2(it); REQUIRE(it == it2); ++it2; REQUIRE(it != it2); REQUIRE(std::begin(*it) == std::end(*it)); } TEST_CASE("powerset: binds to lvalues, moves rvalues", "[powerset]") { itertest::BasicIterable bi{1, 2}; SECTION("binds to lvalues") { powerset(bi); REQUIRE_FALSE(bi.was_moved_from()); } SECTION("moves rvalues") { powerset(std::move(bi)); REQUIRE(bi.was_moved_from()); } } TEST_CASE("powerset: doesn't move or copy elements of iterable", "[powerset]") { constexpr itertest::SolidInt arr[] = {{1}, {0}, {2}}; for (auto&& st : powerset(arr)) { for (auto&& i : st) { (void)i; } } } TEST_CASE("powerset: iterator meets requirements", "[powerset]") { std::string s{"abc"}; auto c = powerset(s); REQUIRE(itertest::IsIterator::value); auto&& row = *std::begin(c); REQUIRE(itertest::IsIterator::value); } template using ImpT = decltype(powerset(std::declval())); TEST_CASE("powerset: has correct ctor and assign ops", "[powerset]") { REQUIRE(itertest::IsMoveConstructibleOnly>::value); REQUIRE(itertest::IsMoveConstructibleOnly>::value); }