Godboltでclangトランクとlibc ++を使用してstd::span
の最新の仕様をいじってみましたが、いくつかのコンストラクターが混乱しています。
特に、プレーンな古い配列とstd::array
のコンストラクタが他のコンテナとは異なることがわかりました。
たとえば、次のコードはコンパイルされているように見えます。
std::vector<int*> v = {nullptr, nullptr};
std::span<const int* const> s{v};
しかし、これはしません:
std::array<int*, 2> a = {nullptr, nullptr};
std::span<const int* const> s{a};
これは コンストラクターがcppreference.comで記述されている方法 と一致しているようです。なぜこれが当てはまるのかを理解するのに苦労しています。誰かが光を当てることはできますか?
これは見落としのようです。配列コンストラクターは現在次のように指定されています。
_template<size_t N> constexpr span(array<value_type, N>& arr) noexcept;
template<size_t N> constexpr span(const array<value_type, N>& arr) noexcept;
_
ただし、おそらく次のように指定する必要があります。
_template<class T, size_t N>
requires std::convertible_to<T(*)[], ElementType(*)[]>
constexpr span(array<T, N>& arr) noexcept;
template<class T, size_t N>
requires std::convertible_to<const T(*)[], ElementType(*)[]>
constexpr span(const array<T, N>& arr) noexcept;
_
安全に実行できるため、サンプルをコンパイルできます。 LWGの問題を提出しました。これは現在 LWG 3255 です。
表現alreadyには、この制約が [span.cons]/11 で指定されています:
_template<size_t N> constexpr span(element_type (&arr)[N]) noexcept; template<size_t N> constexpr span(array<value_type, N>& arr) noexcept; template<size_t N> constexpr span(const array<value_type, N>& arr) noexcept;
_制約:
- _
extent == dynamic_extent || N == extent
_はtrue
であり、remove_pointer_t<decltype(data(arr))>(*)[]
はElementType(*)[]
に変換可能です。
したがって、すでに適切な制約があります。 data(arr)
がこれらのいずれの場合でも実際には依存していないため、制約はごくわずかに満たされます。これらのテンプレートを作成するだけです。