[libcxx-commits] [libcxx] [libcxx] Implement `std::constant_wrapper` (PR #191695)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 13 05:43:32 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Hui (huixie90)

<details>
<summary>Changes</summary>

Fixes #<!-- -->148179
Fixes #<!-- -->189605
Fixes #<!-- -->189865
Fixes #<!-- -->171370
Fixes #<!-- -->189856

---

Patch is 144.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191695.diff


32 Files Affected:

- (modified) libcxx/docs/FeatureTestMacroTable.rst (+2) 
- (modified) libcxx/docs/ReleaseNotes/23.rst (+2) 
- (modified) libcxx/docs/Status/Cxx2cIssues.csv (+3-3) 
- (modified) libcxx/docs/Status/Cxx2cPapers.csv (+2-2) 
- (modified) libcxx/include/CMakeLists.txt (+1) 
- (added) libcxx/include/__utility/constant_wrapper.h (+335) 
- (modified) libcxx/include/module.modulemap.in (+1) 
- (modified) libcxx/include/span (+1-1) 
- (modified) libcxx/include/utility (+17) 
- (modified) libcxx/include/version (+2) 
- (modified) libcxx/test/std/containers/views/views.span/span.cons/deduct.pass.cpp (+8) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp (+27) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+27) 
- (added) libcxx/test/std/utilities/const.wrap.class/adl.pass.cpp (+54) 
- (added) libcxx/test/std/utilities/const.wrap.class/assign.pass.cpp (+86) 
- (added) libcxx/test/std/utilities/const.wrap.class/binary_ops.pass.cpp (+590) 
- (added) libcxx/test/std/utilities/const.wrap.class/call.pass.cpp (+239) 
- (added) libcxx/test/std/utilities/const.wrap.class/comma.pass.cpp (+66) 
- (added) libcxx/test/std/utilities/const.wrap.class/comp.pass.cpp (+424) 
- (added) libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp (+90) 
- (added) libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp (+37) 
- (added) libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp (+74) 
- (added) libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp (+91) 
- (added) libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp (+75) 
- (added) libcxx/test/std/utilities/const.wrap.class/general.pass.cpp (+47) 
- (added) libcxx/test/std/utilities/const.wrap.class/helpers.h (+23) 
- (added) libcxx/test/std/utilities/const.wrap.class/mem_ptr.pass.cpp (+116) 
- (added) libcxx/test/std/utilities/const.wrap.class/pseudo_mutators.pass.cpp (+427) 
- (added) libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp (+187) 
- (added) libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp (+40) 
- (added) libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp (+249) 
- (modified) libcxx/utils/generate_feature_test_macro_components.py (+7) 


``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 0f65770a4fa14..cbe55ffddb93b 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -426,6 +426,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_bitset``                                       ``202306L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_constant_wrapper``                             ``202603L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_algorithms``                         ``202306L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_flat_map``                           ``202502L``
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index aeabfeedfbc5e..13cf86eb25621 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -39,6 +39,8 @@ Implemented Papers
 ------------------
 
 - P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github <https://llvm.org/PR105184>`__)
