We need to apply remove_cvref_t on decltype(_Xv) for default template argument
due PR115314. The constant_wrapper::value is declared as decltype((__Xv)) due
PR125188.

libstdc++-v3/ChangeLog:

        * include/bits/funcref_impl.h (function_ref::function_ref): Rename
        template parameter from __cwfn to __fn and use it direclty.
        * include/bits/funcwrap.h (function_ref): Rename template parameter
        to __fn.
        (std::constant_wrapper): Use auto as non-type template parameter,
        and refeference it as value.
        * include/bits/utility.h (__CwFixedValue): Remove.
        * testsuite/20_util/constant_wrapper/generic.cc: Remove arrays
        and string literal tests. Add test for address of value.
        * testsuite/20_util/constant_wrapper/other_wrappers.cc:
        Remove test_array.

Reviewed-by: Patrick Palka <[email protected]>
---
v2 clearly marks is as RFC and applies suggestion from Patrick:
- name second template parameter in forward declaration
- reffer to PR115314 instead of PR117004

 libstdc++-v3/include/bits/funcref_impl.h      | 15 ++--
 libstdc++-v3/include/bits/funcwrap.h          |  8 +-
 libstdc++-v3/include/bits/utility.h           | 50 +++----------
 .../20_util/constant_wrapper/generic.cc       | 74 ++++++-------------
 .../constant_wrapper/other_wrappers.cc        | 14 ----
 .../constant_wrapper/type_param_neg.cc        |  9 +++
 6 files changed, 52 insertions(+), 118 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/20_util/constant_wrapper/type_param_neg.cc

diff --git a/libstdc++-v3/include/bits/funcref_impl.h 
b/libstdc++-v3/include/bits/funcref_impl.h
index 9fc8432b42b..c51e1a54ff2 100644
--- a/libstdc++-v3/include/bits/funcref_impl.h
+++ b/libstdc++-v3/include/bits/funcref_impl.h
@@ -132,12 +132,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 4256. Incorrect constrains for function_ref constructors from nontype
       /// Target object is __fn. There is no bound object.
-      template<auto __cwfn, typename _Fn>
+      template<auto __fn, typename _Fn>
        requires __is_invocable_using<const _Fn&>
        constexpr
