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
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