Почему span-массив и std::array конструкторы отличаются от своих контейнерных конструкторов - программирование
Подтвердить что ты не робот

Почему span-массив и std::array конструкторы отличаются от своих контейнерных конструкторов

Я играл с последней спецификацией для std::span, используя ствол лязга и libc++ на Godbolt, и нахожу некоторых конструкторов непонятными.

В частности, я считаю, что конструкторы из простого старого массива и 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, я просто пытаюсь понять, почему это так. Кто-нибудь может пролить свет?

4b9b3361

Ответ 1

Это похоже на недосмотр. Конструкторы массива в настоящее время определены как:

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.


В формулировке уже есть это ограничение, указанное в [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;

Constraints:

  • extent == dynamic_­extent || N == extent - это true, а
  • remove_­pointer_­t<decltype(data(arr))>(*)[] конвертируется в ElementType(*)[].

Таким образом, у нас уже есть правильное ограничение. Просто data(arr) на самом деле не зависит ни в одном из этих случаев, поэтому ограничение выполняется тривиально. Нам просто нужно сделать эти шаблоны.