【问题标题】:std::span constructor, libcxx vs libstdc++, template vs non-template?std::span 构造函数,libcxx 与 libstdc++,模板与非模板?
【发布时间】:2020-05-19 12:31:40
【问题描述】:

漫步the code of libcxx's std::span,我注意到前两个值构造函数(cppreference 上的数字 2 和 3)不是模板。

_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)"); }

它们直接使用 pointer 类型,而不是 cppreference 页面上显示的模板类型 ItEnd。所以我想知道 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&lt;It&gt;element_type 的转换最多时才参与重载解析资格转换。为了满足这一点,libstdc++ 代码使用 contiguous_iterator 概念作为模板类型名 (defined here) 和 __is_compatible_ref 要求 (defined just above)。

所以,这里是我的问题:是直接使用pointer类型,而不是混淆概念和要求,实际上符合标准吗? libcxx 代码是否正确,而 libstdc++ 代码是否过于复杂?

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

【问题讨论】:

  • 您知道 C++20 目前正在开发中吗?比如p0122r5指定了libc++实现的构造函数(constexpr span(pointer ptr, index_type count); ),所以看起来libc++没有完全更新到最新的草稿版本。
  • libcxx 代码对我来说似乎不完整。 constexpr span(pointer __f, pointer __l) 是不够的,例如,如果我将一对迭代器传递给一个向量。我想知道他们是否还没有完成实施。
  • @DanielLangr TBF,C++20 完成。 AFAIK 它只是通过最后的官僚和编辑步骤,所以现在什么都不会改变。
  • @NathanOliver 公平点。
  • 标准可能已经完成,但实施仍在开发中,有些可能是从旧的不同版本开始的一段时间

标签: c++ language-lawyer std c++20


【解决方案1】:

您提到的std::span 的迭代器构造函数是在P1394R4 中提出的。根据libc++ C++2a Status的说法,本文尚未在libc++中实现。

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


P1872R0 也是相关的:span 应该有 size_type,而不是 index_type

【讨论】:

    【解决方案2】:

    是直接使用指针类型,……居然符合标准?

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

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

    【讨论】:

      猜你喜欢
      • 2016-11-27
      • 2011-05-24
      • 1970-01-01
      • 2020-09-04
      • 1970-01-01
      • 2013-08-26
      • 2014-01-09
      • 2016-07-02
      • 2023-01-30
      相关资源
      最近更新 更多