[libcxx-commits] [libcxx] [libc++] Implement LWG3528 (`make_from_tuple` can perform (the equivalent of) a C-style cast) (PR #85263)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Mar 17 08:31:29 PDT 2024
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/85263
>From fc8c1a24f09c8860269fbdcfb0b285ffd19f427c Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 15 Mar 2024 00:48:08 +0800
Subject: [PATCH 1/3] [libc++] Implement LWG3528 (`make_from_tuple` can perform
(the equivalent of) a C-style cast)
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/docs/Status/Cxx23Issues.csv | 2 +-
libcxx/include/tuple | 12 ++-
.../tuple.apply/make_from_tuple.verify.cpp | 74 +++++++++++++++++++
3 files changed, 85 insertions(+), 3 deletions(-)
create mode 100644 libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index e00345533b865d..0fd58649b0cf64 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -77,7 +77,7 @@
`3523 <https://wg21.link/LWG3523>`__,"``iota_view::sentinel`` is not always ``iota_view``'s sentinel","June 2021","","","|ranges|"
`3526 <https://wg21.link/LWG3526>`__,"Return types of ``uses_allocator_construction_args`` unspecified","June 2021","",""
`3527 <https://wg21.link/LWG3527>`__,"``uses_allocator_construction_args`` handles rvalue pairs of rvalue references incorrectly","June 2021","",""
-`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","",""
+`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","|Complete|","19.0"
`3529 <https://wg21.link/LWG3529>`__,"``priority_queue(first, last)`` should construct ``c`` with ``(first, last)``","June 2021","|Complete|","14.0"
`3530 <https://wg21.link/LWG3530>`__,"``BUILTIN-PTR-MEOW`` should not opt the type out of syntactic checks","June 2021","",""
`3532 <https://wg21.link/LWG3532>`__,"``split_view<V, P>::inner-iterator<true>::operator++(int)`` should depend on ``Base``","June 2021","","","|ranges|"
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 8808db6739fb9b..1ef546c5b2153d 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1423,8 +1423,16 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&&
typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{}))
template <class _Tp, class _Tuple, size_t... _Idx>
-inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
- _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
+inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
+ noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)))
+#if _LIBCPP_STD_VER >= 20
+ requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>
+#endif
+{
+ static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>,
+ "Cannot constructible target type from the fields of the argument tuple.");
+ return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...);
+}
template <class _Tp, class _Tuple>
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
new file mode 100644
index 00000000000000..9bdca4dc7813cb
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <tuple>
+
+// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
+
+#include <tuple>
+
+int main() {
+ // clang-format off
+#if _LIBCPP_STD_VER <= 20
+ // reinterpret_cast
+ {
+ struct B { int b; } b;
+ std::tuple<B *> t{&b};
+ auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
+ (void)a;
+ }
+
+ // const_cast
+ {
+ const char *str = "Hello";
+ std::tuple<const char *> t{str};
+ auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
+ (void)a;
+ }
+
+ // static_cast
+ {
+ struct B {};
+ struct C : public B {} c;
+ B &br = c;
+ std::tuple<const B&> t{br};
+ auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
+ (void)a;
+ }
+#else
+ // reinterpret_cast
+ {
+ struct B { int b; } b;
+ std::tuple<B *> t{&b};
+ auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}}
+ (void)a;
+ }
+
+ // const_cast
+ {
+ const char *str = "Hello";
+ std::tuple<const char *> t{str};
+ auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}}
+ (void)a;
+ }
+
+ // static_cast
+ {
+ struct B {};
+ struct C : public B {} c;
+ B &br = c;
+ std::tuple<const B &> t{br};
+ auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}}
+ (void)a;
+ }
+#endif
+ // clang-format on
+ return 0;
+}
>From 14d6e7168e52c3236685dc3d947a37d9926bf8a2 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 15 Mar 2024 00:54:47 +0800
Subject: [PATCH 2/3] Add comment after #endif
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/include/tuple | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 1ef546c5b2153d..0839fa7d1280a0 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1427,7 +1427,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t,
noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)))
#if _LIBCPP_STD_VER >= 20
requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>
-#endif
+#endif // _LIBCPP_STD_VER >= 20
{
static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>,
"Cannot constructible target type from the fields of the argument tuple.");
>From 14ae30770795c9d06ca83b23bf903922965b6ea0 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 15 Mar 2024 20:59:40 +0800
Subject: [PATCH 3/3] Address comments and uses SFINAE to remove the function
from the overload set
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/include/tuple | 16 ++++++-----
.../tuple.apply/make_from_tuple.verify.cpp | 28 -------------------
2 files changed, 9 insertions(+), 35 deletions(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 0839fa7d1280a0..4d0e89d74ba14b 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1422,17 +1422,19 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&&
std::forward<_Tuple>(__t),
typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{}))
+#if _LIBCPP_STD_VER >= 20
template <class _Tp, class _Tuple, size_t... _Idx>
-inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
+inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>)
noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)))
-#if _LIBCPP_STD_VER >= 20
- requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>
-#endif // _LIBCPP_STD_VER >= 20
-{
- static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>,
- "Cannot constructible target type from the fields of the argument tuple.");
+ requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> {
return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...);
}
+#else
+template <class _Tp, class _Tuple, size_t... _Idx>
+inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>,
+ enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr)
+ _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
+#endif // _LIBCPP_STD_VER >= 20
template <class _Tp, class _Tuple>
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 9bdca4dc7813cb..d5905404d43a35 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -16,33 +16,6 @@
int main() {
// clang-format off
-#if _LIBCPP_STD_VER <= 20
- // reinterpret_cast
- {
- struct B { int b; } b;
- std::tuple<B *> t{&b};
- auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
- (void)a;
- }
-
- // const_cast
- {
- const char *str = "Hello";
- std::tuple<const char *> t{str};
- auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
- (void)a;
- }
-
- // static_cast
- {
- struct B {};
- struct C : public B {} c;
- B &br = c;
- std::tuple<const B&> t{br};
- auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}}
- (void)a;
- }
-#else
// reinterpret_cast
{
struct B { int b; } b;
@@ -68,7 +41,6 @@ int main() {
auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}}
(void)a;
}
-#endif
// clang-format on
return 0;
}
More information about the libcxx-commits
mailing list