Skip to content

[libc++] Implement P4206R0 Revert string support in std::constant_wrapper#203338

Merged
yronglin merged 12 commits into
llvm:mainfrom
yronglin:p4206r0
Jun 22, 2026
Merged

[libc++] Implement P4206R0 Revert string support in std::constant_wrapper#203338
yronglin merged 12 commits into
llvm:mainfrom
yronglin:p4206r0

Conversation

@yronglin

Copy link
Copy Markdown
Contributor

Fixes #203336

@yronglin yronglin requested a review from a team as a code owner June 11, 2026 16:41
@llvmorg-github-actions llvmorg-github-actions Bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 11, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-libcxx

Author: Yihan Wang (yronglin)

Changes

Fixes #203336


Full diff: https://github.com/llvm/llvm-project/pull/203338.diff

12 Files Affected:

  • (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1)
  • (modified) libcxx/include/__utility/constant_wrapper.h (+18-32)
  • (modified) libcxx/include/utility (+2-5)
  • (modified) libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp (+2-16)
  • (removed) libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp (-32)
  • (modified) libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp (+3-12)
  • (removed) libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp (-86)
  • (removed) libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp (-70)
  • (modified) libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp (-6)
  • (added) libcxx/test/std/utilities/const.wrap.class/template.verify.cpp (+23)
  • (modified) libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp (+15-8)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (+1-1)
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 2132e80251657..c85c025ae88ab 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -216,3 +216,4 @@
 "`P4159R0 <https://wg21.link/P4159R0>`__","Make ``sender_in`` and ``receiver_of`` exposition-only","2026-03 (Croydon)","","","`#189632 <https://github.com/llvm/llvm-project/issues/189632>`__",""
 "`P4154R0 <https://wg21.link/P4154R0>`__","Renaming various execution things","2026-03 (Croydon)","","","`#189633 <https://github.com/llvm/llvm-project/issues/189633>`__",""
 "","","","","","",""
+"`P3726R2 <https://wg21.link/4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`<TBD>`__",""
diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index 6bae95fc1878a..3f490be6f8bf5 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -14,6 +14,7 @@
 #include <__functional/invoke.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_constructible.h>
+#include <__type_traits/is_same.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
@@ -27,36 +28,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 26
 
-template <class _Tp>
-struct __cw_fixed_value {
-  using __type _LIBCPP_NODEBUG = _Tp;
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(__type __v) noexcept : __data(__v) {}
-  _Tp __data;
-};
-
-template <class _Tp, size_t _Extent>
-struct __cw_fixed_value<_Tp[_Extent]> {
-  using __type _LIBCPP_NODEBUG = _Tp[_Extent];
-  _Tp __data[_Extent];
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(_Tp (&__arr)[_Extent]) noexcept
-      : __cw_fixed_value(__arr, make_index_sequence<_Extent>{}) {}
-
-private:
-  template <size_t... _Idxs>
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(_Tp (&__arr)[_Extent], index_sequence<_Idxs...>) noexcept
-      : __data{__arr[_Idxs]...} {}
-};
-
-template <class _Tp, size_t _Extent>
-__cw_fixed_value(_Tp (&)[_Extent]) -> __cw_fixed_value<_Tp[_Extent]>;
-
-template <__cw_fixed_value _Xp,
+template <auto _Xp,
 #  ifdef _LIBCPP_COMPILER_GCC
-          // gcc bug:  https://gcc.gnu.org/PR117392
-          class = typename decltype(__cw_fixed_value(_Xp))::__type
+          // gcc bug: https://gcc.gnu.org/PR117392
+          class = remove_cvref_t<decltype(_Xp)>,
 #  else
-          class = typename decltype(_Xp)::__type
+          class = decltype(_Xp)
 #  endif
           >
 struct constant_wrapper;
@@ -64,7 +41,7 @@ struct constant_wrapper;
 template <class _Tp>
 concept __constexpr_param = requires { typename constant_wrapper<_Tp::value>; };
 
