c++ - 为什么span的数组和std::array构造函数与其容器构造函数不同

标签 c++ c++20 std-span

我一直在使用 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)实际上在任何这些情况下都不依赖,因此约束条件很容易得到满足。我们只需要制作这些模板即可。

关于c++ - 为什么span的数组和std::array构造函数与其容器构造函数不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57444188/

相关文章:

c++ - 通过 IIS 应用程序池 w3wp.exe 调用 COM DLL 时未调用 DLL_THREAD_ATTACH

c++ - 在 C++ 中获取总内存和可用内存

c++ - Visual Studio 是否发出错误的汇编代码?

c++ - 带数组的聚合模板的模板参数推导

c++ - 如何在 C++ 中双向循环迭代 4 个枚举类值?

c++ - 什么是 "span",我应该什么时候使用?

c++ - 重载模板函数,根据模板参数具有不同的返回类型

c++ - 使用 lambda 默认构造的 std::priority_queue

c++ - std::span 迭代器能否比创建它们的 span 对象更长寿?

c++ - std::span 中 std::dynamic_extent 的用途是什么