From: Yihan Wang Date: Mon, 9 Jun 2025 10:07:51 +0000 (+0100) Subject: libstdc++: Implement LWG3528 make_from_tuple can perform (the equivalent of) a C... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=73edc003c0a8f0badc7027e6deefd3a573300b03;p=thirdparty%2Fgcc.git libstdc++: Implement LWG3528 make_from_tuple can perform (the equivalent of) a C-style cast Implement LWG3528 to make std::make_from_tuple SFINAE friendly. libstdc++-v3/ChangeLog: * include/std/tuple (__can_make_from_tuple): New variable template. (__make_from_tuple_impl): Add static_assert. (make_from_tuple): Constrain using __can_make_from_tuple. * testsuite/20_util/tuple/dr3528.cc: New test. Signed-off-by: Yihan Wang Co-authored-by: Jonathan Wakely Reviewed-by: Tomasz KamiƄski --- diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 2e69af13a98..b39ce710984 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -2939,19 +2939,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #ifdef __cpp_lib_make_from_tuple // C++ >= 17 + template >>> + constexpr bool __can_make_from_tuple = false; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3528. make_from_tuple can perform (the equivalent of) a C-style cast + template + constexpr bool __can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>> + = is_constructible_v<_Tp, + decltype(std::get<_Idx>(std::declval<_Tuple>()))...>; + template constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) - { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } + { + static_assert(__can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>); + return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); + } #if __cpp_lib_tuple_like // >= C++23 template #else template #endif - constexpr _Tp + constexpr auto make_from_tuple(_Tuple&& __t) noexcept(__unpack_std_tuple) +#ifdef __cpp_concepts // >= C++20 + -> _Tp + requires __can_make_from_tuple<_Tp, _Tuple> +#else + -> __enable_if_t<__can_make_from_tuple<_Tp, _Tuple>, _Tp> +#endif { constexpr size_t __n = tuple_size_v>; #if __has_builtin(__reference_constructs_from_temporary) diff --git a/libstdc++-v3/testsuite/20_util/tuple/dr3528.cc b/libstdc++-v3/testsuite/20_util/tuple/dr3528.cc new file mode 100644 index 00000000000..c20ff95e12d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/dr3528.cc @@ -0,0 +1,46 @@ +// { dg-do compile { target c++17 } } + +// LWG 3528. make_from_tuple can perform (the equivalent of) a C-style cast + +#include +#include +#include + +template +using make_t = decltype(std::make_from_tuple(std::declval())); + +template +constexpr bool can_make = false; +template +constexpr bool can_make>> = true; + +static_assert( can_make> ); +static_assert( can_make&> ); +static_assert( can_make&> ); +static_assert( can_make> ); +static_assert( can_make&&> ); +static_assert( can_make, std::pair> ); +static_assert( can_make, std::array> ); +static_assert( can_make> ); +static_assert( can_make> ); +static_assert( can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make&> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make> ); + +struct Two +{ + Two(const char*, int); +}; + +static_assert( can_make> ); +static_assert( ! can_make> ); +static_assert( can_make> ); +static_assert( ! can_make> ); +static_assert( ! can_make, std::array> );