+- P2781R9: ``std::constant_wrapper`` (`Github <https://llvm.org/PR148179>`__)
+- P3978R3: ``constant_wrapper`` should unwrap on call and subscript (`Github <https://llvm.org/PR189605>`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index e17992f899b3b..d130e643658d5 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -209,7 +209,7 @@
 "`LWG4376 <https://wg21.link/LWG4376>`__","ABI tag in return type of [simd.mask.unary] is overconstrained","2025-11 (Kona)","","","`#171367 <https://github.com/llvm/llvm-project/issues/171367>`__",""
 "`LWG4377 <https://wg21.link/LWG4377>`__","Misleading note about lock-free property of ``std::atomic_ref``","2025-11 (Kona)","","","`#171368 <https://github.com/llvm/llvm-project/issues/171368>`__",""
 "`LWG4382 <https://wg21.link/LWG4382>`__","The ``simd::basic_mask(bool)`` overload needs to be more constrained","2025-11 (Kona)","","","`#171369 <https://github.com/llvm/llvm-project/issues/171369>`__",""
-"`LWG4383 <https://wg21.link/LWG4383>`__","``constant_wrapper``\'s pseudo-mutators are underconstrained","2025-11 (Kona)","","","`#171370 <https://github.com/llvm/llvm-project/issues/171370>`__",""
+"`LWG4383 <https://wg21.link/LWG4383>`__","``constant_wrapper``\'s pseudo-mutators are underconstrained","2025-11 (Kona)","|Complete|","23","`#171370 <https://github.com/llvm/llvm-project/issues/171370>`__",""
 "`LWG4384 <https://wg21.link/LWG4384>`__","``flat_set::erase(iterator)`` is underconstrained","2025-11 (Kona)","","","`#171371 <https://github.com/llvm/llvm-project/issues/171371>`__",""
 "`LWG4388 <https://wg21.link/LWG4388>`__","Align new definition of ``va_start`` with C23","2025-11 (Kona)","","","`#171372 <https://github.com/llvm/llvm-project/issues/171372>`__",""
 "`LWG4396 <https://wg21.link/LWG4396>`__","Improve ``inplace_vector(from_range_t, R&& rg)``","2025-11 (Kona)","","","`#171373 <https://github.com/llvm/llvm-project/issues/171373>`__",""
@@ -311,7 +311,7 @@
 "`LWG4496 <https://wg21.link/LWG4496>`__","Precedes vs Reachable in [meta.reflection]","2026-03 (Croydon)","","","`#189853 <https://github.com/llvm/llvm-project/issues/189853>`__",""
 "`LWG4497 <https://wg21.link/LWG4497>`__","``std::nullopt_t`` should be comparable","2026-03 (Croydon)","","","`#189854 <https://github.com/llvm/llvm-project/issues/189854>`__",""
 "`LWG4499 <https://wg21.link/LWG4499>`__","``flat_set::insert_range`` specification may be problematic","2026-03 (Croydon)","","","`#189855 <https://github.com/llvm/llvm-project/issues/189855>`__",""
-"`LWG4500 <https://wg21.link/LWG4500>`__","``constant_wrapper`` wording problems","2026-03 (Croydon)","","","`#189856 <https://github.com/llvm/llvm-project/issues/189856>`__",""
+"`LWG4500 <https://wg21.link/LWG4500>`__","``constant_wrapper`` wording problems","2026-03 (Croydon)","|Complete|","23","`#189856 <https://github.com/llvm/llvm-project/issues/189856>`__",""
 "`LWG4504 <https://wg21.link/LWG4504>`__","Wording problem in ``{simple_}counting_scope``","2026-03 (Croydon)","","","`#189857 <https://github.com/llvm/llvm-project/issues/189857>`__",""
 "`LWG4506 <https://wg21.link/LWG4506>`__","``source_location`` is explicitly unspecified if is constexpr or not","2026-03 (Croydon)","","","`#189858 <https://github.com/llvm/llvm-project/issues/189858>`__",""
 "`LWG4510 <https://wg21.link/LWG4510>`__","Ambiguity of ``std::ranges::advance`` and ``std::ranges::next`` when the difference type is also a sentinel type","2026-03 (Croydon)","","","`#189859 <https://github.com/llvm/llvm-project/issues/189859>`__",""
@@ -320,7 +320,7 @@
 "`LWG4514 <https://wg21.link/LWG4514>`__","Missing absolute value of ``init`` in ``vector_two_norm`` and ``matrix_frob_norm``","2026-03 (Croydon)","","","`#189862 <https://github.com/llvm/llvm-project/issues/189862>`__",""
 "`LWG4517 <https://wg21.link/LWG4517>`__","``data_member_spec`` should throw for *cv*-qualified unnamed bit-fields","2026-03 (Croydon)","","","`#189863 <https://github.com/llvm/llvm-project/issues/189863>`__",""
 "`LWG4522 <https://wg21.link/LWG4522>`__","Clarify that ``std::format`` transcodes for ``std::wformat_string``\s","2026-03 (Croydon)","","","`#189864 <https://github.com/llvm/llvm-project/issues/189864>`__",""
-"`LWG4523 <https://wg21.link/LWG4523>`__","``constant_wrapper`` should assign to value","2026-03 (Croydon)","","","`#189865 <https://github.com/llvm/llvm-project/issues/189865>`__",""
+"`LWG4523 <https://wg21.link/LWG4523>`__","``constant_wrapper`` should assign to value","2026-03 (Croydon)","|Complete|","23","`#189865 <https://github.com/llvm/llvm-project/issues/189865>`__",""
 "`LWG4525 <https://wg21.link/LWG4525>`__","``task``'s ``final_suspend`` should move the result","2026-03 (Croydon)","","","`#189866 <https://github.com/llvm/llvm-project/issues/189866>`__",""
 "`LWG4527 <https://wg21.link/LWG4527>`__","``await_transform`` needs to use ``as_awaitable``","2026-03 (Croydon)","","","`#189867 <https://github.com/llvm/llvm-project/issues/189867>`__",""
 "`LWG4528 <https://wg21.link/LWG4528>`__","``task`` needs ``get_completion_signatures()``","2026-03 (Croydon)","","","`#189868 <https://github.com/llvm/llvm-project/issues/189868>`__",""
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 6eda9128fda48..28e8a3f87c12b 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -152,7 +152,7 @@
 "`P3060R3 <https://wg21.link/P3060R3>`__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","22","`#148175 <https://github.com/llvm/llvm-project/issues/148175>`__",""
 "`P2319R5 <https://wg21.link/P2319R5>`__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","","`#148177 <https://github.com/llvm/llvm-project/issues/148177>`__",""
 "`P3223R2 <https://wg21.link/P3223R2>`__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","|Complete|","22","`#148178 <https://github.com/llvm/llvm-project/issues/148178>`__",""
-"`P2781R9 <https://wg21.link/P2781R9>`__","``std::constant_wrapper``","2025-06 (Sofia)","","","`#148179 <https://github.com/llvm/llvm-project/issues/148179>`__",""
+"`P2781R9 <https://wg21.link/P2781R9>`__","``std::constant_wrapper``","2025-06 (Sofia)","|Complete|","23","`#148179 <https://github.com/llvm/llvm-project/issues/148179>`__",""
 "`P3697R1 <https://wg21.link/P3697R1>`__","Minor additions to C++26 standard library hardening","2025-06 (Sofia)","","","`#148180 <https://github.com/llvm/llvm-project/issues/148180>`__",""
 "`P3552R3 <https://wg21.link/P3552R3>`__","Add a Coroutine Task Type","2025-06 (Sofia)","","","`#148182 <https://github.com/llvm/llvm-project/issues/148182>`__",""
 "`P1317R2 <https://wg21.link/P1317R2>`__","Remove return type deduction in ``std::apply``","2025-06 (Sofia)","","","`#148183 <https://github.com/llvm/llvm-project/issues/148183>`__",""
@@ -193,7 +193,7 @@
 "`P3828R1 <https://wg21.link/P3828R1>`__","Rename the to_input view to as_input","2026-03 (Croydon)","","","`#189602 <https://github.com/llvm/llvm-project/issues/189602>`__",""
 "`P3795R2 <https://wg21.link/P3795R2>`__","Miscellaneous Reflection Cleanup","2026-03 (Croydon)","","","`#189603 <https://github.com/llvm/llvm-project/issues/189603>`__",""
 "`P3948R1 <https://wg21.link/P3948R1>`__","``constant_wrapper`` is the only tool needed for passing constant expressions via function arguments","2026-03 (Croydon)","","","`#189604 <https://github.com/llvm/llvm-project/issues/189604>`__",""
-"`P3978R3 <https://wg21.link/P3978R3>`__","``constant_wrapper`` should unwrap on call and subscript","2026-03 (Croydon)","","","`#189605 <https://github.com/llvm/llvm-project/issues/189605>`__",""
+"`P3978R3 <https://wg21.link/P3978R3>`__","``constant_wrapper`` should unwrap on call and subscript","2026-03 (Croydon)","|Complete|","23","`#189605 <https://github.com/llvm/llvm-project/issues/189605>`__",""
 "`P3961R1 <https://wg21.link/P3961R1>`__","Less double indirection in ``function_ref`` (RU-220)","2026-03 (Croydon)","","","`#189606 <https://github.com/llvm/llvm-project/issues/189606>`__",""
 "`P3981R2 <https://wg21.link/P3981R2>`__","Better return types in ``std::inplace_vector`` and ``std::exception_ptr_cast``","2026-03 (Croydon)","","","`#189607 <https://github.com/llvm/llvm-project/issues/189607>`__",""
 "`P4022R0 <https://wg21.link/P4022R0>`__","Remove ``try_append_range`` from ``inplace_vector`` for now","2026-03 (Croydon)","","","`#189608 <https://github.com/llvm/llvm-project/issues/189608>`__",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 53165f0336b2d..712ad8bf66593 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -926,6 +926,7 @@ set(files
   __utility/as_lvalue.h
   __utility/auto_cast.h
   __utility/cmp.h
+  __utility/constant_wrapper.h
   __utility/convert_to_integral.h
   __utility/declval.h
   __utility/default_three_way_comparator.h
diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
new file mode 100644
index 0000000000000..440405fca304e
--- /dev/null
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -0,0 +1,335 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_CONSTANT_WRAPPER_H
+#define _LIBCPP___UTILITY_CONSTANT_WRAPPER_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/invoke.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <__utility/integer_sequence.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Tp>
+struct __cw_fixed_value;
+
+template <__cw_fixed_value _Xp, class = typename decltype(_Xp)::__type>
+struct constant_wrapper;
+
+template <class _Tp>
+concept __constexpr_param = requires { typename constant_wrapper<_Tp::value>; };
+
+struct __cw_operators;
+
+template <__cw_fixed_value _Xp>
+constexpr auto cw = constant_wrapper<_Xp>{};
+
+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]>;
+
+struct __cw_operators {
+  // unary operators
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)> {
+    return {};
+  }
+
+  // binary operators
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value + _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value - _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value * _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator/(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value / _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator%(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value % _Rp::value)> {
+    return {};
+  }
+
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<<(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value << _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>>(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value >> _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value & _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator|(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value | _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator^(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value ^ _Rp::value)> {
+    return {};
+  }
+
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+    requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&&(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value && _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+    requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator||(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value || _Rp::value)> {
+    return {};
+  }
+
+  // comparisons
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value <=> _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value < _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value <= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  friend constexpr auto operator==(_Lp, _Rp) noexcept -> constant_wrapper<(_Lp::value == _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!=(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value != _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value > _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>=(_Lp, _Rp) noexcept
+      -> constant_wrapper<(_Lp::value >= _Rp::value)> {
+    return {};
+  }
+
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator,(_Lp, _Rp) noexcept = delete;
+  template <__constexpr_param _Lp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator->*(_Lp, _Rp) noexcept
+      -> constant_wrapper<_Lp::value->*(_Rp::value)> {
+    return {};
+  }
+
+  // pseudo-mutators
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept -> constant_wrapper<++(_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp, int) noexcept -> constant_wrapper<(_Tp::value++)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept -> constant_wrapper<--(_Tp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp, int) noexcept -> constant_wrapper<(_Tp::value--)> {
+    return {};
+  }
+
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator+=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value += _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator-=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value -= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator*=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value *= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator/=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value /= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator%=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value %= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator&=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value &= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __constexpr_param _Rp>
+  _LIBCPP_HIDE_FROM_ABI constexpr auto operator|=(this _Tp, _Rp) noexcept
+      -> constant_wrapper<(_Tp::value |= _Rp::value)> {
+    return {};
+  }
+  template <__constexpr_param _Tp, __const...
[truncated]

``````````

</details>


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


More information about the libcxx-commits mailing list