[libc-commits] [libc] [libc][wctype] Upstream custom slice implementation from PtrHash-cc prototype to LLVM libc (PR #174779)
Muhammad Bassiouni via libc-commits
libc-commits at lists.llvm.org
Fri Jan 9 10:27:13 PST 2026
================
@@ -0,0 +1,117 @@
+//===-- Internal utils for wctype conversion code - slice -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Similar to cpp::span with additional functionality
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_CONVERSION_UTILS_SLICE_H
+#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_CONVERSION_UTILS_SLICE_H
+
+#include "hdr/types/size_t.h"
+#include "src/__support/CPP/algorithm.h"
+#include "src/__support/CPP/expected.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/libc_assert.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace wctype_internal {
+
+namespace conversion_utils {
+
+enum class Ordering {
+ /// An ordering where a compared value is less than another.
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ Greater = 1,
+};
+
+template <typename T> struct Slice : public cpp::span<T> {
+ LIBC_INLINE constexpr Slice() : cpp::span<T>() {}
+
+ LIBC_INLINE constexpr Slice(T *ptr, size_t len) : cpp::span<T>(ptr, len) {}
+ LIBC_INLINE constexpr Slice(T const *ptr, size_t len)
+ : cpp::span<T>(ptr, len) {}
+
+ template <typename U, size_t N>
+ LIBC_INLINE constexpr Slice<U>(cpp::array<U, N> &arr) : cpp::span<T>(arr) {}
----------------
bassiounix wrote:
The template type `T` is placed over the whole class, which means when the compilers resolves type `T` to `int` for example, it has to generate a whole class with `T` equals to `int`. If another type is resolved, a new class has to be generated with this type (think `int` and `const int`).
But by adding a type to the constructor
```cc
template <typename U, size_t N>
LIBC_INLINE constexpr span(array<U, N> &arr) {}
```
This constructor is meant to allow conversion from arrays whose element type is different but compatible with `T`.
If it only used `T` (as you wrote above), you would lose that flexibility.
Also the size of the array is part of the constructor signature, so this allows to generate multiple constructor with different sizes within the same generated class scope.
Think of it as follows: any template places over a code, this code has to be generated.
(_I'm not sure of this but I think_ ...) If 2 templates are concatenated in the same scope, the compiler resolves the first one with the generated code but keeps the second template unresolved until it encounters a usage for the second template within the generated code, if the compiler can generate only a new constructor for this new type only then it would. If the types are not compatible, then it fallback to generating new code for the whole class, not only the constructor. (_We need someone from the compiler team to confirm this, this is just my reasoning of what's happening and I could be totally wrong_)
Helping the compiler be lazy and not generate much code is the goal here.
That's my understanding at least :)
https://github.com/llvm/llvm-project/pull/174779
More information about the libc-commits
mailing list