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

Fixes https://github.com/llvm/llvm-project/issues/203336

---------

Signed-off-by: yronglin <yronglin777@gmail.com>
Co-authored-by: A. Jiang <de34@live.cn>
This commit is contained in:
Yihan Wang 2026-06-23 01:17:53 +08:00 committed by GitHub
parent 08d766ba6d
commit a88b88bdd3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 97 additions and 296 deletions

View file

@ -432,7 +432,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_constant_wrapper`` ``202603L``
``__cpp_lib_constant_wrapper`` ``202606L``
---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_algorithms`` ``202306L``
---------------------------------------------------------- -----------------

View file

@ -52,6 +52,7 @@ Implemented Papers
- P3383R3: ``mdspan.at()`` (`Github <https://llvm.org/PR175213>`__)
- P3369R0: constexpr for ``uninitialized_default_construct`` (`Github <https://llvm.org/PR118380>`__)
- P3508R0: Wording for "constexpr for specialized memory algorithms" (`Github <https://llvm.org/PR118379>`__)
- P4206R0: Revert string support in ``std::constant_wrapper`` (`Github <https://llvm.org/PR203338>`__)
Improvements and New Features
-----------------------------

View file

@ -5,7 +5,7 @@
"`P3319R6 <https://wg21.link/P3319R6>`__","Add an ``iota`` object for ``simd`` (and more)","2026-06 (Brno)","","","`#204393 <https://github.com/llvm/llvm-project/issues/204393>`__",""
"`P3798R1 <https://wg21.link/P3798R1>`__","The unexpected in ``std::expected``","2026-06 (Brno)","","","`#204394 <https://github.com/llvm/llvm-project/issues/204394>`__",""
"`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","","","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","","","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","To be applied as a Defect Report."
"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","Applied as a Defect Report."
"`P3395R6 <https://wg21.link/P3395R6>`__","Fix encoding issues and add a formatter for ``std::error_code``","2026-06 (Brno)","","","`#204396 <https://github.com/llvm/llvm-project/issues/204396>`__",""
"`P3505R4 <https://wg21.link/P3505R4>`__","Fix the default floating-point representation in ``std::format``","2026-06 (Brno)","","","`#204397 <https://github.com/llvm/llvm-project/issues/204397>`__","To be applied as a Defect Report."
"`P3154R3 <https://wg21.link/P3154R3>`__","Deprecating signed character types in iostreams","2026-06 (Brno)","","","`#204398 <https://github.com/llvm/llvm-project/issues/204398>`__",""

1 Paper # Paper Name Meeting Status First released version GitHub issue Notes
5 `P3319R6 <https://wg21.link/P3319R6>`__ Add an ``iota`` object for ``simd`` (and more) 2026-06 (Brno) `#204393 <https://github.com/llvm/llvm-project/issues/204393>`__
6 `P3798R1 <https://wg21.link/P3798R1>`__ The unexpected in ``std::expected`` 2026-06 (Brno) `#204394 <https://github.com/llvm/llvm-project/issues/204394>`__
7 `P3052R2 <https://wg21.link/P3052R2>`__ ``view_interface::at()`` 2026-06 (Brno) `#204395 <https://github.com/llvm/llvm-project/issues/204395>`__
8 `P4206R0 <https://wg21.link/P4206R0>`__ Revert string support in ``std::constant_wrapper`` 2026-06 (Brno) |Complete| 23 `#203336 <https://github.com/llvm/llvm-project/issues/203336>`__ To be applied as a Defect Report. Applied as a Defect Report.
9 `P3395R6 <https://wg21.link/P3395R6>`__ Fix encoding issues and add a formatter for ``std::error_code`` 2026-06 (Brno) `#204396 <https://github.com/llvm/llvm-project/issues/204396>`__
10 `P3505R4 <https://wg21.link/P3505R4>`__ Fix the default floating-point representation in ``std::format`` 2026-06 (Brno) `#204397 <https://github.com/llvm/llvm-project/issues/204397>`__ To be applied as a Defect Report.
11 `P3154R3 <https://wg21.link/P3154R3>`__ Deprecating signed character types in iostreams 2026-06 (Brno) `#204398 <https://github.com/llvm/llvm-project/issues/204398>`__

View file

