web-dev-qa-db-ja.com

spanの配列とstd :: arrayコンストラクターがコンテナーコンストラクターと異なるのはなぜですか

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で記述されている方法 と一致しているようです。なぜこれが当てはまるのかを理解するのに苦労しています。誰かが光を当てることはできますか?

14
John M

これは見落としのようです。配列コンストラクターは現在次のように指定されています。

_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)がこれらのいずれの場合でも実際には依存していないため、制約はごくわずかに満たされます。これらのテンプレートを作成するだけです。

8
Barry