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}
This commit is contained in:
Karl Wiberg 2019-02-04 13:07:18 +01:00 committed by Commit Bot
parent ee61f9440a
commit 30abc36444
2 changed files with 24 additions and 10 deletions

View File

@ -231,6 +231,12 @@ class ArrayView final : public impl::ArrayViewBase<T, Size> {
HasDataAndSize<U, T>::value>::type* = nullptr> HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(U& u) // NOLINT ArrayView(U& u) // NOLINT
: ArrayView(u.data(), u.size()) {} : 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 // Indexing and iteration. These allow mutation even if the ArrayView is
// const, because the ArrayView doesn't own the array. (To prevent mutation, // const, because the ArrayView doesn't own the array. (To prevent mutation,

View File

@ -28,16 +28,21 @@ using ::testing::ElementsAre;
using ::testing::IsEmpty; using ::testing::IsEmpty;
template <typename T> 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 } // namespace
TEST(ArrayViewTest, TestConstructFromPtrAndArray) { TEST(ArrayViewTest, TestConstructFromPtrAndArray) {
char arr[] = "Arrr!"; char arr[] = "Arrr!";
const char carr[] = "Carrr!"; const char carr[] = "Carrr!";
Call<const char>(arr); EXPECT_EQ(6u, Call<const char>(arr));
Call<const char>(carr); EXPECT_EQ(7u, Call<const char>(carr));
Call<char>(arr); EXPECT_EQ(6u, Call<char>(arr));
// Call<char>(carr); // Compile error, because can't drop const. // Call<char>(carr); // Compile error, because can't drop const.
// Call<int>(arr); // Compile error, because incompatible types. // Call<int>(arr); // Compile error, because incompatible types.
ArrayView<int*> x; ArrayView<int*> x;
@ -182,6 +187,8 @@ TEST(ArrayViewTest, TestCopyAssignmentFixed) {
} }
TEST(ArrayViewTest, TestStdArray) { 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; constexpr size_t size = 5;
std::array<float, size> arr{}; std::array<float, size> arr{};
// Fixed size view. // Fixed size view.
@ -214,11 +221,12 @@ TEST(ArrayViewTest, TestConstStdArray) {
} }
TEST(ArrayViewTest, TestStdVector) { TEST(ArrayViewTest, TestStdVector) {
EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6}));
std::vector<int> v; std::vector<int> v;
v.push_back(3); v.push_back(3);
v.push_back(11); v.push_back(11);
Call<const int>(v); EXPECT_EQ(2u, Call<const int>(v));
Call<int>(v); EXPECT_EQ(2u, Call<int>(v));
// Call<unsigned int>(v); // Compile error, because incompatible types. // Call<unsigned int>(v); // Compile error, because incompatible types.
ArrayView<int> x = v; ArrayView<int> x = v;
EXPECT_EQ(2u, x.size()); EXPECT_EQ(2u, x.size());
@ -229,7 +237,7 @@ TEST(ArrayViewTest, TestStdVector) {
EXPECT_EQ(v.data(), y.data()); EXPECT_EQ(v.data(), y.data());
// ArrayView<double> d = v; // Compile error, because incompatible types. // ArrayView<double> d = v; // Compile error, because incompatible types.
const std::vector<int> cv; 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. // Call<int>(cv); // Compile error, because can't drop const.
ArrayView<const int> z = cv; ArrayView<const int> z = cv;
EXPECT_EQ(0u, z.size()); EXPECT_EQ(0u, z.size());
@ -239,8 +247,8 @@ TEST(ArrayViewTest, TestStdVector) {
TEST(ArrayViewTest, TestRtcBuffer) { TEST(ArrayViewTest, TestRtcBuffer) {
rtc::Buffer b = "so buffer"; rtc::Buffer b = "so buffer";
Call<const uint8_t>(b); EXPECT_EQ(10u, Call<const uint8_t>(b));
Call<uint8_t>(b); EXPECT_EQ(10u, Call<uint8_t>(b));
// Call<int8_t>(b); // Compile error, because incompatible types. // Call<int8_t>(b); // Compile error, because incompatible types.
ArrayView<uint8_t> x = b; ArrayView<uint8_t> x = b;
EXPECT_EQ(10u, x.size()); EXPECT_EQ(10u, x.size());
@ -251,7 +259,7 @@ TEST(ArrayViewTest, TestRtcBuffer) {
EXPECT_EQ(b.data(), y.data()); EXPECT_EQ(b.data(), y.data());
// ArrayView<char> d = b; // Compile error, because incompatible types. // ArrayView<char> d = b; // Compile error, because incompatible types.
const rtc::Buffer cb = "very const"; 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. // Call<uint8_t>(cb); // Compile error, because can't drop const.
ArrayView<const uint8_t> z = cb; ArrayView<const uint8_t> z = cb;
EXPECT_EQ(11u, z.size()); EXPECT_EQ(11u, z.size());