@ -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,44 +28,13 @@ _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,
# ifdef _LIBCPP_COMPILER_GCC
// gcc bug: https://gcc.gnu.org/PR117392
class = typename decltype(__cw_fixed_value(_Xp))::__type
# else
class = typename decltype(_Xp)::__type
# endif
>
template <auto _Xp, class = remove_cvref_t<decltype(_Xp)>>
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 {
@ -202,7 +172,8 @@ struct __cw_operators {
template <__constexpr_param _Lp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator->*(_Lp, _Rp) noexcept
-> constant_wrapper<(_Lp::value->*_Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Lp::value->*_Rp::value)> {
return {};
}
@ -228,52 +199,62 @@ struct __cw_operators {
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator+=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value += _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value += _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator-=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value -= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value -= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator*=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value *= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value *= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator/=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value /= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value /= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator%=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value %= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value %= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator&=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value &= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value &= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator|=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value |= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value |= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator^=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value ^= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value ^= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator<<=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value <<= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value <<= _Rp::value)> {
return {};
}
template <__constexpr_param _Tp, __constexpr_param _Rp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator>>=(this _Tp, _Rp) noexcept
-> constant_wrapper<(_Tp::value >>= _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(_Tp::value >>= _Rp::value)> {
return {};
}
};
@ -285,18 +266,23 @@ concept __constexpr_callable = (__constexpr_param<remove_cvref_t<_Args>> && ...)
template <const auto& _Obj, class... _Args>
concept __constexpr_indexable = (__constexpr_param<remove_cvref_t<_Args>> && ...) && requires {
typename constant_wrapper<_Obj[remove_cvref_t<_Args>::value...]>;
typename constant_wrapper<auto(_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;
using type = constant_wrapper;
using value_type = decltype(_Xp)::__type;
static constexpr decltype((_Xp)) value = (_Xp);
using type = constant_wrapper;
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
-> constant_wrapper<(value = _Rp::value)> {
// TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
-> constant_wrapper<auto(value = _Rp::value)> {
return {};
}
@ -320,7 +306,7 @@ struct constant_wrapper : __cw_operators {
template <class... _Args>
requires __constexpr_indexable<value, _Args...>
[[nodiscard]]
_LIBCPP_HIDE_FROM_ABI static constexpr constant_wrapper<value[remove_cvref_t<_Args>::value...]>
_LIBCPP_HIDE_FROM_ABI static constexpr constant_wrapper<auto(value[remove_cvref_t<_Args>::value...])>
operator[](_Args&&...) noexcept {
return {};
}

View file

@ -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

View file

@ -64,7 +64,7 @@ __cpp_lib_common_reference 202302L <type_traits>
__cpp_lib_common_reference_wrapper 202302L <functional>
__cpp_lib_complex_udls 201309L <complex>
__cpp_lib_concepts 202207L <concepts>
__cpp_lib_constant_wrapper 202603L <utility>
__cpp_lib_constant_wrapper 202606L <utility>
__cpp_lib_constexpr_algorithms 202306L <algorithm> <utility>
201806L // C++20
__cpp_lib_constexpr_bitset 202207L <bitset>
@ -563,7 +563,7 @@ __cpp_lib_void_t 201411L <type_traits>
# undef __cpp_lib_bind_front
# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
# define __cpp_lib_constant_wrapper 202603L
# define __cpp_lib_constant_wrapper 202606L
# undef __cpp_lib_constexpr_algorithms
# define __cpp_lib_constexpr_algorithms 202306L
# define __cpp_lib_constexpr_flat_map 202502L

View file

@ -404,8 +404,8 @@
# ifndef __cpp_lib_constant_wrapper
# error "__cpp_lib_constant_wrapper should be defined in c++26"
# endif
# if __cpp_lib_constant_wrapper != 202603L
# error "__cpp_lib_constant_wrapper should have the value 202603L in c++26"
# if __cpp_lib_constant_wrapper != 202606L
# error "__cpp_lib_constant_wrapper should have the value 202606L in c++26"
# endif
# ifndef __cpp_lib_constexpr_algorithms

View file

@ -6609,8 +6609,8 @@
# ifndef __cpp_lib_constant_wrapper
# error "__cpp_lib_constant_wrapper should be defined in c++26"
# endif
# if __cpp_lib_constant_wrapper != 202603L
# error "__cpp_lib_constant_wrapper should have the value 202603L in c++26"
# if __cpp_lib_constant_wrapper != 202606L
# error "__cpp_lib_constant_wrapper should have the value 202606L in c++26"
# endif
# ifndef __cpp_lib_constexpr_algorithms

View file

@ -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; };

View file

@ -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]>);

View file

@ -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,17 +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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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>;

View file

@ -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}}

View file

@ -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*>);

View file

@ -148,7 +148,12 @@ static_assert(!HasPlus<std::constant_wrapper<NoOps{}>>);
static_assert(!HasMinus<std::constant_wrapper<NoOps{}>>);
static_assert(!HasBitNot<std::constant_wrapper<NoOps{}>>);
static_assert(!HasNot<std::constant_wrapper<NoOps{}>>);
// TODO: Remove this guard when Clang 21 is no longer supported.
#if defined(TEST_CLANG_VER) && TEST_CLANG_VER >= 2200 // https://llvm.org/PR151531
static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);
#endif
static_assert(!HasDeref<std::constant_wrapper<NoOps{}>>);
// The operators from constant_wrapper do not exist, but they can be implicited converted

View file

@ -337,7 +337,7 @@ feature_test_macros = [
{
"name": "__cpp_lib_constant_wrapper",
"values": {
"c++26": 202603,
"c++26": 202606,
},
"headers": ["utility"],
},