Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ span's C style array constructor need type_identity_t?

The C style array constructor for span is specified as follows

template<size_t N> constexpr span(
   type_identity_t<element_type> (&arr)[N]) noexcept;

Why is type_identity_t necessary? instead of just:

template<size_t N> constexpr span(
   element_type (&arr)[N]) noexcept;

As was originally defined in this proposal?

like image 785
cbhattac Avatar asked Dec 05 '25 23:12

cbhattac


1 Answers

As cbhattac's answer explains, the problem was that span's deduction guide's picked the wrong overload.

In issue3369 a fix was developed.

The core problem was that:

template <size_t Size>
  requires (Extent == dynamic_extent || Extent == Size)
span(T (&)[Size]) {}

ctor generates an implicit deduction guide, and so does

template <typename T, size_t Extent>
span(T (&)[Extent]) -> span<T, Extent>;

The constructor builds a span with variable length, and the deduction guide builds one with a fixed length.

When passed an array of fixed length, the ideal deduced span should also be of fixed length. But it wasn't happening.

Naively, explicit deduction guilds beat ones produced from constructors, but that isn't true -- the constructor here is more constrained due to the requires (Extent == dynamic_extent || Extent == Size) clause. So it beats the deduction guide.

To fix this, type_identity_t<T> was used to block CTAD with this constructor completely. (An alternative that would also work was to add a trivial constraint to the deduction guide).

like image 57
Yakk - Adam Nevraumont Avatar answered Dec 07 '25 15:12

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!