[1/2] libstdc++: Move constant_wrapper from <type_traits> to <utility>

Message ID 20260407165536.534545-1-tkaminsk@redhat.com
State Committed
Commit 58564c85c5dd221b26c65a26b4bd0a6ccb6e3178
Headers
Series [1/2] libstdc++: Move constant_wrapper from <type_traits> to <utility> |

Commit Message

Tomasz Kaminski April 7, 2026, 4:51 p.m. UTC
  Change placement of constant_wrapper and related classes per
P3978R3: constant_wrapper should unwrap on call and subscript

libstdc++-v3/ChangeLog:

	* include/bits/utility.h (std::_CwFixedValue, std::_ConstExprParam)
	(std::_CwOperators, std::constant_wrapper): Moved from...
	* include/std/type_traits (std::_CwFixedValue, std::_ConstExprParam)
	(std::_CwOperators, std::constant_wrapper): Moved to bits_utility.
	Disable __cpp_lib_constant_wrapper defintion.
	* include/std/utility: Define __cpp_lib_constant_wrapper.
	* testsuite/20_util/constant_wrapper/adl.cc: Updated header includes.
	* testsuite/20_util/constant_wrapper/ex.cc: Likewise.
	* testsuite/20_util/constant_wrapper/generic.cc: Likewise.
	* testsuite/20_util/constant_wrapper/instantiate.cc: Likewise.
	* testsuite/20_util/constant_wrapper/op_comma_neg.cc: Likewise.
	* testsuite/20_util/constant_wrapper/other_wrappers.cc: Likewise.
	* testsuite/20_util/constant_wrapper/version.cc: Likewise.
---
Testing on x86_64-linux. *constant_wrapper* test passed.
OK for trunk when all test passes?

 libstdc++-v3/include/bits/utility.h           | 325 +++++++++++++++++
 libstdc++-v3/include/std/type_traits          | 326 ------------------
 libstdc++-v3/include/std/utility              |   1 +
 .../testsuite/20_util/constant_wrapper/adl.cc |   2 +-
 .../testsuite/20_util/constant_wrapper/ex.cc  |   2 +-
 .../20_util/constant_wrapper/generic.cc       |   1 -
 .../20_util/constant_wrapper/instantiate.cc   |   1 -
 .../20_util/constant_wrapper/op_comma_neg.cc  |   2 +-
 .../constant_wrapper/other_wrappers.cc        |   2 +-
 .../20_util/constant_wrapper/version.cc       |   4 +-
 10 files changed, 332 insertions(+), 334 deletions(-)
  

Comments

Jonathan Wakely April 7, 2026, 7:42 p.m. UTC | #1
OK

On Tue, 7 Apr 2026, 17:55 Tomasz KamiƄski, <tkaminsk@redhat.com> wrote:

