Allow SkSpan(data, size) ctor to accept any integral-typed size.
We can reduce the boilerplate casts needed in the code by allowing
SkSpan to take any integral type here, not just size_t.
Change-Id: I3a34b8d21d83ae00af7a8e7af31a65e1f1f31b03
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/601321
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
diff --git a/include/core/SkSpan.h b/include/core/SkSpan.h
index 4e4d02c..ad8f126 100644
--- a/include/core/SkSpan.h
+++ b/include/core/SkSpan.h
@@ -9,6 +9,7 @@
#define SkSpan_DEFINED
#include "include/core/SkTypes.h"
+#include "include/private/SkTo.h"
#include <cstddef>
#include <initializer_list>
@@ -63,9 +64,11 @@
class SkSpan {
public:
constexpr SkSpan() : fPtr{nullptr}, fSize{0} {}
- constexpr SkSpan(T* ptr, size_t size) : fPtr{ptr}, fSize{size} {
- SkASSERT(ptr || size == 0); // disallow nullptr + a nonzero size
- SkASSERT(size < kMaxSize);
+
+ template <typename Integer, std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
+ constexpr SkSpan(T* ptr, Integer size) : fPtr{ptr}, fSize{SkToSizeT(size)} {
+ SkASSERT(ptr || fSize == 0); // disallow nullptr + a nonzero size
+ SkASSERT(fSize < kMaxSize);
}
template <typename U, typename = typename std::enable_if<std::is_same<const U, T>::value>::type>
constexpr SkSpan(const SkSpan<U>& that) : fPtr(std::data(that)), fSize{std::size(that)} {}
diff --git a/tests/SkSpanTest.cpp b/tests/SkSpanTest.cpp
index 63b4851..196eadd 100644
--- a/tests/SkSpanTest.cpp
+++ b/tests/SkSpanTest.cpp
@@ -7,7 +7,10 @@
#include "include/core/SkSpan.h"
#include "tests/Test.h"
+
#include <array>
+#include <cstddef>
+#include <cstdint>
#include <vector>
DEF_TEST(SkSpanBasicTemplateGuide, reporter) {
@@ -96,3 +99,32 @@
REPORTER_ASSERT(reporter, test_span_parameter(s));
}
}
+
+DEF_TEST(SkSpanDeduceSize, reporter) {
+ int d[] = {1, 2, 3, 4, 5};
+ {
+ int s = std::size(d);
+ SkSpan span = SkSpan{d, s};
+ REPORTER_ASSERT(reporter, span.size() == std::size(d));
+ }
+ {
+ uint32_t s = std::size(d);
+ SkSpan span = SkSpan{d, s};
+ REPORTER_ASSERT(reporter, span.size() == std::size(d));
+ }
+ {
+ size_t s = std::size(d);
+ SkSpan span = SkSpan{d, s};
+ REPORTER_ASSERT(reporter, span.size() == std::size(d));
+ }
+ {
+ struct C {
+ int* data() { return nullptr; }
+ int size() const { return 0; }
+ };
+
+ C c;
+ SkSpan span = SkSpan(c);
+ REPORTER_ASSERT(reporter, span.size() == 0);
+ }
+}