From ff61f3a55500cd8046e614dc54b08452ff296ea6 Mon Sep 17 00:00:00 2001 From: Karl Wiberg Date: Fri, 28 Feb 2020 10:01:18 +0100 Subject: [PATCH] Fix + test copying of fixed-sized ArrayView rvalues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, only lvalues were tested, and only lvalues worked. Bug: webrtc:11389 Change-Id: I524e9d63e0840c3ba274dbe2062d78f72d79019d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/169347 Commit-Queue: Karl Wiberg Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#30644} --- api/array_view.h | 8 +++++ api/array_view_unittest.cc | 71 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/api/array_view.h b/api/array_view.h index f7130dcc37..a66369a3d3 100644 --- a/api/array_view.h +++ b/api/array_view.h @@ -213,6 +213,14 @@ class ArrayView final : public impl::ArrayViewBase { : ArrayView(u.data(), u.size()) { static_assert(U::size() == Size, "Sizes must match exactly"); } + template < + typename U, + typename std::enable_if::value>::type* = nullptr> + ArrayView(const U& u) // NOLINT(runtime/explicit) + : ArrayView(u.data(), u.size()) { + static_assert(U::size() == Size, "Sizes must match exactly"); + } // (Only if size is variable.) Construct an ArrayView from any type U that // has a size() method whose return value converts implicitly to size_t, and diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc index 06394047b0..8aa858805f 100644 --- a/api/array_view_unittest.cc +++ b/api/array_view_unittest.cc @@ -116,7 +116,7 @@ TEST(ArrayViewTest, TestCopyConstructorVariableRvalue) { // ArrayView v = std::move(z); // Error, because can't drop const. } -TEST(ArrayViewTest, TestCopyConstructorFixed) { +TEST(ArrayViewTest, TestCopyConstructorFixedLvalue) { char arr[] = "Arrr!"; ArrayView x = arr; static_assert(x.size() == 6, ""); @@ -147,6 +147,37 @@ TEST(ArrayViewTest, TestCopyConstructorFixed) { // ArrayView vv = z; // Compile error, because can't drop const. } +TEST(ArrayViewTest, TestCopyConstructorFixedRvalue) { + char arr[] = "Arrr!"; + ArrayView x = arr; + static_assert(x.size() == 6, ""); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView y = std::move(x); // Copy non-const -> non-const. + static_assert(y.size() == 6, ""); + EXPECT_EQ(arr, y.data()); + ArrayView z = std::move(x); // Copy non-const -> const. + static_assert(z.size() == 6, ""); + EXPECT_EQ(arr, z.data()); + ArrayView w = std::move(z); // Copy const -> const. + static_assert(w.size() == 6, ""); + EXPECT_EQ(arr, w.data()); + // ArrayView v = std::move(z); // Error, because can't drop const. + + // Copy fixed -> variable. + ArrayView yv = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView zv = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView wv = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView vv = std::move(z); // Error, because can't drop const. +} + TEST(ArrayViewTest, TestCopyAssignmentVariableLvalue) { char arr[] = "Arrr!"; ArrayView x(arr); @@ -189,7 +220,7 @@ TEST(ArrayViewTest, TestCopyAssignmentVariableRvalue) { // v = std::move(z); // Compile error, because can't drop const. } -TEST(ArrayViewTest, TestCopyAssignmentFixed) { +TEST(ArrayViewTest, TestCopyAssignmentFixedLvalue) { char arr[] = "Arrr!"; char init[] = "Init!"; ArrayView x(arr); @@ -225,6 +256,42 @@ TEST(ArrayViewTest, TestCopyAssignmentFixed) { // v = z; // Compile error, because can't drop const. } +TEST(ArrayViewTest, TestCopyAssignmentFixedRvalue) { + char arr[] = "Arrr!"; + char init[] = "Init!"; + ArrayView x(arr); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView y(init); + y = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(arr, y.data()); + ArrayView z(init); + z = std::move(x); // Copy non-const -> const. + EXPECT_EQ(arr, z.data()); + ArrayView w(init); + w = std::move(z); // Copy const -> const. + EXPECT_EQ(arr, w.data()); + // ArrayView v(init); + // v = std::move(z); // Compile error, because can't drop const. + + // Copy fixed -> variable. + ArrayView yv; + yv = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView zv; + zv = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView wv; + wv = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView v; + // v = std::move(z); // Compile error, because can't drop const. +} + TEST(ArrayViewTest, TestStdArray) { EXPECT_EQ(4u, Call(std::array{1, 2, 3, 4})); CallFixed(std::array{2, 3, 4});