> Change placement of constant_wrapper and related classes per
> P3978R3: constant_wrapper should unwrap on call and subscript
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/utility.h (std::_CwFixedValue, std::_ConstExprParam)
>         (std::_CwOperators, std::constant_wrapper): Moved from...
>         * include/std/type_traits (std::_CwFixedValue,
> std::_ConstExprParam)
>         (std::_CwOperators, std::constant_wrapper): Moved to bits_utility.
>         Disable __cpp_lib_constant_wrapper defintion.
>         * include/std/utility: Define __cpp_lib_constant_wrapper.
>         * testsuite/20_util/constant_wrapper/adl.cc: Updated header
> includes.
>         * testsuite/20_util/constant_wrapper/ex.cc: Likewise.
>         * testsuite/20_util/constant_wrapper/generic.cc: Likewise.
>         * testsuite/20_util/constant_wrapper/instantiate.cc: Likewise.
>         * testsuite/20_util/constant_wrapper/op_comma_neg.cc: Likewise.
>         * testsuite/20_util/constant_wrapper/other_wrappers.cc: Likewise.
>         * testsuite/20_util/constant_wrapper/version.cc: Likewise.
> ---
> Testing on x86_64-linux. *constant_wrapper* test passed.
> OK for trunk when all test passes?
>
>  libstdc++-v3/include/bits/utility.h           | 325 +++++++++++++++++
>  libstdc++-v3/include/std/type_traits          | 326 ------------------
>  libstdc++-v3/include/std/utility              |   1 +
>  .../testsuite/20_util/constant_wrapper/adl.cc |   2 +-
>  .../testsuite/20_util/constant_wrapper/ex.cc  |   2 +-
>  .../20_util/constant_wrapper/generic.cc       |   1 -
>  .../20_util/constant_wrapper/instantiate.cc   |   1 -
>  .../20_util/constant_wrapper/op_comma_neg.cc  |   2 +-
>  .../constant_wrapper/other_wrappers.cc        |   2 +-
>  .../20_util/constant_wrapper/version.cc       |   4 +-
>  10 files changed, 332 insertions(+), 334 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/utility.h
> b/libstdc++-v3/include/bits/utility.h
> index bd6b18d54dd..970e63e8170 100644
> --- a/libstdc++-v3/include/bits/utility.h
> +++ b/libstdc++-v3/include/bits/utility.h
> @@ -137,6 +137,331 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      using tuple_element_t = typename tuple_element<__i, _Tp>::type;
>  #endif
>
> +#ifdef __glibcxx_constant_wrapper // C++ >= 26
> +  template<typename _Tp>
> +    struct _CwFixedValue
> +    {
> +      using __type = _Tp;
> +
> +      constexpr
> +      _CwFixedValue(__type __v) noexcept
> +      : _M_data(__v) { }
> +
> +      __type _M_data;
> +    };
> +
> +  template<typename _Tp, size_t _Extent>
> +    struct _CwFixedValue<_Tp[_Extent]>
> +    {
> +      using __type = _Tp[_Extent];
> +
> +      constexpr
> +      _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept
> +        : _CwFixedValue(__arr, typename
> _Build_index_tuple<_Extent>::__type())
> +      { }
> +
> +      template<size_t... _Indices>
> +       constexpr
> +       _CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>)
> noexcept
> +         : _M_data{__arr[_Indices]...}
> +       { }
> +
> +      _Tp _M_data[_Extent];
> +    };
> +
> +  template<typename _Tp, size_t _Extent>
> +    _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>;
> +
> +  template<_CwFixedValue _Xv,
> +          typename = typename decltype(_CwFixedValue(_Xv))::__type>
> +    struct constant_wrapper;
> +
> +  template<typename _Tp>
> +    concept _ConstExprParam = requires
> +    {
> +      typename constant_wrapper<_Tp::value>;
> +    };
> +
> +  struct _CwOperators
> +  {
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      friend constexpr auto
> +      operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator+(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value + _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator-(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value - _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator*(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value * _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator/(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value / _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator%(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value % _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator<<(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value << _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator>>(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value >> _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator&(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value & _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator|(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value | _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator^(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value ^ _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      requires (!is_constructible_v<bool, decltype(_Left::value)>
> +               || !is_constructible_v<bool, decltype(_Right::value)>)
> +      friend constexpr auto
> +      operator&&(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value && _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      requires (!is_constructible_v<bool, decltype(_Left::value)>
> +               || !is_constructible_v<bool, decltype(_Right::value)>)
> +      friend constexpr auto
> +      operator||(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value || _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator<=>(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value <=> _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator<(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value < _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator<=(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value <= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator==(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value == _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator!=(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value != _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator>(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value > _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator>=(_Left, _Right) noexcept
> +       -> constant_wrapper<(_Left::value >= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator,(_Left, _Right) noexcept = delete;
> +
> +    template<_ConstExprParam _Left, _ConstExprParam _Right>
> +      friend constexpr auto
> +      operator->*(_Left, _Right) noexcept
> +       -> constant_wrapper<_Left::value->*(_Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
> +      constexpr auto
> +      operator()(this _Tp, _Args...) noexcept
> +      requires
> +       requires(_Args...) {
> constant_wrapper<_Tp::value(_Args::value...)>(); }
> +      { return constant_wrapper<_Tp::value(_Args::value...)>{}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
> +      constexpr auto
> +      operator[](this _Tp, _Args...) noexcept
> +       -> constant_wrapper<(_Tp::value[_Args::value...])>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      constexpr auto
> +      operator++(this _Tp) noexcept
> +       -> constant_wrapper<(++_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      constexpr auto
> +      operator++(this _Tp, int) noexcept
> +       -> constant_wrapper<(_Tp::value++)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      constexpr auto
> +      operator--(this _Tp) noexcept
> +       -> constant_wrapper<(--_Tp::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp>
> +      constexpr auto
> +      operator--(this _Tp, int) noexcept
> +       -> constant_wrapper<(_Tp::value--)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator+=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value += _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator-=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value -= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator*=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value *= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator/=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value /= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator%=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value %= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator&=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value &= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator|=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value |= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator^=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value ^= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator<<=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value <<= _Right::value)>
> +      { return {}; }
> +
> +    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> +      constexpr auto
> +      operator>>=(this _Tp, _Right) noexcept
> +       -> constant_wrapper<(_Tp::value >>= _Right::value)>
> +      { return {}; }
> +  };
> +
> +  template<_CwFixedValue _Xv, typename>
> +  struct constant_wrapper : _CwOperators
> +  {
> +    static constexpr const auto& value = _Xv._M_data;
> +    using type = constant_wrapper;
> +    using value_type = typename decltype(_Xv)::__type;
> +
> +    template<_ConstExprParam _Right>
> +      constexpr auto
> +      operator=(_Right) const noexcept
> +       -> constant_wrapper<(value = _Right::value)>
> +      { return {}; }
> +
> +    constexpr
> +    operator decltype(value)() const noexcept
> +    { return value; }
> +  };
> +
> +  template<_CwFixedValue _Tp>
> +    constexpr auto cw = constant_wrapper<_Tp>{};
> +#endif
> +
>  #ifdef __glibcxx_integer_sequence // C++ >= 14
>
>    /// Class template integer_sequence
> diff --git a/libstdc++-v3/include/std/type_traits
> b/libstdc++-v3/include/std/type_traits
> index 38be1b0e09d..d10cbde19cc 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -42,7 +42,6 @@
>  #define __glibcxx_want_bool_constant
>  #define __glibcxx_want_bounded_array_traits
>  #define __glibcxx_want_common_reference
> -#define __glibcxx_want_constant_wrapper
>  #define __glibcxx_want_has_unique_object_representations
>  #define __glibcxx_want_integral_constant_callable
>  #define __glibcxx_want_is_aggregate
> @@ -4403,331 +4402,6 @@ template<typename _Ret, typename _Fn, typename...
> _Args>
>      };
>  #endif // C++11
>
> -#ifdef __cpp_lib_constant_wrapper // C++ >= 26
> -  template<typename _Tp>
> -    struct _CwFixedValue
> -    {
> -      using __type = _Tp;
> -
> -      constexpr
> -      _CwFixedValue(__type __v) noexcept
> -      : _M_data(__v) { }
> -
> -      __type _M_data;
> -    };
> -
> -  template<typename _Tp, size_t _Extent>
> -    struct _CwFixedValue<_Tp[_Extent]>
> -    {
> -      using __type = _Tp[_Extent];
> -
> -      constexpr
> -      _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept
> -        : _CwFixedValue(__arr, typename
> _Build_index_tuple<_Extent>::__type())
> -      { }
> -
> -      template<size_t... _Indices>
> -       constexpr
> -       _CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>)
> noexcept
> -         : _M_data{__arr[_Indices]...}
> -       { }
> -
> -      _Tp _M_data[_Extent];
> -    };
> -
> -  template<typename _Tp, size_t _Extent>
> -    _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>;
> -
> -  template<_CwFixedValue _Xv,
> -          typename = typename decltype(_CwFixedValue(_Xv))::__type>
> -    struct constant_wrapper;
> -
> -  template<typename _Tp>
> -    concept _ConstExprParam = requires
> -    {
> -      typename constant_wrapper<_Tp::value>;
> -    };
> -
> -  struct _CwOperators
> -  {
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      friend constexpr auto
> -      operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator+(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value + _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator-(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value - _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator*(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value * _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator/(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value / _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator%(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value % _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator<<(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value << _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator>>(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value >> _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator&(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value & _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator|(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value | _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator^(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value ^ _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      requires (!is_constructible_v<bool, decltype(_Left::value)>
> -               || !is_constructible_v<bool, decltype(_Right::value)>)
> -      friend constexpr auto
> -      operator&&(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value && _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      requires (!is_constructible_v<bool, decltype(_Left::value)>
> -               || !is_constructible_v<bool, decltype(_Right::value)>)
> -      friend constexpr auto
> -      operator||(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value || _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator<=>(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value <=> _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator<(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value < _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator<=(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value <= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator==(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value == _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator!=(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value != _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator>(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value > _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator>=(_Left, _Right) noexcept
> -       -> constant_wrapper<(_Left::value >= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator,(_Left, _Right) noexcept = delete;
> -
> -    template<_ConstExprParam _Left, _ConstExprParam _Right>
> -      friend constexpr auto
> -      operator->*(_Left, _Right) noexcept
> -       -> constant_wrapper<_Left::value->*(_Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
> -      constexpr auto
> -      operator()(this _Tp, _Args...) noexcept
> -      requires
> -       requires(_Args...) {
> constant_wrapper<_Tp::value(_Args::value...)>(); }
> -      { return constant_wrapper<_Tp::value(_Args::value...)>{}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
> -      constexpr auto
> -      operator[](this _Tp, _Args...) noexcept
> -       -> constant_wrapper<(_Tp::value[_Args::value...])>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      constexpr auto
> -      operator++(this _Tp) noexcept
> -       -> constant_wrapper<(++_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      constexpr auto
> -      operator++(this _Tp, int) noexcept
> -       -> constant_wrapper<(_Tp::value++)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      constexpr auto
> -      operator--(this _Tp) noexcept
> -       -> constant_wrapper<(--_Tp::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp>
> -      constexpr auto
> -      operator--(this _Tp, int) noexcept
> -       -> constant_wrapper<(_Tp::value--)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator+=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value += _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator-=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value -= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator*=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value *= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator/=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value /= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator%=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value %= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator&=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value &= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator|=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value |= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator^=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value ^= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator<<=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value <<= _Right::value)>
> -      { return {}; }
> -
> -    template<_ConstExprParam _Tp, _ConstExprParam _Right>
> -      constexpr auto
> -      operator>>=(this _Tp, _Right) noexcept
> -       -> constant_wrapper<(_Tp::value >>= _Right::value)>
> -      { return {}; }
> -  };
> -
> -  template<_CwFixedValue _Xv, typename>
> -  struct constant_wrapper : _CwOperators
> -  {
> -    static constexpr const auto& value = _Xv._M_data;
> -    using type = constant_wrapper;
> -    using value_type = typename decltype(_Xv)::__type;
> -
> -    template<_ConstExprParam _Right>
> -      constexpr auto
> -      operator=(_Right) const noexcept
> -       -> constant_wrapper<(value = _Right::value)>
> -      { return {}; }
> -
> -    constexpr
> -    operator decltype(value)() const noexcept
> -    { return value; }
> -  };
> -
> -  template<_CwFixedValue _Tp>
> -    constexpr auto cw = constant_wrapper<_Tp>{};
> -#endif
> -
>    /// @} group metaprogramming
>
>  _GLIBCXX_END_NAMESPACE_VERSION
> diff --git a/libstdc++-v3/include/std/utility
> b/libstdc++-v3/include/std/utility
> index 7d9d3653cd0..2e1775bf6b3 100644
> --- a/libstdc++-v3/include/std/utility
> +++ b/libstdc++-v3/include/std/utility
> @@ -87,6 +87,7 @@
>
>  #define __glibcxx_want_addressof_constexpr
>  #define __glibcxx_want_as_const
> +#define __glibcxx_want_constant_wrapper
>  #define __glibcxx_want_constexpr_algorithms
>  #define __glibcxx_want_constexpr_utility
>  #define __glibcxx_want_exchange_function
> diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
> index 3cdc09c1eb7..3629e4fc559 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
> @@ -1,5 +1,5 @@
>  // { dg-do compile { target c++26 } }
> -#include <type_traits>
> +#include <utility>
>  #include <concepts>
>
>  #include <testsuite_hooks.h>
> diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
> index a4d967b9634..a5d19fd8132 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
> @@ -1,5 +1,5 @@
>  // { dg-do compile { target c++26 } }
> -#include <type_traits>
> +#include <utility>
>  #include <iostream>
>
>  #include <testsuite_hooks.h>
> diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
> index de4334b64f5..1c7770d7a89 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -#include <type_traits>
>  #include <utility>
>  #include <string_view>
>
> diff --git
> a/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
> index 5adf6fda5a3..452f01fadcd 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -#include <type_traits>
>  #include <utility>
>
>  #include <testsuite_hooks.h>
> diff --git
> a/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
> index 4384e920ea5..2fc8c78c2da 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
> @@ -1,5 +1,5 @@
>  // { dg-do compile { target c++26 } }
> -#include <type_traits>
> +#include <utility>
>
>  constexpr void
>  test_comma_same_types()
> diff --git
> a/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
> index 3c3cfafd6ed..fe45c5a8516 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
> @@ -1,5 +1,5 @@
>  // { dg-do run { target c++26 } }
> -#include <type_traits>
> +#include <utility>
>  #include <concepts>
>
>  #include <testsuite_hooks.h>
> diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
> b/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
> index 4fee6159141..776d80c576a 100644
> --- a/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
> +++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
> @@ -1,10 +1,10 @@
>  // { dg-do preprocess { target c++26 } }
>  // { dg-add-options no_pch }
>
> -#include <type_traits>
> +#include <utility>
>
>  #ifndef __cpp_lib_constant_wrapper
> -#error "Feature test macro __cpp_lib_constant_wrapper is missing for
> <type_traits>"
> +#error "Feature test macro __cpp_lib_constant_wrapper is missing for
> <utility>"
>  #if __cpp_lib_constant_wrapper < 202506L
>  #error "Feature test macro __cpp_lib_constant_wrapper has the wrong value"
>  #endif
> --
> 2.53.0
>
>
  

Patch

diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h
index bd6b18d54dd..970e63e8170 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -137,6 +137,331 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using tuple_element_t = typename tuple_element<__i, _Tp>::type;
 #endif
 
+#ifdef __glibcxx_constant_wrapper // C++ >= 26
+  template<typename _Tp>
+    struct _CwFixedValue
+    {
+      using __type = _Tp;
+
+      constexpr
+      _CwFixedValue(__type __v) noexcept
+      : _M_data(__v) { }
+
+      __type _M_data;
+    };
+
+  template<typename _Tp, size_t _Extent>
+    struct _CwFixedValue<_Tp[_Extent]>
+    {
+      using __type = _Tp[_Extent];
+
+      constexpr
+      _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept
+        : _CwFixedValue(__arr, typename _Build_index_tuple<_Extent>::__type())
+      { }
+
+      template<size_t... _Indices>
+	constexpr
+	_CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>) noexcept
+	  : _M_data{__arr[_Indices]...}
+	{ }
+
+      _Tp _M_data[_Extent];
+    };
+
+  template<typename _Tp, size_t _Extent>
+    _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>;
+
+  template<_CwFixedValue _Xv,
+	   typename = typename decltype(_CwFixedValue(_Xv))::__type>
+    struct constant_wrapper;
+
+  template<typename _Tp>
+    concept _ConstExprParam = requires
+    {
+      typename constant_wrapper<_Tp::value>;
+    };
+
+  struct _CwOperators
+  {
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      friend constexpr auto
+      operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator+(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value + _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator-(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value - _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator*(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value * _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator/(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value / _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator%(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value % _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator<<(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value << _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator>>(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value >> _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator&(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value & _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator|(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value | _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator^(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value ^ _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      requires (!is_constructible_v<bool, decltype(_Left::value)>
+		|| !is_constructible_v<bool, decltype(_Right::value)>)
+      friend constexpr auto
+      operator&&(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value && _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      requires (!is_constructible_v<bool, decltype(_Left::value)>
+		|| !is_constructible_v<bool, decltype(_Right::value)>)
+      friend constexpr auto
+      operator||(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value || _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator<=>(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value <=> _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator<(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value < _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator<=(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value <= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator==(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value == _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator!=(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value != _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator>(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value > _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator>=(_Left, _Right) noexcept
+	-> constant_wrapper<(_Left::value >= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator,(_Left, _Right) noexcept = delete;
+
+    template<_ConstExprParam _Left, _ConstExprParam _Right>
+      friend constexpr auto
+      operator->*(_Left, _Right) noexcept
+	-> constant_wrapper<_Left::value->*(_Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
+      constexpr auto
+      operator()(this _Tp, _Args...) noexcept
+      requires
+	requires(_Args...) { constant_wrapper<_Tp::value(_Args::value...)>(); }
+      { return constant_wrapper<_Tp::value(_Args::value...)>{}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
+      constexpr auto
+      operator[](this _Tp, _Args...) noexcept
+	-> constant_wrapper<(_Tp::value[_Args::value...])>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      constexpr auto
+      operator++(this _Tp) noexcept
+ 	-> constant_wrapper<(++_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      constexpr auto
+      operator++(this _Tp, int) noexcept
+ 	-> constant_wrapper<(_Tp::value++)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      constexpr auto
+      operator--(this _Tp) noexcept
+ 	-> constant_wrapper<(--_Tp::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp>
+      constexpr auto
+      operator--(this _Tp, int) noexcept
+ 	-> constant_wrapper<(_Tp::value--)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator+=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value += _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator-=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value -= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator*=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value *= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator/=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value /= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator%=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value %= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator&=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value &= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator|=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value |= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator^=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value ^= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator<<=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value <<= _Right::value)>
+      { return {}; }
+
+    template<_ConstExprParam _Tp, _ConstExprParam _Right>
+      constexpr auto
+      operator>>=(this _Tp, _Right) noexcept
+  	-> constant_wrapper<(_Tp::value >>= _Right::value)>
+      { return {}; }
+  };
+
+  template<_CwFixedValue _Xv, typename>
+  struct constant_wrapper : _CwOperators
+  {
+    static constexpr const auto& value = _Xv._M_data;
+    using type = constant_wrapper;
+    using value_type = typename decltype(_Xv)::__type;
+
+    template<_ConstExprParam _Right>
+      constexpr auto
+      operator=(_Right) const noexcept
+  	-> constant_wrapper<(value = _Right::value)>
+      { return {}; }
+
+    constexpr
+    operator decltype(value)() const noexcept
+    { return value; }
+  };
+
+  template<_CwFixedValue _Tp>
+    constexpr auto cw = constant_wrapper<_Tp>{};
+#endif
+
 #ifdef __glibcxx_integer_sequence // C++ >= 14
 
   /// Class template integer_sequence
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 38be1b0e09d..d10cbde19cc 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -42,7 +42,6 @@ 
 #define __glibcxx_want_bool_constant
 #define __glibcxx_want_bounded_array_traits
 #define __glibcxx_want_common_reference
-#define __glibcxx_want_constant_wrapper
 #define __glibcxx_want_has_unique_object_representations
 #define __glibcxx_want_integral_constant_callable
 #define __glibcxx_want_is_aggregate
@@ -4403,331 +4402,6 @@  template<typename _Ret, typename _Fn, typename... _Args>
     };
 #endif // C++11
 
-#ifdef __cpp_lib_constant_wrapper // C++ >= 26
-  template<typename _Tp>
-    struct _CwFixedValue
-    {
-      using __type = _Tp;
-
-      constexpr
-      _CwFixedValue(__type __v) noexcept
-      : _M_data(__v) { }
-
-      __type _M_data;
-    };
-
-  template<typename _Tp, size_t _Extent>
-    struct _CwFixedValue<_Tp[_Extent]>
-    {
-      using __type = _Tp[_Extent];
-
-      constexpr
-      _CwFixedValue(_Tp (&__arr)[_Extent]) noexcept
-        : _CwFixedValue(__arr, typename _Build_index_tuple<_Extent>::__type())
-      { }
-
-      template<size_t... _Indices>
-	constexpr
-	_CwFixedValue(_Tp (&__arr)[_Extent], _Index_tuple<_Indices...>) noexcept
-	  : _M_data{__arr[_Indices]...}
-	{ }
-
-      _Tp _M_data[_Extent];
-    };
-
-  template<typename _Tp, size_t _Extent>
-    _CwFixedValue(_Tp (&)[_Extent]) -> _CwFixedValue<_Tp[_Extent]>;
-
-  template<_CwFixedValue _Xv,
-	   typename = typename decltype(_CwFixedValue(_Xv))::__type>
-    struct constant_wrapper;
-
-  template<typename _Tp>
-    concept _ConstExprParam = requires
-    {
-      typename constant_wrapper<_Tp::value>;
-    };
-
-  struct _CwOperators
-  {
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      friend constexpr auto
-      operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator+(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value + _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator-(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value - _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator*(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value * _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator/(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value / _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator%(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value % _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator<<(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value << _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator>>(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value >> _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator&(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value & _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator|(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value | _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator^(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value ^ _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      requires (!is_constructible_v<bool, decltype(_Left::value)>
-		|| !is_constructible_v<bool, decltype(_Right::value)>)
-      friend constexpr auto
-      operator&&(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value && _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      requires (!is_constructible_v<bool, decltype(_Left::value)>
-		|| !is_constructible_v<bool, decltype(_Right::value)>)
-      friend constexpr auto
-      operator||(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value || _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator<=>(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value <=> _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator<(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value < _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator<=(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value <= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator==(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value == _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator!=(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value != _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator>(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value > _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator>=(_Left, _Right) noexcept
-	-> constant_wrapper<(_Left::value >= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator,(_Left, _Right) noexcept = delete;
-
-    template<_ConstExprParam _Left, _ConstExprParam _Right>
-      friend constexpr auto
-      operator->*(_Left, _Right) noexcept
-	-> constant_wrapper<_Left::value->*(_Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
-      constexpr auto
-      operator()(this _Tp, _Args...) noexcept
-      requires
-	requires(_Args...) { constant_wrapper<_Tp::value(_Args::value...)>(); }
-      { return constant_wrapper<_Tp::value(_Args::value...)>{}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam... _Args>
-      constexpr auto
-      operator[](this _Tp, _Args...) noexcept
-	-> constant_wrapper<(_Tp::value[_Args::value...])>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      constexpr auto
-      operator++(this _Tp) noexcept
- 	-> constant_wrapper<(++_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      constexpr auto
-      operator++(this _Tp, int) noexcept
- 	-> constant_wrapper<(_Tp::value++)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      constexpr auto
-      operator--(this _Tp) noexcept
- 	-> constant_wrapper<(--_Tp::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp>
-      constexpr auto
-      operator--(this _Tp, int) noexcept
- 	-> constant_wrapper<(_Tp::value--)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator+=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value += _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator-=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value -= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator*=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value *= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator/=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value /= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator%=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value %= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator&=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value &= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator|=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value |= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator^=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value ^= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator<<=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value <<= _Right::value)>
-      { return {}; }
-
-    template<_ConstExprParam _Tp, _ConstExprParam _Right>
-      constexpr auto
-      operator>>=(this _Tp, _Right) noexcept
-  	-> constant_wrapper<(_Tp::value >>= _Right::value)>
-      { return {}; }
-  };
-
-  template<_CwFixedValue _Xv, typename>
-  struct constant_wrapper : _CwOperators
-  {
-    static constexpr const auto& value = _Xv._M_data;
-    using type = constant_wrapper;
-    using value_type = typename decltype(_Xv)::__type;
-
-    template<_ConstExprParam _Right>
-      constexpr auto
-      operator=(_Right) const noexcept
-  	-> constant_wrapper<(value = _Right::value)>
-      { return {}; }
-
-    constexpr
-    operator decltype(value)() const noexcept
-    { return value; }
-  };
-
-  template<_CwFixedValue _Tp>
-    constexpr auto cw = constant_wrapper<_Tp>{};
-#endif
-
   /// @} group metaprogramming
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index 7d9d3653cd0..2e1775bf6b3 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -87,6 +87,7 @@ 
 
 #define __glibcxx_want_addressof_constexpr
 #define __glibcxx_want_as_const
+#define __glibcxx_want_constant_wrapper
 #define __glibcxx_want_constexpr_algorithms
 #define __glibcxx_want_constexpr_utility
 #define __glibcxx_want_exchange_function
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
index 3cdc09c1eb7..3629e4fc559 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/adl.cc
@@ -1,5 +1,5 @@ 
 // { dg-do compile { target c++26 } }
-#include <type_traits>
+#include <utility>
 #include <concepts>
 
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
index a4d967b9634..a5d19fd8132 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/ex.cc
@@ -1,5 +1,5 @@ 
 // { dg-do compile { target c++26 } }
-#include <type_traits>
+#include <utility>
 #include <iostream>
 
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
index de4334b64f5..1c7770d7a89 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
@@ -1,5 +1,4 @@ 
 // { dg-do run { target c++26 } }
-#include <type_traits>
 #include <utility>
 #include <string_view>
 
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
index 5adf6fda5a3..452f01fadcd 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/instantiate.cc
@@ -1,5 +1,4 @@ 
 // { dg-do run { target c++26 } }
-#include <type_traits>
 #include <utility>
 
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
index 4384e920ea5..2fc8c78c2da 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/op_comma_neg.cc
@@ -1,5 +1,5 @@ 
 // { dg-do compile { target c++26 } }
-#include <type_traits>
+#include <utility>
 
 constexpr void
 test_comma_same_types()
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
index 3c3cfafd6ed..fe45c5a8516 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
@@ -1,5 +1,5 @@ 
 // { dg-do run { target c++26 } }
-#include <type_traits>
+#include <utility>
 #include <concepts>
 
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc b/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
index 4fee6159141..776d80c576a 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/version.cc
@@ -1,10 +1,10 @@ 
 // { dg-do preprocess { target c++26 } }
 // { dg-add-options no_pch }
 
-#include <type_traits>
+#include <utility>
 
 #ifndef __cpp_lib_constant_wrapper
-#error "Feature test macro __cpp_lib_constant_wrapper is missing for <type_traits>"
+#error "Feature test macro __cpp_lib_constant_wrapper is missing for <utility>"
 #if __cpp_lib_constant_wrapper < 202506L
 #error "Feature test macro __cpp_lib_constant_wrapper has the wrong value"
 #endif