c++ - 为什么在具有静态范围的 std::span 中不允许默认构造?

标签 c++ c++20

看看这个例子:

#include <span>
#include <vector>

class Data
{
public:
    Data() = default;
  
    template<class R>
    explicit Data(R& r)
        : buf_(r) 
        , header_(buf_.first<4>())
    {}

private:
    std::span<char> buf_;

    // compile error
    // std::span<char, 4> header_;

    // compiles but ill-formed (against the precondition of [span.sub])
    std::span<char, 4> header_{buf_.first<4>()};
};

int main()
{
    std::vector<char> buf(1234);
    Data data{buf};
}
编译错误的原因是标准[span.cons]中明确禁止:
constexpr span() noexcept;

Constraints: Extent == dynamic_­extent || Extent == 0 is true.
Postconditions: size() == 0 && data() == nullptr.


为什么会存在这个约束?
由于 dynamic_extent 的跨度的默认构造已经允许,感觉这两种情况在语义上是相同的:
std::span<char> header_; // allowed
std::span<char, 4> header_; // why disallowed?
此外,看看[span.obs]的措辞:
constexpr size_type size() const noexcept;

Effects: Equivalent to: return size_­;


例如,标准甚至可以定义更严格的实现细节以鼓励静态优化。如果这个措辞类似于 Returns Extent when Extent != dynamic_extent , size_数据成员可以在运行时省略。如果是这样,我知道默认构造是无效的,因为在这种情况下 size()将始终返回无效大小,即 Extent ,不为零。
但是,当前标准在类定义中公开了非静态成员变量 [span.overview] :
  private:
    pointer data_;              // exposition only
    size_type size_;            // exposition only
既然我们已经有了这些变量,标准库就不能设置data_ = nullptr吗?和 size_ = 0当静态大小的跨度是默认构造的?我当然可以接受当前的措辞,但是当前的标准是不是期望有太强的限制?
请注意,委员会曾经尝试修复 LWG3198 中的 [span.cons]。 ,所以我很确定他们对当前的措辞有一些理由。

最佳答案

默认构建的 std::span<T>成功引用了 T 类型的 0 个对象从 nullptr 开始.对什么 3 个对象类型 T是否std::span<T,3>()引用?size_成员始终在场纯粹是一种简化规范的叙述手段;对于静态范围跨度,它没有任何意义,并且在实践中确实不存在。

关于c++ - 为什么在具有静态范围的 std::span 中不允许默认构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66809280/

相关文章:

c++ - 将 CfbsBitmap 格式转换为 JPG

c++ - 可选的仅 header 库

c++ - thread_local 变量的实例是否保证由访问它们的线程初始化?

C++20 std::ranges:范围适配器跳过每个第 n 个元素

c++ - 将 std::ranges::view 类型对象传递给类的正确方法是什么?

c++ - 通过 unsigned char[] 创建隐式对象 - reinterpret_cast 为隐式对象是否合法? (P0593)

c++ - 为什么 std::begin 使用尾随返回类型语法?

c++ - Bag of Features 如何运作?

c++ - 使用 Char 数组的 ROT13 实现

c++ - 为什么在使用 `std::views::reverse` 时对过滤函数进行了多余的调用?