#include "../tap.hpp" #include "../iterator/counting.hpp" #include "../iterator/dereference.hpp" #include "../iterator/iota.hpp" #include "../iterator/zip.hpp" #include #include #include /////////////////////////////////////////////////////////////////////////////// static void test_counting_output_iterator (cruft::TAP::logger &tap) { { cruft::iterator::counting_output_iterator out; *out = 0; ++out; *out = 1; ++out; *out = 2; ++out; tap.expect_eq (out.count (), 3u, "counting_output_iterator simple manual assignment"); } { std::vector numbers (100); std::iota (std::begin (numbers), std::end (numbers), 0); cruft::iterator::counting_output_iterator out; std::copy (std::begin (numbers), std::end (numbers), out); tap.expect_eq (out.count (), 100u, "counting_output_iterator, std::copy over a vector"); } } //----------------------------------------------------------------------------- static void test_dereference_iterator (cruft::TAP::logger &tap) { int values[4] { 0, 1, 2, 3 }; int const* pointers[4] = { values + 0, values + 1, values + 2, values + 3 }; auto const sum = std::accumulate ( cruft::iterator::dereference_adapter (std::cbegin (pointers)), cruft::iterator::dereference_adapter (std::cend (pointers)), 0 ); tap.expect_eq (sum, 6, "dereference_adapter used in accumulate"); } //----------------------------------------------------------------------------- static void test_iota (cruft::TAP::logger &tap) { cruft::iterator::iota seq (5); auto const sum = std::accumulate (std::begin (seq), std::end (seq), 0u); tap.expect_eq (sum, 4u+3u+2u+1u+0u, "iota summation {}", sum); } /////////////////////////////////////////////////////////////////////////////// int main (int, char**) { cruft::TAP::logger tap; // test that iteration across disparate types works as expected. // // the char array is an important element because it tends to decay to a // pointer type unless we're paying careful attention. { std::vector v_int { 1, 2, 3 }; std::array a_float { 1.1f, 2.2f, 3.3f }; char c_char[] = { '\0', 'b', 'c' }; bool success = true; for (auto const [i, v, a, c]: cruft::iterator::izip (v_int, a_float, c_char)) { success = success && v_int[i] == v && cruft::equal (a_float[i], a) && c_char[i] == c; } tap.expect (success, "izip containers of int, float, and char and an initialiser_list"); } // test that the obvious structured binding syntax gives references to // the underlying values rather than silently supplying lvalues. // // we deliberately do not use any type of references in the range loop so // that we check the syntax a user is likely to employ actually works. // references may not be an obvious consideration. { const std::array src { 0, 1, 2 }; std::array dst { 2, 0, 1 }; for (auto [a,b]: cruft::iterator::zip (src, dst)) b = a; tap.expect_eq (src, dst, "copy using structured bindings"); } test_counting_output_iterator (tap); test_dereference_iterator (tap); test_iota (tap); return tap.status (); }