[libcxx-commits] [libcxx] [libcxx][string] Allow fancy pointers in basic_string (PR #199264)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 5 02:30:36 PDT 2026


================
@@ -878,16 +880,91 @@ private:
 
   static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
 
-  union __rep {
+  template <typename _LongT, typename = void>
+  union __rep_t {
     __short __s;
-    __long __l;
+    _LongT __l;
 
-    __rep() = default;
-    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(__short __r) : __s(__r) {}
-    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(__long __r) : __l(__r) {}
-    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(__uninitialized_tag) {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_long_lifetime() {}
+
+    __rep_t() = default;
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(__short __r) : __s(__r) {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(_LongT __r) : __l(__r) {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(__uninitialized_tag) {}
   };
 
+  template <typename _LongT>
+  union __rep_t<_LongT,
+                typename std::enable_if<!is_trivially_constructible<_LongT>::value ||
+                                        !is_trivially_copy_assignable<_LongT>::value ||
+                                        !is_trivially_destructible<_LongT>::value >::type> {
+    __short __s;
+    _LongT __l;
+
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_long() const _NOEXCEPT {
+      if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__l.__is_long_)) {
+        return __l.__is_long_;
+      }
+      return __s.__is_long_;
+    }
+
+    // If __long is not trivially constructible (this occurs if the pointer type inside __long is not trivially
+    // constructible) then the lifetime of __l must be explicitly started with std::__construct_at before it can be
+    // assigned to. If __long is trivially constructible, then the lifetime of __l can be implicitly started with a
+    // simple assignment and therefore does not need to be explicitly initialised here.
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_long_lifetime() {
+      if _LIBCPP_CONSTEXPR (!__is_trivially_constructible(_LongT)) {
+        std::__construct_at(std::addressof(__l));
+      }
+    }
+
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t() : __s() {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(__short __r) : __s(__r) {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(_LongT __r) : __l(__r) {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(__uninitialized_tag) : __s() {}
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep_t(const __rep_t& __other) {
----------------
frederick-vs-ja wrote:

Do we want make these special member functions non-`noexcept`?

https://github.com/llvm/llvm-project/pull/199264


More information about the libcxx-commits mailing list