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});