为什么 span 的数组和 std::array 构造函数与其容器构造函数不同
Why are span's array and std::array constructors different from its container constructors
我一直在使用 Godbolt 上的 clang trunk 和 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};
这似乎符合the way the constructors are described on 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.
措辞已经在[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
is true
, and
remove_pointer_t<decltype(data(arr))>(*)[]
is convertible to ElementType(*)[]
.
所以我们已经有了正确的约束条件。只是 data(arr)
在任何这些情况下实际上都不依赖,所以约束很容易满足。我们只需要制作这些模板。
我一直在使用 Godbolt 上的 clang trunk 和 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};
这似乎符合the way the constructors are described on 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.
措辞已经在[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
istrue
, andremove_pointer_t<decltype(data(arr))>(*)[]
is convertible toElementType(*)[]
.
所以我们已经有了正确的约束条件。只是 data(arr)
在任何这些情况下实际上都不依赖,所以约束很容易满足。我们只需要制作这些模板。