C++ Logo

std-proposals

Advanced search

[std-proposals] Make std::make_from_tuple SFINAE friendly

From: Yrong <yronglin777_at_[hidden]>
Date: Fri, 29 Mar 2024 23:28:20 +0800
Hello,

I was wondering if I can submit this improvement as a short proposal paper.

*Discussion:*

LWG3528 constraint *`*constexpr T *make-from-tuple-impl*(Tuple&& t,
index_sequence<I...>)*` with `*requires is_constructible_v<T,
decltype(get<I>(declval<Tuple>()))...>`.
When someone write SFINAE code like below to check whether T can make from
tuple, they may meet hard errors like "*no matching function for call to
'make-from-tuple-impl'...*".

```
template <class T, class Tuple, class = void>
inline constexpr bool has_make_from_tuple = false;

template <class T, class Tuple>
inline constexpr bool
has_make_from_tuple<T, Tuple,
std::void_t<decltype(std::make_from_tuple<T>(std::declval<Tuple>()))>>
= true;

struct A { int a; };

static_assert(!has_make_from_tuple<int*, std::tuple<A*>>);
```


*Proposed resolution:*

This wording is relative to N4971 <https://wg21.link/N4971>.

   1.

   Edit 22.4.6 [tuple.apply] <https://wg21.link/tuple.apply> as indicated:

template<class T, *tuple-like*
<https://eel.is/c++draft/tuple.like#concept:tuple-like> Tuple> constexpr T
make_from_tuple(Tuple&& t); *-3- Let I be the pack 0, 1, ...,
(tuple_size_v<remove_reference_t<Tuple>> - 1).*-4- Constraints:
is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...> is true.
-5- *Mandates*: If tuple_size_v<remove_reference_t<Tuple>> is 1, then
reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>
 is false. <https://eel.is/c++draft/tuple.apply#3.sentence-1>

-6- *Effects*: Given the exposition-only function template:
namespace std { template<class T, *tuple-like*
<https://eel.is/c++draft/tuple.like#concept:tuple-like> Tuple, size_t... I>
requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...>
constexpr T *make-from-tuple-impl*(Tuple&& t, index_sequence<I...>) {
// *exposition
only* return T(get<I>(std::forward<Tuple>(t))...); } }
Equivalent to:return *make-from-tuple-impl*<T>( std::forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});

[*Note 1*:
The type of T must be supplied as an explicit template parameter, as it
cannot be deduced from the argument list.
<https://eel.is/c++draft/tuple#apply-4.sentence-2>
 — *end note*]

Implementation Experience:
I've implement this improvement in libc++ and STL.
https://github.com/llvm/llvm-project/pull/85263
https://github.com/microsoft/STL/pull/4528

Thanks,
Yrong

Received on 2024-03-29 15:28:35