Date: Thu, 10 Mar 2022 13:22:33 +0100
Thanks @Arthur and @Zhihao.
About these two comments:
> You can (and should) std::move(arr[Idx]).
and
> Because of everything you said about MSVC, I suggest that your proposal
> (and vendors' implementations too) should actually say
>
> return std::move(arr[Idx]); // correct in practice
>
> not
>
> return std::move(arr)[Idx]; // pedantically correct but fails on MSVC
>
> The effect is the same, on everything-but-MSVC; and on MSVC the former
> is preferable. (AFAIK, both are equally correct as far as the paper
> standard is concerned.)
I can't understand whether there's a real difference in either of the
return statements if the return type of std::get is T&&. I'd expect an
implicit cast to T&& on MSCV (and no cast on other compilers). Am I
missing something here?
> In your actual proposal, please don't overspecify that tuple_size<X>
> must inherit from tuple_size<Y>; that puts unnecessary and inefficient
> constraints on the vendor.
Why would you consider this an overspecification? My point here is the
tuple size of any cv-qualified array is the same as the unqualified
array.
>From https://en.cppreference.com/w/cpp/utility/tuple_size I can see the
standard implementation does it differently:
template< class T >
struct tuple_size< const T >
: integral_constant<size_t, tuple_size<T>::value> { };
But, still, tuple_size<T const> instanciates tuple_size<T>.
Also, from the page linked above, I learn the volatile specializations
are deprecated (both for tuple_size and tuple_element). So I should drop
them from the proposal.
> However, I think you could actually get away with only this C++20ism
> instead:
>
> template<class T, size_t N>
> requires (!is_same_v<T, remove_cv_t<T>>)
> struct tuple_size<T[N]> : public integral_constant<size_t, N> { };
Thanks for this suggestion: I would have never considered it. I don't
understand the negation in the requires clause: did you actually mean
the following?
requires (is_same_v<T, remove_cv_t<T>>)
> I don't understand why you need this layer of indirection at all, even
> before applying the trick above.
I needed to implement specializations of tuple_element for cv-qualified
arrays; otherwise tuple_element<T const[N]>, say, would match both the
newly introduced <T[N]> and the existing <T const> specializations. I
didn't want to reimplement tuple_element four times, so I delegated to
array_tuple_element. Is this bad somehow?
> Also, and slightly scarier, but still not too bad:
>
> auto a = std::make_tuple("hello");
> assert(std::tuple_size_v<decltype(a)> == 1); // OK
>
> auto b = std::make_from_tuple("world");
> assert(std::tuple_size_v<decltype(b)> == 6); // cursed
>
I don't think this code is going to be an issue as it doesn't compile:
you must pass the type you want to construct to std::make_from_tuple as
an explicit template parameter. However, if I get your point:
* "hello" is treated as a char const* (because std::make_tuple applies
std::decay to its arguments);
* "world" is treated as a char const(&)[6];
And this may lead to confusion or inconsistency. Is this correct?
About these two comments:
> You can (and should) std::move(arr[Idx]).
and
> Because of everything you said about MSVC, I suggest that your proposal
> (and vendors' implementations too) should actually say
>
> return std::move(arr[Idx]); // correct in practice
>
> not
>
> return std::move(arr)[Idx]; // pedantically correct but fails on MSVC
>
> The effect is the same, on everything-but-MSVC; and on MSVC the former
> is preferable. (AFAIK, both are equally correct as far as the paper
> standard is concerned.)
I can't understand whether there's a real difference in either of the
return statements if the return type of std::get is T&&. I'd expect an
implicit cast to T&& on MSCV (and no cast on other compilers). Am I
missing something here?
> In your actual proposal, please don't overspecify that tuple_size<X>
> must inherit from tuple_size<Y>; that puts unnecessary and inefficient
> constraints on the vendor.
Why would you consider this an overspecification? My point here is the
tuple size of any cv-qualified array is the same as the unqualified
array.
>From https://en.cppreference.com/w/cpp/utility/tuple_size I can see the
standard implementation does it differently:
template< class T >
struct tuple_size< const T >
: integral_constant<size_t, tuple_size<T>::value> { };
But, still, tuple_size<T const> instanciates tuple_size<T>.
Also, from the page linked above, I learn the volatile specializations
are deprecated (both for tuple_size and tuple_element). So I should drop
them from the proposal.
> However, I think you could actually get away with only this C++20ism
> instead:
>
> template<class T, size_t N>
> requires (!is_same_v<T, remove_cv_t<T>>)
> struct tuple_size<T[N]> : public integral_constant<size_t, N> { };
Thanks for this suggestion: I would have never considered it. I don't
understand the negation in the requires clause: did you actually mean
the following?
requires (is_same_v<T, remove_cv_t<T>>)
> I don't understand why you need this layer of indirection at all, even
> before applying the trick above.
I needed to implement specializations of tuple_element for cv-qualified
arrays; otherwise tuple_element<T const[N]>, say, would match both the
newly introduced <T[N]> and the existing <T const> specializations. I
didn't want to reimplement tuple_element four times, so I delegated to
array_tuple_element. Is this bad somehow?
> Also, and slightly scarier, but still not too bad:
>
> auto a = std::make_tuple("hello");
> assert(std::tuple_size_v<decltype(a)> == 1); // OK
>
> auto b = std::make_from_tuple("world");
> assert(std::tuple_size_v<decltype(b)> == 6); // cursed
>
I don't think this code is going to be an issue as it doesn't compile:
you must pass the type you want to construct to std::make_from_tuple as
an explicit template parameter. However, if I get your point:
* "hello" is treated as a char const* (because std::make_tuple applies
std::decay to its arguments);
* "world" is treated as a char const(&)[6];
And this may lead to confusion or inconsistency. Is this correct?
Received on 2022-03-10 12:19:48