|
5 | 5 | #include <catch2/catch_template_test_macros.hpp> |
6 | 6 | #include <catch2/catch_test_macros.hpp> |
7 | 7 |
|
| 8 | +#include <algorithm> |
8 | 9 | #include <array> |
9 | 10 | #include <functional> |
10 | 11 | #include <type_traits> |
@@ -77,19 +78,82 @@ TEST_CASE("apply", "[tuple_algorithms]") { |
77 | 78 | stdx::tuple{}) == 0); |
78 | 79 | static_assert(stdx::apply([](auto... xs) { return (0 + ... + xs); }, |
79 | 80 | stdx::tuple{1, 2, 3}) == 6); |
| 81 | +} |
80 | 82 |
|
| 83 | +TEST_CASE("apply handles a stateful function properly", "[tuple_algorithms]") { |
81 | 84 | auto stateful = [calls = 0](auto...) mutable { return ++calls; }; |
82 | 85 | CHECK(stdx::apply(stateful, stdx::tuple{1, 2, 3}) == 1); |
83 | 86 | CHECK(stdx::apply(stateful, stdx::tuple{1, 2, 3}) == 2); |
| 87 | +} |
84 | 88 |
|
| 89 | +TEST_CASE("apply handles move-only types", "[tuple_algorithms]") { |
85 | 90 | static_assert(stdx::apply([](auto x) { return x.value; }, |
86 | 91 | stdx::tuple{move_only{42}}) == 42); |
| 92 | +} |
87 | 93 |
|
| 94 | +TEST_CASE("apply handles tuples of references", "[tuple_algorithms]") { |
88 | 95 | auto t = stdx::tuple{1, 2, 3}; |
89 | 96 | stdx::apply([](auto &...xs) { (++xs, ...); }, t); |
90 | 97 | CHECK(t == stdx::tuple{2, 3, 4}); |
91 | 98 | } |
92 | 99 |
|
| 100 | +TEST_CASE("apply preserves argument order", "[tuple_algorithms]") { |
| 101 | + int called{}; |
| 102 | + stdx::apply( |
| 103 | + [&](auto... xs) { |
| 104 | + ++called; |
| 105 | + auto const a = std::array{xs...}; |
| 106 | + CHECK(std::is_sorted(std::begin(a), std::end(a))); |
| 107 | + }, |
| 108 | + stdx::tuple{1, 2, 3}); |
| 109 | + CHECK(called == 1); |
| 110 | +} |
| 111 | + |
| 112 | +TEST_CASE("variadic apply", "[tuple_algorithms]") { |
| 113 | + static_assert(stdx::apply([](auto... xs) { return (0 + ... + xs); }) == 0); |
| 114 | + static_assert(stdx::apply([](auto... xs) { return (0 + ... + xs); }, |
| 115 | + stdx::tuple{1, 2, 3}, |
| 116 | + stdx::tuple{4, 5, 6}) == 21); |
| 117 | +} |
| 118 | + |
| 119 | +TEST_CASE("variadic apply handles a stateful function properly", |
| 120 | + "[tuple_algorithms]") { |
| 121 | + auto stateful = [calls = 0](auto...) mutable { return ++calls; }; |
| 122 | + CHECK(stdx::apply(stateful) == 1); |
| 123 | + CHECK(stdx::apply(stateful) == 2); |
| 124 | +} |
| 125 | + |
| 126 | +TEST_CASE("variadic apply handles move-only types", "[tuple_algorithms]") { |
| 127 | + static_assert(stdx::apply([](auto x, auto y) { return x.value + y.value; }, |
| 128 | + stdx::tuple{move_only{42}}, |
| 129 | + stdx::tuple{move_only{17}}) == 59); |
| 130 | +} |
| 131 | + |
| 132 | +TEST_CASE("variadic apply handles tuples of references", "[tuple_algorithms]") { |
| 133 | + auto t1 = stdx::tuple{1}; |
| 134 | + auto t2 = stdx::tuple{2}; |
| 135 | + stdx::apply( |
| 136 | + [](auto &x1, auto &x2) { |
| 137 | + x1 += x2; |
| 138 | + x2 *= 2; |
| 139 | + }, |
| 140 | + t1, t2); |
| 141 | + CHECK(t1 == stdx::tuple{3}); |
| 142 | + CHECK(t2 == stdx::tuple{4}); |
| 143 | +} |
| 144 | + |
| 145 | +TEST_CASE("variadic apply preserves argument order", "[tuple_algorithms]") { |
| 146 | + int called{}; |
| 147 | + stdx::apply( |
| 148 | + [&](auto... xs) { |
| 149 | + ++called; |
| 150 | + auto const a = std::array{xs...}; |
| 151 | + CHECK(std::is_sorted(std::begin(a), std::end(a))); |
| 152 | + }, |
| 153 | + stdx::tuple{1, 2, 3}, stdx::tuple{4, 5, 6}); |
| 154 | + CHECK(called == 1); |
| 155 | +} |
| 156 | + |
93 | 157 | TEST_CASE("join", "[tuple_algorithms]") { |
94 | 158 | constexpr auto t = stdx::tuple{1, 2, 3}; |
95 | 159 | static_assert(t.join(std::plus{}) == 6); |
|
0 commit comments