Remove distinction between input/output views in fxcrt::Zip().
C++'s notion of a forwarding (universal) reference allows these
templates to bind to either rvalues or lvalues.
Change-Id: Ia75314dc5f8e9bf2c3cd41970752fd2bb17e5f60
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/127790
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/zip.h b/core/fxcrt/zip.h
index 8902f19..0610ff7 100644
--- a/core/fxcrt/zip.h
+++ b/core/fxcrt/zip.h
@@ -19,7 +19,7 @@
// Vastly simplified implementation of ideas from C++23 zip_view<>. Allows
// safe traversal of two or three ranges with a single bounds check per
// iteration.
-
+//
// Example two range usage:
// struct RGB { uint8_t r; uint8_t g; uint8_t b; };
// const uint8_t gray[256] = { ... };
@@ -31,17 +31,13 @@
// }
// which fills the first 256 elements of rgbs with the corresponding gray
// value in each component, say.
-
+//
// Differences include:
// - Only zips together two or three views instead of N.
// - Size is determined by the first view, which must be smaller than the
// other view(s).
-// - With two views, the first view is presumed to be "input-like" and is const.
-// The second view is presumed to be "output-like", can be non-const, and
-// can be assigned-to if desired.
-// - With three views, the first two views are presumed to be "input-like" and
-// are const. The third view is is presumed to be "output-like", can be
-// non-const, and can be assigned-to if desired.
+// - Views are passed as forwarding-references, so non-const views may be
+// assigned-to in the body of the loop.
// - Only those methods required to support use in a range-based for-loop
// are provided.
@@ -125,12 +121,12 @@
};
template <typename T, typename U>
-auto Zip(const T& first, U&& second) {
+auto Zip(T&& first, U&& second) {
return ZipView2(pdfium::span(first), pdfium::span(second));
}
template <typename T, typename U, typename V>
-auto Zip(const T& first, const U& second, V&& third) {
+auto Zip(T&& first, U&& second, V&& third) {
return ZipView3(pdfium::span(first), pdfium::span(second),
pdfium::span(third));
}
diff --git a/core/fxcrt/zip_unittest.cpp b/core/fxcrt/zip_unittest.cpp
index 09a2891..211fd8d 100644
--- a/core/fxcrt/zip_unittest.cpp
+++ b/core/fxcrt/zip_unittest.cpp
@@ -37,16 +37,22 @@
TEST(Zip, ActualZip) {
const int stuff[] = {1, 2, 3};
const int expected[] = {1, 2, 3, 0};
- int output[4] = {};
-
- for (auto [in, out] : Zip(stuff, output)) {
- out = in;
+ {
+ int output[4] = {};
+ for (auto [in, out] : Zip(stuff, output)) {
+ out = in;
+ }
+ EXPECT_THAT(output, ElementsAreArray(expected));
}
- EXPECT_THAT(output, ElementsAreArray(expected));
-
- // The "output" span can, in fact, be const so long as we don't assign to it.
- for (auto [in, expect] : Zip(stuff, expected)) {
- EXPECT_EQ(in, expect);
+ {
+ // Test that ordering of args doesn't matter, except for the size
+ // determination.
+ int output[4] = {};
+ auto sub_output = pdfium::make_span(output).first(3);
+ for (auto [out, in] : Zip(sub_output, stuff)) {
+ out = in;
+ }
+ EXPECT_THAT(output, ElementsAreArray(expected));
}
}
@@ -54,16 +60,30 @@
const int stuff1[] = {1, 2, 3};
const int stuff2[] = {4, 5, 6};
const int expected[] = {5, 7, 9, 0};
- int output[4] = {};
-
- for (auto [in1, in2, out] : Zip(stuff1, stuff2, output)) {
- out = in1 + in2;
+ {
+ int output[4] = {};
+ for (auto [in1, in2, out] : Zip(stuff1, stuff2, output)) {
+ out = in1 + in2;
+ }
+ EXPECT_THAT(output, ElementsAreArray(expected));
}
- EXPECT_THAT(output, ElementsAreArray(expected));
-
- // The "output" span can, in fact, be const so long as we don't assign to it.
- for (auto [in1, in2, expect] : Zip(stuff1, stuff2, output)) {
- EXPECT_EQ(in1 + in2, expect);
+ {
+ // Test that ordering of args doesn't matter.
+ int output[4] = {};
+ for (auto [in1, out, in2] : Zip(stuff1, output, stuff2)) {
+ out = in1 + in2;
+ }
+ EXPECT_THAT(output, ElementsAreArray(expected));
+ }
+ {
+ // Test that ordering of args doesn't matter, except for the size
+ // determination.
+ int output[4] = {};
+ auto sub_output = pdfium::make_span(output).first(3);
+ for (auto [out, in1, in2] : Zip(sub_output, stuff1, stuff2)) {
+ out = in1 + in2;
+ }
+ EXPECT_THAT(output, ElementsAreArray(expected));
}
}