diff --git a/src/core/include/units/magnitude.h b/src/core/include/units/magnitude.h index 9e73fd20..09343c86 100644 --- a/src/core/include/units/magnitude.h +++ b/src/core/include/units/magnitude.h @@ -176,23 +176,31 @@ constexpr auto pi_to_the() { return magnitude()>{}; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Magnitude concept implementation. -template -constexpr bool pairwise_all(const std::tuple &ts, const Predicate &pred) { - // Carefully handle different sizes, avoiding unsigned integer underflow. - constexpr auto num_comparisons = [](auto num_elements) { - return (num_elements > 1) ? (num_elements - 1) : 0; - }(sizeof...(Ts)); +template +struct pairwise_all { + Predicate predicate; - // Compare zero or more pairs of neighbours as needed. - return [&ts, &pred](std::integer_sequence) { - return (pred(std::get(ts), std::get(ts)) && ...); - }(std::make_index_sequence()); -} + template + constexpr bool operator()(Ts&&... ts) const { + // Carefully handle different sizes, avoiding unsigned integer underflow. + constexpr auto num_comparisons = [](auto num_elements) { + return (num_elements > 1) ? (num_elements - 1) : 0; + }(sizeof...(Ts)); + + // Compare zero or more pairs of neighbours as needed. + return [this](std::tuple &&t, std::index_sequence) { + return (predicate(std::get(t), std::get(t)) && ...); + }(std::make_tuple(std::forward(ts)...), std::make_index_sequence()); + } +}; + +template +pairwise_all(T) -> pairwise_all; // Check whether a tuple of (possibly heterogeneously typed) values are strictly increasing. template -constexpr bool strictly_increasing(const std::tuple &ts) { - return pairwise_all(ts, std::less{}); +constexpr bool strictly_increasing(Ts&&... ts) { + return pairwise_all{std::less{}}(std::forward(ts)...); } namespace detail diff --git a/test/unit_test/runtime/magnitude_test.cpp b/test/unit_test/runtime/magnitude_test.cpp index 9cd54835..ff66d952 100644 --- a/test/unit_test/runtime/magnitude_test.cpp +++ b/test/unit_test/runtime/magnitude_test.cpp @@ -30,23 +30,23 @@ namespace units::mag TEST_CASE("strictly_increasing") { - SECTION ("Empty tuple is sorted") + SECTION ("Empty input is sorted") { - CHECK(strictly_increasing(std::make_tuple())); + CHECK(strictly_increasing()); } - SECTION ("Single-element tuple is sorted") + SECTION ("Single-element input is sorted") { - CHECK(strictly_increasing(std::make_tuple(3))); - CHECK(strictly_increasing(std::make_tuple(15.42))); - CHECK(strictly_increasing(std::make_tuple('c'))); + CHECK(strictly_increasing(3)); + CHECK(strictly_increasing(15.42)); + CHECK(strictly_increasing('c')); } - SECTION ("Multi-element tuples compare correctly") + SECTION ("Multi-value inputs compare correctly") { - CHECK(strictly_increasing(std::make_tuple(3, 3.14))); - CHECK(!strictly_increasing(std::make_tuple(3, 3.0))); - CHECK(!strictly_increasing(std::make_tuple(4, 3.0))); + CHECK(strictly_increasing(3, 3.14)); + CHECK(!strictly_increasing(3, 3.0)); + CHECK(!strictly_increasing(4, 3.0)); } } @@ -94,9 +94,6 @@ TEST_CASE("strictly_increasing") // } // } -template -using double_v = 2 * x; - TEST_CASE("Multiplication works for magnitudes") { SECTION("Reciprocals reduce to null magnitude") @@ -107,7 +104,6 @@ TEST_CASE("Multiplication works for magnitudes") SECTION("Products work as expected") { CHECK(make_ratio<4, 5>() * make_ratio<4, 3>() == make_ratio<16, 15>()); - CHECK(double_v<1.5> == 3.0); } //SECTION("Products handle pi correctly") @@ -205,23 +201,23 @@ TEST_CASE("pairwise_all evaluates all pairs") { SECTION("always true for empty tuples") { - CHECK(pairwise_all(std::make_tuple(), [](auto, auto){ return true; })); - CHECK(pairwise_all(std::make_tuple(), [](auto, auto){ return false; })); + CHECK(pairwise_all{[](auto, auto){ return true; }}()); + CHECK(pairwise_all{[](auto, auto){ return false; }}()); } SECTION("always true for single-element tuples") { - CHECK(pairwise_all(std::make_tuple(1), [](auto, auto){ return true; })); - CHECK(pairwise_all(std::make_tuple(3.14), [](auto, auto){ return false; })); - CHECK(pairwise_all(std::make_tuple('x'), [](auto, auto){ return true; })); + CHECK(pairwise_all{[](auto, auto){ return true; }}(1)); + CHECK(pairwise_all{[](auto, auto){ return false; }}(3.14)); + CHECK(pairwise_all{[](auto, auto){ return true; }}('x')); } SECTION("true for longer tuples iff true for all neighbouring pairs") { - CHECK(pairwise_all(std::make_tuple(1, 1.5), std::less{})); - CHECK(pairwise_all(std::make_tuple(1, 1.5, 2), std::less{})); - CHECK(!pairwise_all(std::make_tuple(1, 2.0, 2), std::less{})); - CHECK(!pairwise_all(std::make_tuple(1, 2.5, 2), std::less{})); + CHECK(pairwise_all{std::less{}}(1, 1.5)); + CHECK(pairwise_all{std::less{}}(1, 1.5, 2)); + CHECK(!pairwise_all{std::less{}}(1, 2.0, 2)); + CHECK(!pairwise_all{std::less{}}(1, 2.5, 2)); } }