-template <__cw_fixed_value _Xp>
+template <auto _Xp>
 constexpr auto cw = constant_wrapper<_Xp>{};
 
 struct __cw_operators {
@@ -288,11 +265,20 @@ concept __constexpr_indexable = (__constexpr_param<remove_cvref_t<_Args>> && ...
   typename constant_wrapper<_Obj[remove_cvref_t<_Args>::value...]>;
 };
 
-template <__cw_fixed_value _Xp, class>
+template <auto _Xp, class _Tp>
 struct constant_wrapper : __cw_operators {
-  static constexpr const auto& value = _Xp.__data;
+#  ifdef _LIB_CPP_COMPILER_GCC
+  // gcc bug: https://gcc.gnu.org/PR125188
+  static constexpr decltype((_Xp)) value = (_Xp);
+#  else
+  static constexpr decltype(auto) value = (_Xp);
+#  endif
+
   using type                         = constant_wrapper;
-  using value_type                   = decltype(_Xp)::__type;
+  using value_type                   = decltype(_Xp);
+
+  static_assert(is_same_v<_Tp, value_type>,
+                "the second template parameter of std::constant_wrapper must be its value_type");
 
   template <__constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator=(_Rp) const noexcept
diff --git a/libcxx/include/utility b/libcxx/include/utility
index e0c97efc6424d..940dc4f354984 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -196,10 +196,7 @@ template<class T1, class T2>
     constexpr const T1&& get(const pair<T2, T1>&&) noexcept; // C++14
 
 // [const.wrap.class], class template constant_wrapper
-template<class T>
-  struct cw-fixed-value;                                    // exposition only, since C++26
-
-template<cw-fixed-value X, class = typename decltype(X)::type>
+template<auto X, class = decltype(X)>
   struct constant_wrapper;                                  // since C++26
 
 template<class T>
@@ -208,7 +205,7 @@ template<class T>
 
 struct cw-operators;                                        // exposition only, since C++26
 
-template<cw-fixed-value X>
+template<auto X>
   constexpr auto cw = constant_wrapper<X>{};                // since C++26
 
 // C++14
diff --git a/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
index a9567cb08b009..f7c59401dcd2a 100644
--- a/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
@@ -27,11 +27,10 @@ constexpr bool test() {
   {
     // int conversion
     std::constant_wrapper<6> cw6;
-    const int& result = cw6;
+    int result = cw6;
     assert(result == 6);
-    assert(&result == &cw6.value);
 
-    static_assert(noexcept(static_cast<const int&>(cw6)));
+    static_assert(noexcept(static_cast<int>(cw6)));
   }
 
   {
@@ -45,19 +44,6 @@ constexpr bool test() {
     static_assert(noexcept(static_cast<const S&>(cws)));
   }
 
-  {
-    // array conversion
-    constexpr int arr[] = {1, 2, 3};
-    std::constant_wrapper<arr> cwArr;
-    const int (&result)[3] = cwArr;
-    assert(result[0] == 1);
-    assert(result[1] == 2);
-    assert(result[2] == 3);
-    assert(&result == &cwArr.value);
-
-    static_assert(noexcept(static_cast<const int (&)[3]>(cwArr)));
-  }
-
   {
     // function pointer conversion
     constexpr int (*fptr)(int) = [](int x) constexpr { return x * 2; };
diff --git a/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp
deleted file mode 100644
index 7210d7e2152d5..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// template<class T, size_t Extent>
-//   cw-fixed-value(T (&)[Extent]) -> cw-fixed-value<T[Extent]>;                   // exposition only
-
-#include <type_traits>
-#include <utility>
-
-constexpr int arr[] = {1, 2, 3};
-using T1            = std::constant_wrapper<arr>;
-static_assert(std::is_same_v<T1::value_type, const int[3]>);
-
-using T2 = std::constant_wrapper<"hello world">;
-static_assert(std::is_same_v<T2::value_type, const char[12]>);
-
-struct S {
-  int value;
-};
-
-constexpr S s[] = {{1}, {2}, {3}};
-using T3        = std::constant_wrapper<s>;
-static_assert(std::is_same_v<T3::value_type, const S[3]>);
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
index 4f660ee378239..8327076c337ec 100644
--- a/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
@@ -10,12 +10,13 @@
 
 // constant_wrapper
 
-//   template<cw-fixed-value X>
+//   template<auto X>
 //    constexpr auto cw = constant_wrapper<X>{};
 
 #include <cassert>
 #include <concepts>
 #include <utility>
+#include <cstddef>
 
 struct S {
   int value;
@@ -41,7 +42,7 @@ constexpr bool test() {
 
   {
     // array constant
-    constexpr int arr[] = {1, 2, 3};
+    constexpr static int arr[] = {1, 2, 3};
     // gcc complains that cw_val is unused
     [[maybe_unused]] std::same_as<const std::constant_wrapper<arr>> decltype(auto) cw_val = std::cw<arr>;
     static_assert(cw_val[0] == 1);
@@ -49,16 +50,6 @@ constexpr bool test() {
     static_assert(cw_val[2] == 3);
   }
 
-  {
-    // string literals
-    [[maybe_unused]] std::same_as<const std::constant_wrapper<"hello">> decltype(auto) cw_val = std::cw<"hello">;
-    static_assert(cw_val[0] == 'h');
-    static_assert(cw_val[1] == 'e');
-    static_assert(cw_val[2] == 'l');
-    static_assert(cw_val[3] == 'l');
-    static_assert(cw_val[4] == 'o');
-    static_assert(cw_val[5] == '\0');
-  }
 
   return true;
 }
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp
deleted file mode 100644
index 8bccfcfaaaa43..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// constexpr cw-fixed-value(T (&arr)[Extent]) noexcept;
-
-#include <cassert>
-#include <utility>
-
-template <auto v>
-auto helper(std::constant_wrapper<v>) -> decltype(v);
-
-template <class T>
-using cw_fixed_value = decltype(helper(std::constant_wrapper<T{}>{}));
-
-struct S {
-  int value;
-
-  constexpr S(int v = 0) : value(v) {}
-
-  constexpr bool operator==(const S& other) const { return value == other.value; }
-};
-
-constexpr bool test() {
-  {
-    // int array construction
-    // the conversion from int array to cw-fixed-value<int array> uses the constructor
-    constexpr int arr[] = {1, 2, 3};
-    std::constant_wrapper<arr> cw{};
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-  }
-
-  {
-    // struct array construction
-    constexpr S s[] = {{1}, {2}, {3}};
-    std::constant_wrapper<s> cw{};
-    assert(cw.value[0] == S{1});
-    assert(cw.value[1] == S{2});
-    assert(cw.value[2] == S{3});
-  }
-
-  {
-    // calling the constructor
-    constexpr int arr[] = {1, 2, 3, 4, 5};
-    constexpr cw_fixed_value<const int[5]> ci(arr);
-    std::constant_wrapper<ci> cw;
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-    assert(cw.value[3] == 4);
-    assert(cw.value[4] == 5);
-
-    static_assert(noexcept(cw_fixed_value<const int[5]>{arr}));
-  }
-
-  {
-    // the constructor is implicit
-    constexpr int arr[]                       = {1, 2, 3, 4, 5};
-    constexpr cw_fixed_value<const int[5]> ci = arr;
-    std::constant_wrapper<ci> cw;
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-    assert(cw.value[3] == 4);
-    assert(cw.value[4] == 5);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp
deleted file mode 100644
index 30c2952f57d4c..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// constexpr cw-fixed-value(type v) noexcept : data(v) {}
-
-#include <cassert>
-#include <utility>
-
-template <auto v>
-auto helper(std::constant_wrapper<v>) -> decltype(v);
-
-template <class T>
-using cw_fixed_value = decltype(helper(std::constant_wrapper<T{}>{}));
-
-struct S {
-  int value;
-
-  constexpr S(int v = 0) : value(v) {}
-
-  constexpr bool operator==(const S& other) const { return value == other.value; }
-};
-
-constexpr bool test() {
-  {
-    // int construction
-    // the conversion from int to cw-fixed-value<int> uses the constructor
-    std::constant_wrapper<42> cw{};
-    assert(cw.value == 42);
-  }
-
-  {
-    // struct construction
-    std::constant_wrapper<S{13}> cw{};
-    assert(cw.value == S{13});
-  }
-
-  {
-    // calling the constructor
-    constexpr cw_fixed_value<int> ci{42};
-    std::constant_wrapper<ci> cw;
-    assert(cw == 42);
-
-    static_assert(noexcept(cw_fixed_value<int>{42}));
-  }
-
-  {
-    // the constructor is implicit
-    constexpr cw_fixed_value<int> ci = 42;
-    std::constant_wrapper<ci> cw;
-    assert(cw == 42);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
index 7efefa85fed95..bfa77a4662afc 100644
--- a/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
@@ -171,12 +171,6 @@ constexpr bool test() {
     assert(result == 42);
   }
 
-  {
-    // just use the index operator
-    assert(std::cw<"abcd">[2] == 'c');
-    assert(std::cw<"abcd">[std::cw<3>] == 'd');
-  }
-
   {
     // integral_constant
     using T                                                      = std::constant_wrapper<arr>;
diff --git a/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp b/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp
new file mode 100644
index 0000000000000..f8902212299ec
--- /dev/null
+++ b/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+#include <utility>
+
+// expected-error@+1 {{pointer to subobject of string literal is not allowed in a template argument}}
+std::constant_wrapper<"hello"> string_literal;
+
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, float> wrong_type1; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1.0, int> wrong_type2; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, const int> wrong_type3; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, const int&> wrong_type4; // expected-note {{in instantiation of template class}}
diff --git a/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
index 96dce9e055209..cfaf2223875c3 100644
--- a/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
@@ -10,16 +10,15 @@
 
 // constant_wrapper
 
-// static constexpr const auto & value = X.data;
+// static constexpr decltype(auto) value = (X);
 // using type = constant_wrapper;
-// using value_type = decltype(X)::type;
+// using value_type = decltype(X);
 
-#include <algorithm>
 #include <concepts>
 #include <utility>
 
 static_assert(std::constant_wrapper<42>::value == 42);
-static_assert(std::same_as<decltype(std::constant_wrapper<42>::value), const int&>);
+static_assert(std::same_as<decltype(std::constant_wrapper<42>::value), const int>);
 static_assert(std::same_as<std::constant_wrapper<42>::type, std::constant_wrapper<42>>);
 static_assert(std::same_as<std::constant_wrapper<42>::value_type, int>);
 
@@ -32,7 +31,15 @@ static_assert(std::same_as<decltype(std::constant_wrapper<S{5}>::value), const S
 static_assert(std::same_as<std::constant_wrapper<S{5}>::type, std::constant_wrapper<S{5}>>);
 static_assert(std::same_as<std::constant_wrapper<S{5}>::value_type, S>);
 
-static_assert(std::ranges::equal(std::constant_wrapper<"abcd">::value, "abcd"));
-static_assert(std::same_as<decltype(std::constant_wrapper<"abcd">::value), const char (&)[5]>);
-static_assert(std::same_as<std::constant_wrapper<"abcd">::type, std::constant_wrapper<"abcd">>);
-static_assert(std::same_as<std::constant_wrapper<"abcd">::value_type, const char[5]>);
+template <auto V>
+consteval bool value_ref_to_template_parameter_object() {
+  return &V == &std::constant_wrapper<V>::value;
+}
+
+static_assert(value_ref_to_template_parameter_object<S{5}>());
+
+constexpr int arr[] = {1, 2, 3, 4, 5};
+
+static_assert(std::constant_wrapper<arr>::value == arr);
+static_assert(std::same_as<std::constant_wrapper<arr>::type, std::constant_wrapper<arr>>);
+static_assert(std::same_as<std::constant_wrapper<arr>::value_type, const int *>);
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index d8fb575b97b2f..64e1f1cb7f9a7 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -337,7 +337,7 @@ def add_version_header(tc):
         {
             "name": "__cpp_lib_constant_wrapper",
             "values": {
-                "c++26": 202603,
+                "c++26": 202606,
             },
             "headers": ["utility"],
         },

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

…pper

Signed-off-by: yronglin <yronglin777@gmail.com>
@yronglin

Copy link
Copy Markdown
Contributor Author

The AIX pipeline failed due to a clang bug: #202693, it's use clang-21 which not include this fix.

IBM Open XL C/C++ for AIX 17.1.4 (5725-C72, 5765-J18), version 17.1.4.1, clang version 21.1.3 (build b4e529a b4e529a6ebb9c818097b94568d8a25ab3c2c0c87)
--
  | Target: powerpc-ibm-aix7.2.0.0
  | Thread model: posix
  | InstalledDir: /opt/IBM/openxlC/17.1.4/bin
  | Build config: +assertions
  | .ibm-clang: note: diagnostic msg:
  | ********************

Comment thread libcxx/docs/Status/Cxx2cPapers.csv Outdated
Comment thread libcxx/include/__utility/constant_wrapper.h Outdated
Comment thread libcxx/include/__utility/constant_wrapper.h Outdated
Signed-off-by: yronglin <yronglin777@gmail.com>
Comment thread libcxx/include/__utility/constant_wrapper.h Outdated
yronglin added 2 commits June 12, 2026 14:29
Signed-off-by: yronglin <yronglin777@gmail.com>
Signed-off-by: yronglin <yronglin777@gmail.com>
@frederick-vs-ja

Copy link
Copy Markdown
Contributor

It doesn't seem possible to work around bug #151531 (fixed in Clang 22) for Clang 21, which is very unfortunate.

A possible resolution might be temporarily skipping this line for Clang 21:

static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);

Per https://libcxx.llvm.org/#platform-and-compiler-support, perhaps we don't need to support Clang 21 when LLVM 23 is released, but I'm not very sure. I still want to land this in LLVM 23.


template <__cw_fixed_value _Xp,
template <auto _Xp,
# ifdef _LIBCPP_COMPILER_GCC

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the original gcc bug is due to the missing CTAD conversion to cw-fixed-value. since we are removing it, I think it is very likely we don't need this branch anymore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. The first _LIBCPP_COMPILER_GCC branch can be removed. Although the second is still necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I remove all the 2 special GCC patch. But need to change decltype(auto) value = (_Xp) to decltype((_Xp)) value = (_Xp).

Signed-off-by: yronglin <yronglin777@gmail.com>
@yronglin

Copy link
Copy Markdown
Contributor Author

It doesn't seem possible to work around bug #151531 (fixed in Clang 22) for Clang 21, which is very unfortunate.

A possible resolution might be temporarily skipping this line for Clang 21:

static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);

Per https://libcxx.llvm.org/#platform-and-compiler-support, perhaps we don't need to support Clang 21 when LLVM 23 is released, but I'm not very sure. I still want to land this in LLVM 23.

Hmm, I missed this one, let me add it.

Signed-off-by: yronglin <yronglin777@gmail.com>
Comment thread libcxx/include/__utility/constant_wrapper.h Outdated
Comment thread libcxx/docs/ReleaseNotes/23.rst Outdated
Comment thread libcxx/docs/Status/Cxx2cPapers.csv Outdated
Comment thread libcxx/include/__utility/constant_wrapper.h Outdated
Comment thread libcxx/include/__utility/constant_wrapper.h
Comment thread libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
yronglin added 5 commits June 22, 2026 13:25
Signed-off-by: yronglin <yronglin777@gmail.com>
Signed-off-by: yronglin <yronglin777@gmail.com>
Signed-off-by: yronglin <yronglin777@gmail.com>
Signed-off-by: yronglin <yronglin777@gmail.com>

@frederick-vs-ja frederick-vs-ja left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits, assuming CI passes on macOS. CI failures on Windows were unrelated.

Comment thread libcxx/docs/Status/Cxx29Papers.csv Outdated
Co-authored-by: A. Jiang <de34@live.cn>
@frederick-vs-ja frederick-vs-ja added the pending-ci Merging the PR is only pending completion of CI label Jun 22, 2026
@yronglin yronglin merged commit a88b88b into llvm:main Jun 22, 2026
83 checks passed
@frederick-vs-ja frederick-vs-ja removed the pending-ci Merging the PR is only pending completion of CI label Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P4206R0: Revert string support in std::constant_wrapper

3 participants