Browse Source

Merge pull request #103923 from Ivorforce/span-array-init

Add C array constructor to `Span`.
Rémi Verschelde 5 months ago
parent
commit
76c30189fa
2 changed files with 31 additions and 7 deletions
  1. 19 0
      core/templates/span.h
  2. 12 7
      tests/core/templates/test_span.h

+ 19 - 0
core/templates/span.h

@@ -43,10 +43,29 @@ class Span {
 	uint64_t _len = 0;
 	uint64_t _len = 0;
 
 
 public:
 public:
+	static constexpr bool is_string = std::disjunction_v<
+		std::is_same<T, char>,
+		std::is_same<T, char16_t>,
+		std::is_same<T, char32_t>,
+		std::is_same<T, wchar_t>
+	>;
+
 	_FORCE_INLINE_ constexpr Span() = default;
 	_FORCE_INLINE_ constexpr Span() = default;
 	_FORCE_INLINE_ constexpr Span(const T *p_ptr, uint64_t p_len) :
 	_FORCE_INLINE_ constexpr Span(const T *p_ptr, uint64_t p_len) :
 			_ptr(p_ptr), _len(p_len) {}
 			_ptr(p_ptr), _len(p_len) {}
 
 
+	// Allows creating Span directly from C arrays and string literals.
+	template <size_t N>
+	_FORCE_INLINE_ constexpr Span(const T (&p_array)[N]) :
+			_ptr(p_array), _len(N) {
+		if constexpr (is_string) {
+			// Cut off the \0 terminator implicitly added to string literals.
+			if (N > 0 && p_array[N - 1] == '\0') {
+				_len--;
+			}
+		}
+	}
+
 	_FORCE_INLINE_ constexpr uint64_t size() const { return _len; }
 	_FORCE_INLINE_ constexpr uint64_t size() const { return _len; }
 	_FORCE_INLINE_ constexpr bool is_empty() const { return _len == 0; }
 	_FORCE_INLINE_ constexpr bool is_empty() const { return _len == 0; }
 
 

+ 12 - 7
tests/core/templates/test_span.h

@@ -48,17 +48,22 @@ TEST_CASE("[Span] Constexpr Validators") {
 	static_assert(span_value.size() == 1);
 	static_assert(span_value.size() == 1);
 	static_assert(!span_value.is_empty());
 	static_assert(!span_value.is_empty());
 
 
-	constexpr static char32_t array[] = U"122345";
-	constexpr Span<char32_t> span_array(array, strlen(array));
-	static_assert(span_array.ptr() == &array[0]);
+	static constexpr int ints[] = { 0, 1, 2, 3, 4, 5 };
+	constexpr Span<int> span_array = ints;
 	static_assert(span_array.size() == 6);
 	static_assert(span_array.size() == 6);
 	static_assert(!span_array.is_empty());
 	static_assert(!span_array.is_empty());
-	static_assert(span_array[0] == U'1');
-	static_assert(span_array[span_array.size() - 1] == U'5');
+	static_assert(span_array[0] == 0);
+	static_assert(span_array[span_array.size() - 1] == 5);
+
+	constexpr Span<char32_t> span_string = U"122345";
+	static_assert(span_string.size() == 6);
+	static_assert(!span_string.is_empty());
+	static_assert(span_string[0] == U'1');
+	static_assert(span_string[span_string.size() - 1] == U'5');
 
 
 	int idx = 0;
 	int idx = 0;
-	for (const char32_t &chr : span_array) {
-		CHECK_EQ(chr, span_array[idx++]);
+	for (const char32_t &chr : span_string) {
+		CHECK_EQ(chr, span_string[idx++]);
 	}
 	}
 }
 }