-       function_ref(constant_wrapper<__cwfn, _Fn>) noexcept
+       function_ref(constant_wrapper<__fn, _Fn>) noexcept
        {
-         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
          if constexpr (sizeof...(_ArgTypes) > 0)
            if constexpr ((... && _ConstExprParam<remove_cvref_t<_ArgTypes>>))
              static_assert(!requires {
@@ -153,14 +152,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)).
       /// Bound object is object referenced by second parameter.
-      template<auto __cwfn, typename _Fn, typename _Up,
+      template<auto __fn, typename _Fn, typename _Up,
               typename _Td = remove_reference_t<_Up>>
        requires (!is_rvalue_reference_v<_Up&&>)
                 && __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV&>
        constexpr
-       function_ref(constant_wrapper<__cwfn, _Fn>, _Up&& __ref) noexcept
+       function_ref(constant_wrapper<__fn, _Fn>, _Up&& __ref) noexcept
        {
-         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
          if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
            static_assert(__fn != nullptr);
 
@@ -176,12 +174,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Target object is equivalent to std::bind_front<_fn>(__ptr).
       /// Bound object is object pointed by second parameter (if any).
-      template< auto __cwfn, typename _Fn, typename _Td>
+      template<auto __fn, typename _Fn, typename _Td>
        requires __is_invocable_using<const _Fn&, _Td _GLIBCXX_MOF_CV*>
        constexpr
-       function_ref(constant_wrapper<__cwfn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) 
noexcept
+       function_ref(constant_wrapper<__fn, _Fn>, _Td _GLIBCXX_MOF_CV* __ptr) 
noexcept
        {
-         constexpr const _Fn& __fn = constant_wrapper<__cwfn, _Fn>::value;
          if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>)
            static_assert(__fn != nullptr);
          if constexpr (is_member_pointer_v<_Fn>)
diff --git a/libstdc++-v3/include/bits/funcwrap.h 
b/libstdc++-v3/include/bits/funcwrap.h
index 07163f3a5a3..670efa63b4a 100644
--- a/libstdc++-v3/include/bits/funcwrap.h
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -592,16 +592,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     requires is_function_v<_Fn>
     function_ref(_Fn*) -> function_ref<_Fn>;
 
-  template<auto __cwfn, typename _Fn>
+  template<auto __fn, typename _Fn>
     requires is_function_v<remove_pointer_t<_Fn>>
-    function_ref(constant_wrapper<__cwfn, _Fn>)
+    function_ref(constant_wrapper<__fn, _Fn>)
       -> function_ref<remove_pointer_t<_Fn>>;
 
-  template<auto __cwfn, typename _Fn, typename _Tp,
+  template<auto __fn, typename _Fn, typename _Tp,
           typename _SignaturePtr =
             decltype(__polyfunc::__deduce_funcref<_Fn, _Tp&>())>
     requires (!is_void_v<_SignaturePtr>)
-    function_ref(constant_wrapper<__cwfn, _Fn>, _Tp&&)
+    function_ref(constant_wrapper<__fn, _Fn>, _Tp&&)
       -> function_ref<remove_pointer_t<_SignaturePtr>>;
 
   /// @cond undocumented
diff --git a/libstdc++-v3/include/bits/utility.h 
b/libstdc++-v3/include/bits/utility.h
index dac02e4a479..9bfc0c3d17f 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -141,42 +141,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #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>
+  // remove_cvref_t needed due PR117004
+  template<auto _Xv, typename = remove_cvref_t<decltype(_Xv)>>
     struct constant_wrapper;
 
   template<typename _Tp>
@@ -430,12 +396,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return {}; }
   };
 
-  template<_CwFixedValue _Xv, typename>
+  template<auto _Xv, typename _Vt>
   struct constant_wrapper : _CwOperators
   {
-    static constexpr const auto& value = _Xv._M_data;
+    // Use decltype((_Xv)) instead of decltype(auto) due PR125188
+    static constexpr decltype((_Xv)) value = (_Xv);
     using type = constant_wrapper;
-    using value_type = typename decltype(_Xv)::__type;
+    using value_type = decltype(_Xv);
+    static_assert(is_same_v<value_type, _Vt>);
 
     template<_ConstExprParam _Right>
       constexpr auto
@@ -490,8 +458,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<auto __cw, typename _Fn>
     constexpr bool __is_constant_wrapper_v<constant_wrapper<__cw, _Fn>> = true;
 
-  template<_CwFixedValue _Tp>
-    constexpr auto cw = constant_wrapper<_Tp>{};
+  template<auto _Xv>
+    constexpr auto cw = constant_wrapper<_Xv>{};
 #endif
 
 #ifdef __glibcxx_integer_sequence // C++ >= 14
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc 
b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
index bd41fc4ca3a..f256e08fe0b 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/generic.cc
@@ -12,54 +12,6 @@ check_same(auto actual, auto expected)
   static_assert(std::same_as<decltype(actual), decltype(expected)>);
 };
 
