std::span 构造函数,libcxx 与 libstdc++,模板与非模板?

std::span constructor, libcxx vs libstdc++, template vs non-template?

浏览 the code of libcxx's std::span, I noticed that the first two value constructors (number 2 and 3 on cppreference) 不是模板。

_LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}
    { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
_LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
    { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }

而不是 cppreference 页面上显示的模板类型 ItEnd,它们直接使用 pointer 类型。所以我想知道 libcxx 代码是否符合要求。

我想要一个比较点,所以我继续看 the libstdc++ version,这个确实使用了模板(因此要长很多)。

template<contiguous_iterator _It>
requires __is_compatible_ref<iter_reference_t<_It>>::value
constexpr explicit(extent != dynamic_extent)
span(_It __first, size_type __count)
noexcept
: _M_extent(__count), _M_ptr(std::to_address(__first))
{
  if constexpr (_Extent != dynamic_extent)
    {
      __glibcxx_assert(__count == _Extent);
    }
}

template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
requires __is_compatible_ref<iter_reference_t<_It>>::value
  && (!is_convertible_v<_End, size_type>)
constexpr explicit(extent != dynamic_extent)
span(_It __first, _End __last)
noexcept(noexcept(__last - __first))
: _M_extent(static_cast<size_type>(__last - __first)),
  _M_ptr(std::to_address(__first))
{
  if constexpr (_Extent != dynamic_extent)
    {
      __glibcxx_assert((__last - __first) == _Extent);
    }
}

现在cppreference页面上提到这两个构造函数只有在It满足contiguous_iterator的情况下才参与重载决议,如果转换从std::iter_reference_t<It>element_type顶多是一个限定转换。为了满足这一点,libstdc++ 代码使用 contiguous_iterator 概念作为模板类型名 (defined here) and the __is_compatible_ref requirement (defined just above).

所以,我的问题是:直接使用pointer类型,不乱概念和需求,真的符合标准吗? libcxx 代码是否正确而 libstdc++ 代码过于复杂?

我还想将问题扩展到接下来的三个构造函数(处理原始数组和 std::array,cppreference 上的编号 4、5 和 6)。

你提到的std::span的iterator-constructor是在P1394R4. According to libc++ C++2a Status中提出的,这篇论文还没有在libc++中实现。

libc++ 实现 P0122R7,其中有指针构造函数(由 P1394R4 中的迭代器构造函数替换)。


P1872R0也有关系:span应该有size_type,而不是index_type.

is using the pointer type directly, ... actually conforming to the standard?

不,这样的构造函数不足以提供模板迭代器构造函数。引用/链接的 libc++ 实现不符合即将发布的标准。

libstdc++ 模板构造函数符合要求。