Reputation: 273
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?
Upvotes: 4
Views: 233
Reputation: 275820
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).
Upvotes: 1