-
-constexpr void
-test_c_arrays()
-{
-  constexpr double x[] = {1.1, 2.2, 3.3};
-  auto cx = std::cw<x>;
-  auto access = [](auto x, size_t i)
-  { return x[i]; };
-
-  check_same(std::cw<x>[0], x[0]);
-  check_same(std::cw<x>[1], x[1]);
-  check_same(std::cw<x>[2], x[2]);
-
-  check_same(cx[std::cw<0>], std::cw<x[0]>);
-  check_same(cx[std::cw<1>], std::cw<x[1]>);
-  check_same(cx[std::cw<2>], std::cw<x[2]>);
-}
-
-constexpr size_t
-deduce_cstr_size(auto str)
-{
-  size_t sz = 0;
-  while(str[sz++] != '\0') { }
-  return sz;
-}
-
-constexpr void
-test_string_literals()
-{
-  auto foo = std::cw<"foo">;
-  constexpr const typename decltype(foo)::value_type & cstr = foo;
-  constexpr size_t N = std::size(cstr);
-  constexpr auto foo_view = std::string_view(cstr, N-1);
-
-  constexpr const char (&cstr1)[deduce_cstr_size(foo)] = foo;
-  constexpr size_t N1 = std::size(cstr);
-
-  static_assert(static_cast<char const*>(cstr) ==
-               static_cast<char const*>(cstr1));
-  static_assert(N1 == N);
-
-  static_assert(foo[0] == 'f');
-  static_assert(foo[1] == 'o');
-  static_assert(foo[2] == 'o');
-  static_assert(foo[3] == '\0');
-  static_assert(static_cast<char const *>(foo) == foo_view);
-}
-
 constexpr bool
 convert_constexpr(auto c)
 {
@@ -93,6 +45,29 @@ test_ints()
   VERIFY(two + 3 == std::cw<5>);
 }
 
+constexpr void
+test_objects()
+{
+  if consteval {
+    return;
+  }
+
+  auto check = []<auto V>
+  {
+    auto* ptr1 = &V, *ptr2= &std::constant_wrapper<V>::value;
+    VERIFY(ptr1 == ptr2); 
+    VERIFY(&V == &std::constant_wrapper<V>::value);
+    std::constant_wrapper<V> cw;
+    VERIFY(&V == &cw.value);
+  };
+
+  struct Obj
+  { int x; };
+
+  check.operator()<Obj{10}>();
+  check.operator()<Obj{20}>();
+}
+
 constexpr int
 add(int i, int j)
 { return i + j; }
@@ -586,12 +561,11 @@ test_assignment()
             std::cw<ConstAssignable{2}>);
 }
 
-
 constexpr bool
 test_all()
 {
-  test_c_arrays();
   test_ints();
+  test_objects();
   test_function_object();
   test_function_pointer();
   test_indexable1();
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 fe45c5a8516..a5e2189ef80 100644
--- a/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/other_wrappers.cc
@@ -30,19 +30,6 @@ test_mix_integer_constant()
   check_same(w2 + c3, std::cw<5>);
 }
 
-constexpr void
-test_array()
-{
-  constexpr double x[] = {1.1, 2.2, 3.3};
-  auto cx = std::cw<x>;
-  auto i2 = std::integral_constant<int, 2>{};
-  auto w2 = ConstWrapper<int, 2>{};
-
-  check_same(x[i2], x[2]);
-  check_same(cx[i2], std::cw<x[2]>);
-  check_same(cx[w2], std::cw<x[2]>);
-}
-
 constexpr void
 test_function_object()
 {
@@ -61,7 +48,6 @@ constexpr bool
 test_all()
 {
   test_mix_integer_constant();
-  test_array();
   test_function_object();
   return true;
 }
diff --git a/libstdc++-v3/testsuite/20_util/constant_wrapper/type_param_neg.cc 
b/libstdc++-v3/testsuite/20_util/constant_wrapper/type_param_neg.cc
new file mode 100644
index 00000000000..48895091611
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/constant_wrapper/type_param_neg.cc
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++26 } }
+#include <utility>
+
+std::constant_wrapper<1, float> c1;      // { dg-error "from here" } 
+std::constant_wrapper<1.0, int> c2;      // { dg-error "from here" }
+std::constant_wrapper<1, int const> c3;  // { dg-error "from here" }
+std::constant_wrapper<1, int const&> c4; // { dg-error "from here" }
+
+// { dg-prune-output "static assertion failed" }
-- 
2.54.0

Reply via email to