[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:
parent
08d766ba6d
commit
a88b88bdd3
18 changed files with 97 additions and 296 deletions
|
|
@ -432,7 +432,7 @@ Status
|
|||
---------------------------------------------------------- -----------------
|
||||
``__cpp_lib_bitset`` ``202306L``
|
||||
---------------------------------------------------------- -----------------
|
||||
``__cpp_lib_constant_wrapper`` ``202603L``
|
||||
``__cpp_lib_constant_wrapper`` ``202606L``
|
||||
---------------------------------------------------------- -----------------
|
||||
``__cpp_lib_constexpr_algorithms`` ``202306L``
|
||||
---------------------------------------------------------- -----------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-----------------------------
|
||||
|
|
|
|||
|
|
@ -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>`__",""
|
||||
|
|
|
|||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; };
|
||||
|
|
|
|||
|
|
@ -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]>);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
@ -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*>);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ feature_test_macros = [
|
|||
{
|
||||
"name": "__cpp_lib_constant_wrapper",
|
||||
"values": {
|
||||
"c++26": 202603,
|
||||
"c++26": 202606,
|
||||
},
|
||||
"headers": ["utility"],
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue