ArrayView: Also accept const references when doing implicit conversions
This allows us to bind to temporaries.
Bug: none
Change-Id: Ic84ad378f344776bef38f9dc81a6fe0dee74400f
Reviewed-on: https://webrtc-review.googlesource.com/c/120901
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26530}
diff --git a/api/array_view.h b/api/array_view.h
index efc642d..bf91484 100644
--- a/api/array_view.h
+++ b/api/array_view.h
@@ -231,6 +231,12 @@
HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(U& u) // NOLINT
: ArrayView(u.data(), u.size()) {}
+ template <
+ typename U,
+ typename std::enable_if<Size == impl::kArrayViewVarSize &&
+ HasDataAndSize<U, T>::value>::type* = nullptr>
+ ArrayView(const U& u) // NOLINT(runtime/explicit)
+ : ArrayView(u.data(), u.size()) {}
// Indexing and iteration. These allow mutation even if the ArrayView is
// const, because the ArrayView doesn't own the array. (To prevent mutation,
diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc
index 694ed0b..62b51c0 100644
--- a/api/array_view_unittest.cc
+++ b/api/array_view_unittest.cc
@@ -28,16 +28,21 @@
using ::testing::IsEmpty;
template <typename T>
-void Call(ArrayView<T>) {}
+size_t Call(ArrayView<T> av) {
+ return av.size();
+}
+
+template <typename T, size_t N>
+void CallFixed(ArrayView<T, N> av) {}
} // namespace
TEST(ArrayViewTest, TestConstructFromPtrAndArray) {
char arr[] = "Arrr!";
const char carr[] = "Carrr!";
- Call<const char>(arr);
- Call<const char>(carr);
- Call<char>(arr);
+ EXPECT_EQ(6u, Call<const char>(arr));
+ EXPECT_EQ(7u, Call<const char>(carr));
+ EXPECT_EQ(6u, Call<char>(arr));
// Call<char>(carr); // Compile error, because can't drop const.
// Call<int>(arr); // Compile error, because incompatible types.
ArrayView<int*> x;
@@ -182,6 +187,8 @@
}
TEST(ArrayViewTest, TestStdArray) {
+ EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4}));
+ CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4});
constexpr size_t size = 5;
std::array<float, size> arr{};
// Fixed size view.
@@ -214,11 +221,12 @@
}
TEST(ArrayViewTest, TestStdVector) {
+ EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6}));
std::vector<int> v;
v.push_back(3);
v.push_back(11);
- Call<const int>(v);
- Call<int>(v);
+ EXPECT_EQ(2u, Call<const int>(v));
+ EXPECT_EQ(2u, Call<int>(v));
// Call<unsigned int>(v); // Compile error, because incompatible types.
ArrayView<int> x = v;
EXPECT_EQ(2u, x.size());
@@ -229,7 +237,7 @@
EXPECT_EQ(v.data(), y.data());
// ArrayView<double> d = v; // Compile error, because incompatible types.
const std::vector<int> cv;
- Call<const int>(cv);
+ EXPECT_EQ(0u, Call<const int>(cv));
// Call<int>(cv); // Compile error, because can't drop const.
ArrayView<const int> z = cv;
EXPECT_EQ(0u, z.size());
@@ -239,8 +247,8 @@
TEST(ArrayViewTest, TestRtcBuffer) {
rtc::Buffer b = "so buffer";
- Call<const uint8_t>(b);
- Call<uint8_t>(b);
+ EXPECT_EQ(10u, Call<const uint8_t>(b));
+ EXPECT_EQ(10u, Call<uint8_t>(b));
// Call<int8_t>(b); // Compile error, because incompatible types.
ArrayView<uint8_t> x = b;
EXPECT_EQ(10u, x.size());
@@ -251,7 +259,7 @@
EXPECT_EQ(b.data(), y.data());
// ArrayView<char> d = b; // Compile error, because incompatible types.
const rtc::Buffer cb = "very const";
- Call<const uint8_t>(cb);
+ EXPECT_EQ(11u, Call<const uint8_t>(cb));
// Call<uint8_t>(cb); // Compile error, because can't drop const.
ArrayView<const uint8_t> z = cb;
EXPECT_EQ(11u, z.size());