Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is default construction disallowed in std::span with static extent?

Tags:

c++

c++20

Take a look at this example:

#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};
}

The reason of compile error is because it is explicitly disallowed in the standard [span.cons]:

constexpr span() noexcept;

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

Why does this constraint exist?

Since default construction for a span with dynamic_extent is already allowed, it feels like these two cases are semantically same:

std::span<char> header_; // allowed
std::span<char, 4> header_; // why disallowed?

Furthermore, take a look at the wording of [span.obs]:

constexpr size_type size() const noexcept;

Effects: Equivalent to: return size_­;

Let's say for example, the standard could even define stricter implementation details to encourage static optimization. If this wording was something like Returns Extent when Extent != dynamic_extent, the size_ data member can be omitted in runtime. If so, I understand that the default construction is invalid, because in that case size() will always return invalid size, i.e. Extent, which is not zero.

However, current standard exposes the non-static member variables in the class definition [span.overview]:

  private:
    pointer data_;              // exposition only
    size_type size_;            // exposition only

Since we already have those variables, can't the standard library just set data_ = nullptr and size_ = 0 when statically sized span is default constructed? I surely can live with the current wording, but isn't the current standard expecting too strong constraints?

Note that the committee have once attempted to fix [span.cons] already in LWG3198, so I'm pretty sure that they have some rationale for current wording.

like image 452
saki7 Avatar asked Oct 20 '25 13:10

saki7


1 Answers

A default-constructed std::span<T> successfully refers to 0 objects of type T starting at nullptr. To what 3 objects of type T does std::span<T,3>() refer?

The size_ member always being present is purely a narrative device to simplify the specification; it means nothing and really isn’t there in practice for static-extent spans.

like image 200
Davis Herring Avatar answered Oct 23 '25 03:10

Davis Herring



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!